拦截缺少标头的@RequestHeader异常

Rus*_*mov 6 java spring servlets spring-mvc

我在控制器中有一个方法,例如有参数

@RequestMapping(value = "/{blabla}", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public void post(@RequestHeader("ETag") int etag)
Run Code Online (Sandbox Code Playgroud)

如果请求中没有ETag标头 - 客户端获得400(BAD_REQUEST),这不是任何信息.我需要以某种方式处理此异常并将我自己的异常发送到客户端(我为此目的使用JSON).我知道我可以通过@ExceptionHandler拦截异常,但在这种情况下,所有HTTP 400请求都将被处理,但我希望在标题中缺少ETag.有任何想法吗?

小智 12

您还可以通过使用@ControllerAdvicespring 中的注释来实现这一点。

@ControllerAdvice
public class ExceptionHandler extends ResponseEntityExceptionHandler{

    /**
     * Handle ServletRequestBindingException. Triggered when a 'required' request
     * header parameter is missing.
     *
     * @param ex      ServletRequestBindingException
     * @param headers HttpHeaders
     * @param status  HttpStatus
     * @param request WebRequest
     * @return the ResponseEntity object
     */
    @Override
    protected ResponseEntity<Object> handleServletRequestBindingException(ServletRequestBindingException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
        return new ResponseEntity<>(ex.getMessage(), headers, status);
    }

}
Run Code Online (Sandbox Code Playgroud)

当您在没有所需请求标头的情况下访问 API 时的响应是:

缺少字符串类型的方法参数的请求标头“授权”

像这个例外一样,您可以自定义所有其他例外。


Mik*_*yev 11

如果 Spring 版本是 5+,那么您需要处理的确切异常是MissingRequestHeaderException. 如果您的全局异常处理程序类扩展,ResponseEntityExceptionHandler那么添加@ExceptionHandlerforServletRequestBindingException将不起作用,因为MissingRequestHeaderException扩展ServletRequestBindingException和后者是handleExceptionResponseEntityExceptionHandler. 如果你尝试,你就会得到Ambiguous @ExceptionHandler method mapped for ...例外。


sha*_*zin 6

有两种方法可以实现您的目标

首先使用@RequestHeaderrequired false

@RequestMapping(value = "/{blabla}", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public void post(@RequestHeader(value="ETag", required=false) String ETag) {
    if(ETag == null) {
        // Your JSON Error Handling
    } else {
        // Your Processing
    }
}
Run Code Online (Sandbox Code Playgroud)

第二次使用HttpServletRequest而不是@RequestHeader

@RequestMapping(value = "/{blabla}", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public void post(HttpServletRequest request) {
    String ETag = request.getHeader("ETag");
    if(ETag == null) {
        // Your JSON Error Handling
    } else {
        // Your Processing
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 嗨@shazin。是否可以在某个基类中捕获此 @ request 标头,并在各个方法中的其他任何地方进行访问?到处写这段代码似乎效率很低 (2认同)

Ser*_*sta 2

您应该使用 @ExceptionHandler 方法来查找 ETag 标头是否存在并采取适当的操作:

@ExceptionHandler(UnsatisfiedServletRequestParameterException.class)
public onErr400(@RequestHeader(value="ETag", required=false) String ETag,
        UnsatisfiedServletRequestParameterException ex) {
    if(ETag == null) {
        // Ok the problem was ETag Header : give your informational message
    } else {
        // It is another error 400  : simply say request is incorrect or use ex
    }
}
Run Code Online (Sandbox Code Playgroud)