gpt4 book ai didi

java - 实现 Spring 拦截器

转载 作者:搜寻专家 更新时间:2023-10-31 19:59:27 25 4
gpt4 key购买 nike

我想实现 Spring 拦截器以便打印每个接收和发送的 API XML 请求。我试过这个测试代码:

@SpringBootApplication
@EntityScan(".....")
public class Application extends SpringBootServletInitializer implements WebMvcConfigurer {

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();

List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();

// check if restTeamplate doesn't already have other interceptors
if (CollectionUtils.isEmpty(interceptors)) {
interceptors = new ArrayList<>();
}

interceptors.add(new RestTemplateHeaderModifierInterceptor());
restTemplate.setInterceptors(interceptors);
return restTemplate;
}

@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new RestTemplateHeaderModifierInterceptor());
}
};
}
}

记录组件:

import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.WebRequestInterceptor;
import org.springframework.web.servlet.HandlerInterceptor;

import io.micrometer.core.instrument.util.IOUtils;

@Component
public class RestTemplateHeaderModifierInterceptor implements ClientHttpRequestInterceptor, HandlerInterceptor {

private static final Logger LOGGER = LoggerFactory.getLogger(HomeController.class);

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {

StringBuilder sb = new StringBuilder();
sb.append("[ ");
for (byte b : body) {
sb.append(String.format("0x%02X ", b));
}
sb.append("]");

LOGGER.debug("!!!!!!!!!!!!!!! Input " + sb.toString());

System.out.println("!!!!!!!!!!!!!!!");

ClientHttpResponse response = execution.execute(request, body);
InputStream inputStream = response.getBody();
String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

LOGGER.debug("!!!!!!!!!!!!!!! result " + result);

System.out.println("!!!!!!!!!!!!!!!");

return response;
}

}

但是在 DEBUG 模式下没有任何内容打印到控制台。知道我哪里错了吗?可能这个组件没有注册或者我缺少一些重要的配置?

最佳答案

根据您的代码,您在 RestTemplate 中注册了一个空的拦截器列表。尝试按如下方式更改您的代码:

@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();

List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();

// check if restTeamplate doesn't already have other interceptors
if (CollectionUtils.isEmpty(interceptors)) {
interceptors = new ArrayList<>();
}

interceptors.add(new RestTemplateHeaderModifierInterceptor());
restTemplate.setInterceptors(interceptors);
return restTemplate;
}

更多信息是 here .

该拦截器将服务于传出 请求。

对于income 请求,您必须从HandlerInterceptorAdapter 继承您的拦截器:

public class MyIncomeRequestInterceptor extends HandlerInterceptorAdapter {
//...
}

然后用WebMvcConfigurer注册,例如:

@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyIncomeRequestInterceptor());
}
};
}

更多信息是 here .

在这两种情况下,都没有必要从拦截器中创建 bean(您可以删除注释 @Component)。

更新

一个工作示例:

@Slf4j
@RestController
@ControllerAdvice
@SpringBootApplication
public class Application implements WebMvcConfigurer, ResponseBodyAdvice<Object> {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@GetMapping("/hello")
public ResponseEntity<?> hello() {
return ResponseEntity.ok(Map.of("message", "hello"));
}

@EventListener
public void onReady(final ApplicationReadyEvent e) {
Map result = restTemplate().getForObject("http://localhost:8080/hello", Map.class);
if (result != null) {
log.info("[i] Request result: '{}'", result.get("message"));
}
}

@Bean
public RestTemplate restTemplate() {

ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
RestTemplate restTemplate = new RestTemplate(factory);

var interceptors = restTemplate.getInterceptors();
if (CollectionUtils.isEmpty(interceptors)) interceptors = new ArrayList<>();

interceptors.add(new OutgoingInterceptor());
restTemplate.setInterceptors(interceptors);
return restTemplate;
}

@Override
public void addInterceptors(final InterceptorRegistry registry) {
registry.addInterceptor(new IncomingInterceptor());
}

@Override
public boolean supports(final MethodParameter returnType, final Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}

@Override
public Object beforeBodyWrite(final Object body, final MethodParameter returnType, final MediaType selectedContentType, final Class<? extends HttpMessageConverter<?>> selectedConverterType, final ServerHttpRequest request, final ServerHttpResponse response) {
log.info("[i] ResponseBodyAdvice: response body {}", body);
return body;
}

class OutgoingInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] bytes, final ClientHttpRequestExecution execution) throws IOException {
log.info("[i] Outgoing interceptor: requested URL is '{}'", request.getURI());
ClientHttpResponse response = execution.execute(request, bytes);
String body = StreamUtils.copyToString(response.getBody(), Charset.defaultCharset());
log.info("[i] Outgoing interceptor: response body is '{}'", body);
return response;
}
}

class IncomingInterceptor implements HandlerInterceptor {
@Override
public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final ModelAndView mw) throws Exception {
log.info("[i] Incoming interceptor: requested URL is '{}'", request.getRequestURL().toString());
}
}
}

要记录 Controller IMO 的每个方法的响应主体,最好使用带有 @ControllerAdvice 注释的 ResponseBodyAdvice 实现(参见上面的代码)。

结果:

2019-01-16 14:05:07.260  : [i] Outgoing interceptor: requested URL is 'http://localhost:8080/hello'
2019-01-16 14:05:07.366 : [i] ResponseBodyAdvice: response body {message=hello}
2019-01-16 14:05:07.383 : [i] Incoming interceptor: requested URL is 'http://localhost:8080/hello'
2019-01-16 14:05:07.387 : [i] Outgoing interceptor: response body is '{"message":"hello"}'
2019-01-16 14:05:07.402 : [i] Request result: 'hello'

repo :sb-web-interceptors-demo

关于java - 实现 Spring 拦截器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53469186/

25 4 0
文章推荐: java - Scala List[Int] 在 Java 中变成 List