【问题标题】:In Spring 3 is it possible to dynamically set the reason of @ResponseStatus?在 Spring 3 中是否可以动态设置 @ResponseStatus 的原因?
【发布时间】:2012-01-25 13:11:37
【问题描述】:

我有一个自定义异常类被注释为返回给定的HttpStatus

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

当我从控制器抛出BadRequestException 时,这有效,但原因当然总是“无效参数”。有没有办法在这个类中设置返回的原因?我想传递一个字符串作为原因。

谢谢!

【问题讨论】:

    标签: java spring spring-mvc


    【解决方案1】:

    “原因”是可选的,因此您可以省略它并实现传递错误的抽象方法公共字符串原因。 链接:http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/bind/annotation/ResponseStatus.html

    【讨论】:

    • 你说的是什么意思,并实现了抽象方法public String原因传递了Error”?我不认为只是将reasongetReason 方法添加到OP 的public class BadRequestException extends RuntimeException 将允许动态设置消息?
    【解决方案2】:

    您可以使用HttpServletResponsesendError 函数来实现。
    以下是如何使用它的示例:

    @RequestMapping(value = "some/url", method = RequestMethod.POST)
    public void doAction(final HttpServletResponse response) throws IOException {
      response.sendError(HttpStatus.BAD_REQUEST.value(), "custom error message");
    }
    

    【讨论】:

    • 什么是响应?
    • @user3871754,response可以在控制器方法中获取。 @Bozho 的意思是,与其在我的控制器方法中抛出异常,不如调用response.sendError
    【解决方案3】:

    注解是静态的,不能从你的类中动态设置。我建议为每种类型的故障场景创建一个 BadRequestException 的子类,并以不同的方式对其进行注释。

    这不仅仅是一种解决方法——如果您在 reason 消息中隐藏了有关问题的详细信息,那么您将失去灵活性,因为任何捕获 BadRequestException 的代码都必须以相同的方式处理所有故障情况。

    【讨论】:

    • 在这种情况下,最终处理异常的代码必须以相同的方式处理它......控制器正在响应来自 JavaScript 前端的异步请求。在任何
    • 我明白你的意思。我仍然认为这是一个很好的设计,没有任何伤害(除了引入比你已经拥有的更多的 Exception 类),但如果你倾向于尝试不同的路线,Bozho 提到的方法和/或描述的方法这里可能有用:forum.springsource.org/…。希望有帮助!
    【解决方案4】:

    正确的做法是在你的控制器中引入异常处理程序,然后你可以设置任意状态码的响应体:

    @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;
      }
    }
    

    您不必使用任何 Spring Web MVC 注释和依赖项污染您的模型/异常类。

    如果您想与所有控制器共享处理程序,请查看@ControllerAdvice

    【讨论】:

    • 问题是关于设置原因短语,而不是正文。
    【解决方案5】:

    设置response.setStatus() 的最简单方法。简单干净,您可以将其更改为您想要的任何状态,而不是 ex.getStatusCode() 添加您的代码。

    返回类型也是你的选择,我使用 String b/c 稍后显示。

    顺便说一句,sendError 不是一个好主意,因为例如 JBoss 会在响应中添加大量 HTML。

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

    【讨论】:

      【解决方案6】:

      如果您在自定义异常的@ResponseStatus 注释中省略了“原因”属性,

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

      然后抛出异常 - 在您的 service 层中。因此,您不需要 catch 并在控制器中抛出其他内容或 catch 来将响应直接设置为某些 HTTP 状态代码。

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

      异常消息作为 JSON 输出中“数据”的“消息”传递。注释中的“原因”似乎覆盖了自定义行为。因此,您可以针对给定上下文说一个基本异常,并在十几个地方使用它,每个地方都有一条略有不同的消息,抛出的地方和所有获取都正确处理到 REST 接口。

      【讨论】:

      • 呵呵,这个功能我好像用过几次都不知道。谢谢!
      • 对我不起作用。我将状态代码设置为 BAD_REQUEST (400),但在错误和消息字段中都得到了“错误请求”。即使在我的异常对象中设置了异常消息。
      • 这很好用。谢谢你。这比使用特殊捕获来抛出错误要容易得多。
      • 消息还是空白。
      • 如果消息为空,在 application.properties 文件中设置server.error.include-message=always 会有所帮助。
      【解决方案7】:

      从 spring 5.0 开始,您可以使用可用的ResponseStatusException

      // From https://www.baeldung.com/spring-response-status-exception
      @GetMapping("/actor/{id}")
      public String getActorName(@PathVariable("id") int id) {
          try {
              return actorService.getActor(id);
          } catch (ActorNotFoundException ex) {
              throw new ResponseStatusException(
                HttpStatus.NOT_FOUND, "Actor Not Found", ex);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-30
        • 1970-01-01
        • 2019-03-22
        • 2014-12-18
        • 2020-01-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多