【问题标题】:How return error message in spring mvc @Controller如何在spring mvc @Controller中返回错误消息
【发布时间】:2015-12-03 04:49:55
【问题描述】:

我正在使用这样的方法

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<UserWithPhoto> getUser(@RequestHeader(value="Access-key") String accessKey,
                                     @RequestHeader(value="Secret-key") String secretKey){
    try{
        return new ResponseEntity<UserWithPhoto>((UserWithPhoto)this.userService.chkCredentials(accessKey, secretKey, timestamp),
                new HttpHeaders(),
                HttpStatus.CREATED);
    }
    catch(ChekingCredentialsFailedException e){
        e.printStackTrace();
        return new ResponseEntity<UserWithPhoto>(null,new HttpHeaders(),HttpStatus.FORBIDDEN);
    }
}

并且我想在发生异常时返回一些文本消息,但现在我只返回状态和空对象。有可能吗?

【问题讨论】:

  • 将您的返回类型更改为ResponseEntity&lt;Object&gt; 或ResponseEntity&lt;?&gt;。不要为您的错误案例传递null 参数,而是传递String。 Spring 足够聪明,可以看到String 并将其作为文本写入响应正文。或者,提供一个@ExceptionHandler,它将自己处理异常并让您的处理程序抛出异常。
  • @SotiriosDelimanolis,想知道你为什么不创建答案?
  • @lkrnac 我过去回答过类似的问题。我不再觉得它们一定很有趣。但是我找不到重复的,所以我还是想给点东西。

标签: java spring-mvc


【解决方案1】:

正在评估来自另一个调用的服务的错误响应...

这是我评估错误的解决方案:

try {
        return authenticationFeign.signIn(userDto, dataRequest);
    }catch(FeignException ex){

        //ex.status();

        if(ex.status() == HttpStatus.UNAUTHORIZED.value()){
            System.out.println("is a error 401");
            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
        }
        return new ResponseEntity<>(HttpStatus.OK);

    }

【讨论】:

    【解决方案2】:
    return new ResponseEntity<>(GenericResponseBean.newGenericError("Error during the calling the service", -1L), HttpStatus.EXPECTATION_FAILED);
    

    【讨论】:

    • GenericResponseBean 是从哪里来的?
    【解决方案3】:

    这是另一种选择。创建一个接受状态代码和消息的通用异常。然后创建一个异常处理程序。使用异常处理程序从异常中检索信息并返回给服务的调用者。

    http://javaninja.net/2016/06/throwing-exceptions-messages-spring-mvc-controller/

    public class ResourceException extends RuntimeException {
    
        private HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
    
        public HttpStatus getHttpStatus() {
            return httpStatus;
        }
    
        /**
         * Constructs a new runtime exception with the specified detail message.
         * The cause is not initialized, and may subsequently be initialized by a
         * call to {@link #initCause}.
         * @param message the detail message. The detail message is saved for later retrieval by the {@link #getMessage()}
         *                method.
         */
        public ResourceException(HttpStatus httpStatus, String message) {
            super(message);
            this.httpStatus = httpStatus;
        }
    }
    

    然后使用异常处理程序检索信息并将其返回给服务调用者。

    @ControllerAdvice
    public class ExceptionHandlerAdvice { 
    
        @ExceptionHandler(ResourceException.class)
        public ResponseEntity handleException(ResourceException e) {
            // log exception 
            return ResponseEntity.status(e.getHttpStatus()).body(e.getMessage());
        }         
    } 
    

    然后在需要时创建一个异常。

    throw new ResourceException(HttpStatus.NOT_FOUND, "We were unable to find the specified resource.");
    

    【讨论】:

      【解决方案4】:

      正如 Sotirios Delimanolis 已经在 cmets 中指出的那样,有两种选择:

      返回 ResponseEntity 和错误信息

      像这样改变你的方法:

      @RequestMapping(method = RequestMethod.GET)
      public ResponseEntity getUser(@RequestHeader(value="Access-key") String accessKey,
                                    @RequestHeader(value="Secret-key") String secretKey) {
          try {
              // see note 1
              return ResponseEntity
                  .status(HttpStatus.CREATED)                 
                  .body(this.userService.chkCredentials(accessKey, secretKey, timestamp));
          }
          catch(ChekingCredentialsFailedException e) {
              e.printStackTrace(); // see note 2
              return ResponseEntity
                  .status(HttpStatus.FORBIDDEN)
                  .body("Error Message");
          }
      }
      

      注意 1:您不必使用 ResponseEntity 构建器,但我发现它有助于保持代码的可读性。它还有助于记住特定 HTTP 状态代码的响应应包含哪些数据。例如,状态码为 201 的响应应在 Location 标头中包含指向新创建资源的链接(请参阅 Status Code Definitions)。这就是 Spring 提供方便的构建方法ResponseEntity.created(URI) 的原因。

      注意 2:不要使用 printStackTrace(),而是使用记录器。

      提供@ExceptionHandler

      从您的方法中删除 try-catch 块并让它抛出异常。然后在使用@ControllerAdvice 注释的类中创建另一个方法,如下所示:

      @ControllerAdvice
      public class ExceptionHandlerAdvice {
      
          @ExceptionHandler(ChekingCredentialsFailedException.class)
          public ResponseEntity handleException(ChekingCredentialsFailedException e) {
              // log exception
              return ResponseEntity
                      .status(HttpStatus.FORBIDDEN)
                      .body("Error Message");
          }        
      }
      

      请注意,使用@ExceptionHandler 注释的方法允许具有非常灵活的签名。详情请参阅Javadoc。

      【讨论】:

      • 我一直在做类似于这里的第二个例子的事情。我无法正确测试它。你知道如何使用这种方法测试控制器响应吗?当您不返回自己的 ResponseEntity 时似乎可以工作,而只需使用 \@ResponseStatus 和 \@ResponseBody 以及 \@ExceptionHandler。
      • 带有@ControllerAdvice 的类是否应该尝试处理所有可能的异常?例如,如果我抛出“弱密码”异常,我应该尝试在服务方法中捕获它,还是应该在异常处理程序类中处理它?我们如何区分哪些异常由谁处理?我知道这很主观,但有标准做法吗?
      • 为避免出现Raw use of parameterized class 'ResponseEntity 警告,请使用ResponseEntity&lt;?&gt; 作为您的方法返回类型。
      猜你喜欢
      • 2014-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-27
      • 2012-09-25
      • 2014-07-23
      • 2013-10-08
      • 1970-01-01
      相关资源
      最近更新 更多