現在、HandlerInterceptorAdapter
を組み込もうとしていますが、登録されておらず、他の回答と比較するのは難しいです。そして、私はWebMvcConfigureAdapterが非推奨であることを知っています。一部のバージョン管理は、プロジェクトの範囲を制御できないため、以下の使用法の仕様を参照してください。
誰かがRestTemplateにインターセプターを組み込むことに関するガイダンスを提供していただけますか(これはClientHttpRequestInterceptorではありません)。
メイン:
@SpringBootApplication
@EnableRetry
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
return applicationBuilder.sources(Application.class);
}
@Bean
private RestTemplate restTemplate(){
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("redacted", 8080));
SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
simpleClientHttpRequestFactory.setProxy(proxy);
simpleClientHttpRequestFactory.setOutputStreaming(false);
RestTemplate template = new RestTemplate();
template.setErrorHandler(new MyResponseErrorHandler());
return template;
}
}
インターセプター:com.example.foo.config.request.interceptor
@Component
public class MyInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("INTERCEPTED");
return super.preHandle(request, response, handler);
}
}
InterceptorConfig:com.example.foo.config.request.interceptor
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
@Bean
MyInterceptor myInterceptor() {
return new MyInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
System.out.println("Adding interceptor");
registry.addInterceptor(myInterceptor());
}
}
「インターセプターの追加」はログに記録されるため、構成がスキャンされていることがわかります。インターセプターロジックをログに記録できません。
使用:
HandlerInterceptorAdapter
は、@Controller
または@RestController
に適用される実装です。 RestTemplete
の実装ではありません。
RestTemplete
に適用するには、ClientHttpRequestInterceptor
を使用する必要があります。
例。
@Component
public class CustomInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
// ...
}
}
@Configuation
public class RestTempleteConfig {
// ...
@Autowired
private CustomInterceptor customInterceptor;
@Bean
public RestTemplate restTemplate(){
RestTemplate template = new RestTemplate();
List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
template.add(customInterceptor);
return template;
}
}
@WonChulHeoが指摘したように、HandlerInterceptorAdapter
をRestTemplate
とともに使用することはできません。 ClientHttpRequestInterceptor
のみ。なぜ正確にHandlerInterceptorAdapter
が必要なのかは明確ではありません。リクエストのインターセプトの事実をログに記録しようとしていることがわかります。そして、ClientHttpRequestInterceptor
は同じことを完全に行うことができます-以下の私の動作例を確認してください。
追伸コードにエラーがあります-_@Bean
_メソッドにprivate
アクセスを使用することはできません-private RestTemplate restTemplate() {
を確認してください...
_@Slf4j
@RestController
@SpringBootApplication
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
}
@GetMapping("/users/{id}")
public User get(@PathVariable int id) {
log.info("[i] Controller: received request GET /users/{}", id);
return new User(id, "John Smith");
}
@Bean
public RestTemplate restTemplate(RestTemplateBuilder templateBuilder) {
ClientHttpRequestFactory requestFactory = new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
return templateBuilder
.interceptors((request, bytes, execution) -> {
URI uri = request.getURI();
HttpMethod method = request.getMethod();
log.info("[i] Interceptor: requested {} {}", method, uri);
log.info("[i] Interceptor: request headers {}", request.getHeaders());
ClientHttpRequest delegate = requestFactory.createRequest(uri, method);
request.getHeaders().forEach((header, values) -> delegate.getHeaders().put(header, values));
ClientHttpResponse response = delegate.execute();
log.info("[i] Interceptor: response status: {}", response.getStatusCode().name());
log.info("[i] Interceptor: response headers: {}", response.getHeaders());
String body = StreamUtils.copyToString(response.getBody(), Charset.defaultCharset());
log.info("[i] Interceptor: response body: '{}'", body);
return response;
})
.rootUri("http://localhost:8080")
.build();
}
@Bean
ApplicationRunner run(RestTemplate restTemplate) {
return args -> {
ResponseEntity<User> response = restTemplate.getForEntity("/users/{id}", User.class, 1);
if (response.getStatusCode().is2xxSuccessful()) {
log.info("[i] User: {}", response.getBody());
} else {
log.error("[!] Error: {}", response.getStatusCode());
}
};
}
}
_
_@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
}
_
HandlerInterceptorAdapter
は、サーバー側(つまりRestController)がサーバーがHTTPリクエストを処理するときにいくつかの重要なイベントをインターセプトするためのもので、使用されるHTTPクライアント(例:RestTemplate
)とは関係ありません。
RestTemplate
をHTTPクライアントとして使用し、送信直前のリクエストと受信直後の応答をインターセプトする場合は、ClientHttpRequestInterceptor
を使用する必要があります。
ClientHttpRequestInterceptorよりも柔軟な方法でリクエストとレスポンスをインターセプトしようとしています。
上記のコメントから、それが処理できない実際のユースケースは何ですか? ClientHttpRequestInterceptor
は、要求と応答をインターセプトするための複雑なロジックを実装するのに十分な柔軟性を備えていると思います。あなたの質問はあなたがどのように傍受する必要があるかについての情報を提供していませんので、私はClientHttpRequestInterceptor
が何を提供できるかを示すための一般的な例しか提示できません。
インターセプターを使用するようにRestTemplateを構成するには:
_RestTemplate rt = new RestTemplate();
List<ClientHttpRequestInterceptor> interceptors= new ArrayList<ClientHttpRequestInterceptor>();
inteceptors.add(new MyClientHttpRequestInterceptor());
_
そして、ClientHttpRequestInterceptorは次のようになります。
_public class MyClientHttpRequestInterceptor implements ClientHttpRequestInterceptor{
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
//The HTTP request and its body are intercepted here which you can log them or modify them. e.g.
System.out.println("Log the HTTP request header: " + request.getHeaders());
//Modify the HTTP request header....
request.getHeaders().add("foo", "fooValue");
//Throw exception if you do not want to send the HTTP request
//If it is at the end of the interceptor chain , call execution.execute() to confirm sending the HTTP request will return the response in ClientHttpResponse
//Otherwise, it will pass the request to the next interceptor in the chain to process
ClientHttpResponse response= execution.execute(request, body);
//The HTTP response is intercepted here which you can log them or modify them.e.g.
System.out.println("Log the HTTP response header: " + response.getHeaders());
//Modify the HTTP response header
response.getHeaders().add("bar", "barValue");
return response;
}
}
_
ClientHttpRequestInterceptor
のチェーンを構成することもできます。これにより、いくつかの複雑な要求および応答インターセプトロジックを多数の小さな再利用可能なClientHttpRequestInterceptor
に分割できます。 責任の連鎖 の設計パターンで設計されており、そのAPIエクスペリエンスはServlet
のFilter#doFilter()
と非常によく似ています。