gpt4 book ai didi

java - 当 Controller 返回ResponseEntity时,如何在Filter中设置响应状态代码?

转载 作者:太空宇宙 更新时间:2023-11-04 09:45:58 25 4
gpt4 key购买 nike

我正在开发一个带有 servlet 过滤器的简单 Spring Boot 应用程序,旨在设置响应状态代码:

@Component
public class TestFilter implements Filter {

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {

HttpServletResponse response = (HttpServletResponse) resp;
response.setStatus(201);
chain.doFilter(req, resp);
}

如果 Controller 返回一个字符串,一切都会按预期进行(状态为 201)。但是如果 Controller 返回一个 ResponseEntity,那么调用 doFilter() 后状态码是 200 而不是 201:

@RestController
public class TestController {

@GetMapping("/string")
public String testString() {
return "OK"; // status code is 201 as set by Filter
}
}

@RestController
public class TestController {

@GetMapping("/entity")
public ResponseEntity<String> testResponseEntity() {
return ResponseEntity.ok("OK"); // status code is 200
}
}

为什么过滤器在使用 ResponseEntity 时不更改状态代码?

--

Github 上的项目:https://github.com/timofeev-denis/set-status-code

最佳答案

使用 /string 端点,您不会修改状态代码。使用 /entity 端点,您明确地是(您通过返回 ok 将其设置为 200)。

您的过滤器实现会更改响应状态代码,然后然后继续运行过滤器链的其余部分 - 以及 then the servlet 。我们刚刚建立的 servlet(您的 Controller )正在将响应状态代码设置为其他内容。

因此,您需要在 Servlet/ Controller 完成其操作后更改响应代码。

您的第一个想法可能是像这样重新实现您的过滤器:

@Component
public class TestFilter implements Filter {

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(req, resp);
} finally {
HttpServletResponse response = (HttpServletResponse) resp;

response.setStatus(205);
}
}
}

但不幸的是,这也行不通!根据documentation :

Note that postHandle is less useful with @ResponseBody and ResponseEntity methods for which the response is written and committed within the HandlerAdapter and before postHandle. That means it is too late to make any changes to the response, such as adding an extra header. For such scenarios, you can implement ResponseBodyAdvice and either declare it as an Controller Advice bean or configure it directly on RequestMappingHandlerAdapter.

这可能会达到您想要的效果(请注意,我设置为“CHECKPOINT”只是为了演示这一点!):

@ControllerAdvice
public class TestResponseBodyAdvice<T> implements ResponseBodyAdvice<T> {

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

@Override
public T beforeBodyWrite(T body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
//
// insert status code of choice here
response.setStatusCode(HttpStatus.CHECKPOINT);

return body;
}

}

关于java - 当 Controller 返回ResponseEntity时,如何在Filter中设置响应状态代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55423580/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com