在我的Spring Boot应用程序中,我遇到了一个奇怪的问题。我有一个GET REST端点,它返回一个POJO,如下所示:
@GetMapping(value = "/dto", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ReportDto> dto() {
MultiValueMap<String, String> headers = new HttpHeaders();
headers.add("Controller processed time",LocalDateTime.now().toString());
return new ResponseEntity<ReportDto>(new ReportDto(), headers, HttpStatus.OK);
}
我有一个拦截器,看起来像:
@Slf4j
@Component
public class AuditInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion
(HttpServletRequest request, HttpServletResponse response, Object
handler, Exception exception) throws Exception {
Thread.sleep(10000);
log.info((LocalDateTime.now())+" : Audit event stored");
response.setHeader("Audit event written time",LocalDateTime.now().toString());
}
Thread.sleep(10000)用于模拟我们周期性地从审计事件存储中面临的延迟。
按照设计,审计事件应该在响应提交之后写入,这是为了避免在写入事件延迟的情况下客户端的延迟。
令人惊讶的是,客户端仅在10秒后才收到响应(增加的延迟),这意味着响应在执行"afterCompletion"方法之后提交。当响应类型为String时,响应在执行afterCompletion之前提交。我尝试过响应类型Integer、boolean和int。除了String之外,所有其他类型(我尝试过的类型)只有在afterCompletion执行之后才被写入。
我试过不同的客户,他们的行为分别是:
- Reactwithaxios(同步和异步)-在增加的延迟之后接收响应主体和代码
- Postman -立即收到响应代码200,但正文是在增加的延迟之后收到的
- curl-立即打印响应,但连接仅在增加的延迟后关闭
从curl中观察到的行为可以清楚地看出,延迟并不在Http消息转换器中(Spring Boot中默认为Jackson)。
我的问题有一个变通解决方案,如下所示:
@GetMapping(value = "/custom", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> custom() throws JsonProcessingException {
MultiValueMap<String, String> headers = new HttpHeaders();
headers.add("Controller processed time",LocalDateTime.now().toString());
ObjectMapper objectMapper = new ObjectMapper();
return new ResponseEntity<String>(objectMapper.writeValueAsString(new ReportDto()), headers,
HttpStatus.OK);
}
我更希望有正确的解决方案来解决我的问题。感谢任何人能帮助我了解根本原因,以便我们能拿出正确的解决方案。
谢谢你。
1条答案
按热度按时间nkhmeac61#
我相信拦截器是在请求处理程序中调用的,所以如果您想花很多时间,最好在单独的线程或线程池中进行。
同样,如果你想设置响应头,在
postHandle
中进行,当afterCompletion
被调用时,响应已经被提交了。