[英]RestTemplate Interceptor
I'm currently trying to incorporate a HandlerInterceptorAdapter
but it's not getting registered and comparing it to other answers is tough because everyone is using something different. 我目前正在尝试合并一个HandlerInterceptorAdapter
但它没有注册,并且将其与其他答案进行比较很难,因为每个人都在使用不同的东西。 And I'm aware WebMvcConfigureAdapter is deprecated, some versioning is beyond my control for the scope of the project, see usage specs below. 我知道WebMvcConfigureAdapter已被弃用,某些版本控制超出了我对项目范围的控制,请参阅下面的使用规范。
Can someone please provide some guidance on incorporating interceptors with a RestTemplate (that's not ClientHttpRequestInterceptor). 有人可以提供一些关于将拦截器与RestTemplate(不是ClientHttpRequestInterceptor)合并的指导。
Main: 主要:
@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;
}
}
Interceptor : com.example.foo.config.request.interceptor 拦截器: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 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());
}
}
"Adding interceptor" does get logged so I know the configs are being scanned. “添加拦截器”确实被记录,因此我知道正在扫描配置。 I just can't get any interceptor logic to log. 我只是无法获取任何拦截器逻辑来记录。
Using: 使用:
HandlerInterceptorAdapter
is an implementation that applies to @Controller
or @RestController
. HandlerInterceptorAdapter
是一个适用于@Controller
或@RestController
。 Not an implementation for RestTemplete
. 不是RestTemplete
的实现。
To apply it to RestTemplete
, you need to use ClientHttpRequestInterceptor
. 要将其应用于RestTemplete
,您需要使用ClientHttpRequestInterceptor
。
ex. 恩。
@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;
}
}
RestTemplate expects ClientHttpRequestInterceptor RestTemplate需要ClientHttpRequestInterceptor
setInterceptors(List<ClientHttpRequestInterceptor> interceptors)
Set the request interceptors that this accessor should use. 设置此访问者应使用的请求拦截器。
You can use Servlet Filter to "intercept" requests/response, 您可以使用Servlet过滤器 “拦截”请求/响应,
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response;
implement this with a servlet filter. 用servlet过滤器实现这个。 No Spring involved here at all 这里根本没有春天
But you will have to change RestTemplate to using other framework as jersey 但是你必须将RestTemplate改为使用其他框架作为泽西
Jersey gives a very handy implementation of such as filter called LoggingFilter which can help in logging all kinds of incoming and outgoing traffic. Jersey提供了一个非常方便的实现,例如名为LoggingFilter的过滤器,它可以帮助记录各种传入和传出流量。
As @WonChulHeo noted you can't use HandlerInterceptorAdapter
with RestTemplate
. 正如@WonChulHeo所指出的,你不能将HandlerInterceptorAdapter
与RestTemplate
一起RestTemplate
。 Only ClientHttpRequestInterceptor
. 只有ClientHttpRequestInterceptor
。 It's not clear why do you need exactly HandlerInterceptorAdapter
- we can only see that you are trying to log the fact of the request interception. 目前尚不清楚为什么你需要完全HandlerInterceptorAdapter
- 我们只能看到你正在尝试记录请求拦截的事实。 And ClientHttpRequestInterceptor
is absolutely able to do the same and even more - check my working example bellow. 而ClientHttpRequestInterceptor
绝对能够做到同样甚至更多 - 请查看我的工作示例。
PS There is an error in your code - you can't use private
access for @Bean
methods - check your private RestTemplate restTemplate() {
please... PS您的代码中存在错误 - 您无法对@Bean
方法使用private
访问 - 请检查您的private RestTemplate restTemplate() {
please ...
@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;
}
The HandlerInterceptorAdapter
is for the server side (ie RestController) to intercept some important events when server processes a HTTP request , it is nothing to do with what HTTP client (eg RestTemplate
) is used. HandlerInterceptorAdapter
用于服务器端(即RestController)在服务器处理HTTP请求时拦截一些重要事件,它与使用什么HTTP客户端(例如RestTemplate
) RestTemplate
。
If you want to use RestTemplate
as a HTTP client and want to intercept the request just before it sent out and the response just after it received , you must use ClientHttpRequestInterceptor
. 如果要将RestTemplate
用作HTTP客户端,并希望在发出请求之前拦截请求,并在收到响应之后立即拦截,则必须使用ClientHttpRequestInterceptor
。
I'm trying to intercept requests and responses in a more flexible way than ClientHttpRequestInterceptor. 我试图以比ClientHttpRequestInterceptor更灵活的方式拦截请求和响应。
From your comment above , what is your actual use-cases that it cannot handle ? 从您上面的评论中,您无法处理的实际用例是什么? I think ClientHttpRequestInterceptor
is already quite flexible enough to implement any complex logic to intercept request and response. 我认为ClientHttpRequestInterceptor
已经足够灵活,可以实现任何复杂的逻辑来拦截请求和响应。 As your question does not provide any information about how you need to intercept , I can only give a general example to show what the ClientHttpRequestInterceptor
can offer . 由于您的问题没有提供有关如何拦截的任何信息,我只能举一个例子来说明ClientHttpRequestInterceptor
可以提供什么。
To configure the RestTemplate to use an interceptor : 要配置RestTemplate以使用拦截器:
RestTemplate rt = new RestTemplate();
List<ClientHttpRequestInterceptor> interceptors= new ArrayList<ClientHttpRequestInterceptor>();
inteceptors.add(new MyClientHttpRequestInterceptor());
And the ClientHttpRequestInterceptor looks like: 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;
}
}
Please note that you can also configure a chain of ClientHttpRequestInterceptor
which allows to split some complex request and response intercept logic into many smalls and reusable ClientHttpRequestInterceptor
. 请注意,您还可以配置ClientHttpRequestInterceptor
链,该链允许将一些复杂的请求和响应拦截逻辑拆分为许多ClientHttpRequestInterceptor
和可重用的ClientHttpRequestInterceptor
。 It is designed with the Chain of responsibility design pattern which its API experience is very similar to what Filter#doFilter()
in Servlet
. 它采用责任链设计模式设计,其API体验与Servlet
Filter#doFilter()
非常相似。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.