当执行返回类型为Unit的方法时,我希望弹簧将204 NO CONTENT放在响应的状态代码上,但是它总是返回200 OK。有什么办法可以在全球范围内改变这种行为?我不想向每个Unit方法添加ResponseStatus批注。
@RestController()
@RequestMapping("/{role:(?:veterinarian\\b|admin\\b)}")
class EmployeeController(
private val userService: UserService
) {
@PostMapping(consumes = [MediaType.APPLICATION_JSON_UTF8_VALUE])
fun hire(@RequestBody employeeDTO: EmployeeDTO, @PathVariable role: String): Unit {
if (employeeDTO.user_role != role)
throw ResponseStatusException(HttpStatus.BAD_REQUEST)
else
userService.addNewUser(EmployeeDAO.build(employeeDTO))
}
}
更新:
我最终使用过滤器来检查状态响应为200 OK时内容类型是否未定义,并且似乎可以正常工作。
这是过滤器代码
@Component
public class NoContentFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(httpServletRequest, httpServletResponse);
if (httpServletResponse.getContentType() == null ||
httpServletResponse.getContentType().equals("")) {
if ( httpServletResponse.getStatus() == 200 ) {
httpServletResponse.setStatus(HttpStatus.NO_CONTENT.value());
}
}
}
}
答案 0 :(得分:0)
Spring允许通过@ControllerAdvice配置控制器的全局行为
使用@ControllerAdvice注释的类可以包含@ ExceptionHandler,@ InitBinder和@ModelAttribute注释的方法,并且这些方法将应用于所有控制器层次结构中的@RequestMapping方法,而不是声明它们的控制器层次结构。
通常,我们使用它来@ExceptionHandler
全局处理异常,但情况并非如此。 (也{@InitBinder
,@ModelAttribute
)
有ResponseBodyAdvice
,但没有ResponseStatusAdvice
因此没有直接解决方案
解决方法:
这是一个非常肮脏的黑客,我真的建议您每次都使用@ResponseStatus,但是如果您确实想在全球范围内解决该问题,那么:
您可以将错误处理与ResponseBodyAdvice结合在一起
您应该创建一个异常类
class NoContentException: RuntimeException()
为其创建处理程序。应该在@ControllerAdvice
之后调用它,它将抛出NoContentException,因此它具有@Order(1)
@ControllerAdvice
@Order(1)
class NoContentErrorHandler {
@ExceptionHandler(NoContentException::class)
fun handleNoContent() = ResponseEntity.noContent().build<Unit>()
}
,最后创建一个响应主体建议,该建议会引发实际的异常:
@ControllerAdvice
@Order(0)
class ThrowingNoContentExceptionResponseBodyAdvice : ResponseBodyAdvice<Unit> {
override fun supports(returnType: MethodParameter, converterType: Class<out HttpMessageConverter<*>>): Boolean {
return returnType.parameterType == Void.TYPE
}
override fun beforeBodyWrite(
body: Unit?,
returnType: MethodParameter,
selectedContentType: MediaType,
selectedConverterType: Class<out HttpMessageConverter<*>>,
request: ServerHttpRequest,
response: ServerHttpResponse
): Unit? {
throw NoContentException()
}
}
因此它的工作方式如下: request->具有Unit response调用的方法->引发异常的建议->处理异常并将其转换为NO_CONTENT状态的建议