java 拦截缺少标头的@RequestHeader 异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25151264/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Intercept @RequestHeader exception for missing header
提问by Ruslan Islamov
I have a method in controller with has parameter for example
我在控制器中有一个方法,例如有参数
@RequestMapping(value = "/{blabla}", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public void post(@RequestHeader("ETag") int etag)
If there is no ETag header in request - client gets 400 (BAD_REQUEST), which is not any informative. I need to somehow handle this exception and send my own exception to client (I use JSON for this purpose). I know that I can intercept exception via @ExceptionHandler, but in that case all HTTP 400 requests will be handled, but I want that have missing ETag in headers. Any ideas?
如果请求中没有 ETag 标头 - 客户端得到 400 (BAD_REQUEST),这不是任何信息。我需要以某种方式处理这个异常并将我自己的异常发送给客户端(为此我使用 JSON)。我知道我可以通过@ExceptionHandler 拦截异常,但在这种情况下,所有 HTTP 400 请求都将被处理,但我希望标头中缺少 ETag。有任何想法吗?
采纳答案by Serge Ballesta
You should user an @ExceptionHandler method that looks if ETag header is present and takes appropriate action :
您应该使用 @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
}
}
回答by Vishnu Prabhakar
You can also achieve this by use of annotation @ControllerAdvice
from spring.
您还可以通过使用@ControllerAdvice
spring 中的注释来实现这一点。
@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);
}
}
The response when you access your API without the required request header is:
当您在没有所需请求标头的情况下访问 API 时的响应是:
Missing request header 'Authorization' for method parameter of type String
缺少字符串类型的方法参数的请求标头“授权”
Like this exception, you can customise all other exceptions.
像这个例外一样,您可以自定义所有其他例外。
回答by shazin
There are two ways to achieve what you are trying
有两种方法可以实现您的目标
First using @RequestHeader
with required
false
首先使用@RequestHeader
与required
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
}
}
Second using HttpServletRequest
instead of @RequestHeader
第二次使用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
}
}
回答by Shreyas Keote
Write a method with the annotation @ExceptionHandler and use ServletRequestBindingException.class as this exception is thrown in case of missing header
写一个带有@ExceptionHandler 注释的方法并使用 ServletRequestBindingException.class 因为在缺少头的情况下会抛出这个异常
For example :
例如 :
@ExceptionHandler(ServletRequestBindingException.class)
public ResponseEntity<ResponseObject> handleHeaderError(){
ResponseObject responseObject=new ResponseObject();
responseObject.setStatus(Constants.ResponseStatus.FAILURE.getStatus());
responseObject.setMessage(header_missing_message);
ResponseEntity<ResponseObject> responseEntity=new ResponseEntity<ResponseObject>(responseObject, HttpStatus.BAD_REQUEST);
return responseEntity;
}
回答by Sotirios Delimanolis
This is relatively simple. Declare two handler methods, one that declares the appropriate header in the @RequestMapping
headers
attribute and one that doesn't. Spring will take care to invoke the appropriate one based on the content of the request.
这个比较简单。声明两种处理程序方法,一种在@RequestMapping
headers
属性中声明适当的标头,另一种没有。Spring 会根据请求的内容小心地调用适当的一个。
@RequestMapping(value = "/{blabla}", method = RequestMethod.POST, headers = "ETag")
@ResponseStatus(HttpStatus.CREATED)
public void postWith(@RequestHeader("ETag") int etag) {
// has it
}
@RequestMapping(value = "/{blabla}", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public void postWithout() {
// no dice
// custom failure response
}
回答by Patrick Grimard
If you don't want to handle this in your request mapping, then you could create a Servlet Filter and look for the ETag header in the Filter. If it's not there, then throw the exception. This would apply to only requests that match your filter's URL mapping.
如果您不想在请求映射中处理此问题,那么您可以创建一个 Servlet 过滤器并在过滤器中查找 ETag 标头。如果它不存在,则抛出异常。这仅适用于与您的过滤器的 URL 映射匹配的请求。
public final class MyEtagFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String etag = request.getHeader("ETag");
if(etag == null)
throw new MissingEtagHeaderException("...");
filterChain.doFilter(request, response);
}
}
You'll have to implement your own MissingEtagHeaderException, or use some other existing exception.
您必须实现自己的 MissingEtagHeaderException,或使用其他一些现有的异常。
回答by Leonel Sanches da Silva
You can also intercept the exception without extending ResponseEntityExceptionHandler
:
您还可以在不扩展的情况下拦截异常ResponseEntityExceptionHandler
:
@ControllerAdvice
public class ControllerExceptionHandler {
@ExceptionHandler(ServletRequestBindingException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<Object> handleServletRequestBindingException(ServletRequestBindingException ex) {
// return a ResponseEntity<Object> object here.
}
}
回答by Mikayil Abdullayev
In case Spring version is 5+ then the exact exception you need to handle is the MissingRequestHeaderException
. If your global exception handler class extends ResponseEntityExceptionHandler
then adding an @ExceptionHandler
for ServletRequestBindingException
won't work because MissingRequestHeaderException
extends ServletRequestBindingException
and the latter is handled inside the handleException
method of the ResponseEntityExceptionHandler
. If you try you're going to get Ambiguous @ExceptionHandler method mapped for ...
exception.
如果 Spring 版本是 5+,那么您需要处理的确切异常是MissingRequestHeaderException
. 如果您的全局异常处理程序类扩展,ResponseEntityExceptionHandler
则添加@ExceptionHandler
forServletRequestBindingException
将不起作用,因为MissingRequestHeaderException
extendsServletRequestBindingException
并且后者handleException
在ResponseEntityExceptionHandler
. 如果你尝试,你会得到Ambiguous @ExceptionHandler method mapped for ...
例外。