![](/img/trans.png)
[英]How to test Controller that returns Mono<ResponseEntity<Void>>?
[英]How to set response status code in Filter when controller returns ResponseEntity?
我正在開發一個帶有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);
}
如果控制器返回字符串,則一切按預期進行(狀態為201)。 但是,如果控制器返回一個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
如文檔所述, ResponseEntity#ok
返回HTTP OK( https://httpstatuses.com/200 )狀態代碼。 篩選器較早運行,因此以后將覆蓋狀態。
您應該使用https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html中描述的其他方法創建ResponseEntity
。
使用/string
端點,您無需修改狀態代碼。 使用/entity
端點,您將明確地處於(通過返回ok將其設置為200)。
您的過濾器實現更改響應狀態代碼, 然后繼續運行其余的過濾器鏈- 然后運行servlet 。 並且我們剛剛建立了servlet(您的控制器)將響應狀態代碼設置為其他內容。
因此,您需要在servlet /控制器完成其工作后更改響應代碼。
您首先想到的是重新實現過濾器,如下所示:
@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);
}
}
}
但是不幸的是,那也不行! 根據文檔 :
請注意,對於@ResponseBody和ResponseEntity方法,postHandle的用處不大,在HandlerAdapter內以及postHandle之前,將其寫入並提交響應。 這意味着對響應進行任何更改為時已晚,例如添加額外的標頭。 對於這種情況,您可以實現ResponseBodyAdvice並將其聲明為Controller Advice Bean或直接在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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.