In Spring 3 is it possible to dynamically set the reason of @ResponseStatus?

被刻印的时光 ゝ 提交于 2020-01-12 02:31:32

问题


I have a custom exception class annotated to return a given HttpStatus:

@ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="Invalid parameter")
public class BadRequestException extends RuntimeException
{
  public BadRequestException(String msg)
  {
    super(msg);
  }
}

This works when I throw a BadRequestException from my controller but the reason is always "Invalid parameter" of course. Is there a way to set the returned reason in this class? I'd like to pass a string to be used as the reason.

Thanks!


回答1:


You can use response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid foo");




回答2:


If you omit the 'reason' attribute in the @ResponseStatus annotation on a custom exception,

@ResponseStatus(value = HttpStatus.CONFLICT)  // 409
public class ChildDataExists extends RuntimeException {
...

then throw the exception

throw new ChildDataExists("Can't delete parent if child row exists.");

The exception's message comes through as the 'message' of the 'data' in the JSON output. It seems the 'reason' in the annotation overrides the custom behavior.




回答3:


The correct way is to introduce exception handler in your controller, then you can set response body of any status code:

@Controller
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public class SomeController {
...
  @ExceptionHandler(BadRequestException.class)
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public @ResponseBody
   Map<String,Object> handleIndexNotFoundException(BadRequestException bre,
                                           HttpServletRequest request, HttpServletResponse resp) {
     HashMap<String, Object> result = new HashMap<>();
     result.put("error", true);
     result.put("error_message", bre.getMessage());
     return result;
  }
}

Move over you don't have to pollute your model/exception classes with any Spring Web MVC annotations and dependency.

If you want to share the handler with all controller look into @ControllerAdvice.




回答4:


Annotations are meant to be static, and can't be set dynamically from your class. I suggest creating a subclass of your BadRequestException for every type of failure scenario and annotating them differently.

This doesn't just serve as a workaround -- if you're hiding the details regarding what went wrong in the reason message, then you're losing flexibility because any code that catches a BadRequestException will have to deal with all failure scenarios the same way.




回答5:


The easiest way to just set the response.setStatus(). Easy and clean, you can change it to any status you want just instead of ex.getStatusCode() add your code.

The return type is also of your choice, I'm using String b/c displaying this later.

By the way, the sendError is not a good idea, because JBoss for instance is adding a lot of HTML to the response.

@ExceptionHandler(CommunicationException.class)
@ResponseBody()
public String handleCommunicationException(CommunicationException ex, HttpServletResponse response) throws IOException{
    response.setStatus(ex.getStatusCode());
    return ex.getStatusMessage();   
}



回答6:


The "reason" is optional, so you can omit that and implements the abstract method public String reason passing the Error. Link: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/bind/annotation/ResponseStatus.html



来源:https://stackoverflow.com/questions/8594645/in-spring-3-is-it-possible-to-dynamically-set-the-reason-of-responsestatus

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!