Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在Spring Boot中在JSON中抛出异常_Java_Json_Spring_Spring Mvc_Spring Boot - Fatal编程技术网

Java 如何在Spring Boot中在JSON中抛出异常

Java 如何在Spring Boot中在JSON中抛出异常,java,json,spring,spring-mvc,spring-boot,Java,Json,Spring,Spring Mvc,Spring Boot,我有一个请求- @RequestMapping("/fetchErrorMessages") public @ResponseBody int fetchErrorMessages(@RequestParam("startTime") String startTime,@RequestParam("endTime") String endTime) throws Exception { if(SanityChecker.checkDateSanity(startTime)

我有一个请求-

  @RequestMapping("/fetchErrorMessages")
  public @ResponseBody int fetchErrorMessages(@RequestParam("startTime") String startTime,@RequestParam("endTime") String endTime) throws Exception
  {
      if(SanityChecker.checkDateSanity(startTime)&&SanityChecker.checkDateSanity(endTime))
      {
          return 0;
      }
      else
      {
          throw new NotFoundException("Datetime is invalid");
      }
  }
如果startTime和endTime无效,我想抛出一个500错误,但返回JSON格式的异常字符串。然而,我得到一个HTML页面,而不是说

白标错误页面

此应用程序没有/error的显式映射,因此您将其视为回退

2017年12月20日星期三10:49:37
出现意外错误(类型=内部服务器错误,状态=500)。
日期时间无效

相反,我想用JSON返回500

{"error":"Date time format is invalid"}

我该怎么做呢?

这是我在应用程序中如何做到的:

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class ExceptionHandlingControllerAdvice {

   @ExceptionHandler(ExecutionRestrictionViolationException.class)
   public ResponseEntity<String> handleExecutionRestrictionViolationException(ExecutionRestrictionViolationException ex) {
     return response("Invalid Query", ex.getMessage(), HttpStatus.UNPROCESSABLE_ENTITY);
   }

   private static String createJson(String message, String reason) {
    return "{\"error\" : \"" + message + "\"," +
            "\"reason\" : \"" + reason  + "\"}";
   }

   private static ResponseEntity<String> response(String message,
                                               String reason,
                                               HttpStatus httpStatus) {
    String json = createJson(message, reason);
    return new ResponseEntity<>(json, httpStatus);
   }

}
import org.springframework.web.bind.annotation.ControllerAdvice;
导入org.springframework.web.bind.annotation.ExceptionHandler;
@控制器建议
公共类例外处理控制器建议{
@ExceptionHandler(ExecutionRestrictionViolationException.class)
公共责任处理执行限制违反例外(执行限制违反例外){
返回响应(“无效查询”,例如getMessage(),HttpStatus.UNPROCESSABLE_实体);
}
私有静态字符串createJson(字符串消息、字符串原因){
返回“{\”错误\:\”+消息+“\”,“+
“\”原因\“:\”+原因+“\”}”;
}
专用静态响应属性响应(字符串消息,
字符串原因,
HttpStatus(HttpStatus){
字符串json=createJson(消息、原因);
返回新的响应状态(json、httpStatus);
}
}
说明:

  • 您可以创建一个控制器建议,用一个特殊的注释标记它,并像任何其他bean一样定义它(在我的例子中,它是一个java配置,但实际上并不重要)

  • 对于您希望这样处理的每个异常,定义一个处理程序,该处理程序将以您想要的格式生成响应

  • 有一个静态方法createJson——您可以使用另一种方法,这其实也不重要
  • 现在,这只是一种工作方式(在较新的spring boot版本中可用),但还有其他方式:


    我知道的所有方法(甚至更多)都列出了。

    假设您有一个自定义的异常类
    NotFoundException
    及其实现,如下所示:

    public class NotFoundException extends Exception {
    
        private int errorCode;
        private String errorMessage;
    
        public NotFoundException(Throwable throwable) {
            super(throwable);
        }
    
        public NotFoundException(String msg, Throwable throwable) {
            super(msg, throwable);
        }
    
        public NotFoundException(String msg) {
            super(msg);
        }
    
        public NotFoundException(String message, int errorCode) {
            super();
            this.errorCode = errorCode;
            this.errorMessage = message;
        }
    
    
        public void setErrorCode(int errorCode) {
            this.errorCode = errorCode;
        }
    
        public int getErrorCode() {
            return errorCode;
        }
    
        public void setErrorMessage(String errorMessage) {
            this.errorMessage = errorMessage;
        }
    
        public String getErrorMessage() {
            return errorMessage;
        }
    
        @Override
        public String toString() {
            return this.errorCode + " : " + this.getErrorMessage();
        }
    }
    
    现在您想从控制器抛出一些异常。如果抛出异常,则必须从标准错误处理程序类中捕获它,例如,在spring中,它们提供了
    @ControllerAdvice
    注释以应用于创建标准错误处理程序类。当它应用于一个类时,这个spring组件(我指的是您注释的类)可以捕获从控制器抛出的任何异常。但我们需要用适当的方法映射异常类。因此,我们使用异常
    NotFoundException
    处理程序定义了一个方法,如下所示

    @ControllerAdvice
    public class RestErrorHandler {
    
        @ExceptionHandler(NotFoundException.class)
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        @ResponseBody
        public Object processValidationError(NotFoundException ex) {
            String result = ex.getErrorMessage();
            System.out.println("###########"+result);
            return ex;
        }
    }
    

    您希望将http状态发送到内部服务器错误(500),因此这里我们使用了
    @ResponseStatus(HttpStatus.internal\u server\u error)
    。因为您使用了Spring boot,所以除了一个简单的注释之外,您不需要创建json字符串。
    @ResponseBody
    可以自动为您创建该注释。

    您可以使用
    @ResponseStatus
    注释创建
    NotFoundException
    类,如下所示:

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public class NotFoundException extends RuntimeException {
       public NotFoundException() {
       }
    
       public NotFoundException(String message) {
        super(message);
       }
    
    }
    

    Javax的接口名为ExceptionMapper。请参考下面的代码片段,对于应用程序中的每个RuntimeException,它都会将其映射到Json响应实体

    public class RuntimeExceptionMapper implements ExceptionMapper <RuntimeException> {
    
    @Override
    public Response toResponse(RuntimeException exception) {
        ErrorResponse errorResponse = new ErrorResponse();
        errorResponse.setMessage(exception.getMessage);
        if (exception== null) {
            logger.error("Exception Details Not found");            
        } else {
            return Response.status(Status.INTERNAL_SERVER_ERROR)
                .entity(errorResponse )
                    .type(MediaType.APPLICATION_JSON)
                        .header("trace-id", "1234").build();
        }
    
    
    }
    
    public class SecurityResponse {
    
        private String error;
    
        public SecurityResponse() {
    
        }
    
        public SecurityResponse(String error) {
            this.error = error;
        }
    
        public String getError() {
            return error;
        }
    
        public void setError(String error) {
            this.error = error;
        }
    
    }
    
    公共类RuntimeExceptionMapper实现ExceptionMapper{
    @凌驾
    响应的公共响应(运行时异常){
    ErrorResponse ErrorResponse=新的ErrorResponse();
    errorResponse.setMessage(exception.getMessage);
    if(异常==null){
    logger.error(“未找到异常详细信息”);
    }否则{
    返回Response.status(status.INTERNAL\u SERVER\u错误)
    .实体(错误响应)
    .type(MediaType.APPLICATION_JSON)
    .header(“跟踪id”,“1234”).build();
    }
    }
    

    }创建自定义异常

    public class SecurityException extends RuntimeException {
    
        private static final long serialVersionUID = -7806029002430564887L;
    
        private String message;
    
        public SecurityException() {
        }
    
        public SecurityException(String message) {
            this.message = message;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
    }
    
    创建自定义响应实体

    public class RuntimeExceptionMapper implements ExceptionMapper <RuntimeException> {
    
    @Override
    public Response toResponse(RuntimeException exception) {
        ErrorResponse errorResponse = new ErrorResponse();
        errorResponse.setMessage(exception.getMessage);
        if (exception== null) {
            logger.error("Exception Details Not found");            
        } else {
            return Response.status(Status.INTERNAL_SERVER_ERROR)
                .entity(errorResponse )
                    .type(MediaType.APPLICATION_JSON)
                        .header("trace-id", "1234").build();
        }
    
    
    }
    
    public class SecurityResponse {
    
        private String error;
    
        public SecurityResponse() {
    
        }
    
        public SecurityResponse(String error) {
            this.error = error;
        }
    
        public String getError() {
            return error;
        }
    
        public void setError(String error) {
            this.error = error;
        }
    
    }
    
    为自定义异常创建一个ControllerAdvice with ExceptionHandler,它将处理自定义异常,填充并返回自定义响应,如下所示

    @ControllerAdvice
    public class SecurityControllerAdvice {
    
        @ExceptionHandler(SecurityException.class)
        @ResponseBody
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        public SecurityResponse handleSecurityException(SecurityException se) {
            SecurityResponse response = new SecurityResponse(se.getMessage());
            return response;
        }
    }
    
    根据您的条件引发自定义异常

    throw new SecurityException("Date time format is invalid");
    
    现在运行并测试您的应用程序。例如:


    Spring提供了几种方法来实现这一点,根据您的情况,有些方法比其他方法更明智

    (这里有关于几个选项的精彩教程。)

    我最喜欢的是这个,因为我想发回正确的错误消息和正确的http响应,而不需要在实用程序类中创建超类或帮助器方法,也不需要到处复制样板文件

    如果要通知调用方事件导致错误(在正确的JSON中),请使用Spring的ResponseStatusException。它允许您访问HttpReporte对象,因此您还可以发回除“ok”之外的响应

    它需要一个异常作为其参数之一。在我的一个场景中,我想通知调用方他们正在尝试注册一个已经存在的用户。通常,查找用户不应该抛出异常,但在本例中,我创建了自己的异常,并以类似的方式将其返回给调用方:


    如果他抛出了
    NotFoundException
    ,那么你的
    @ExceptionHandler
    类不应该是
    @ExceptionHandler(NotFoundException.class)
    ?是的,你完全正确。我刚刚展示了我的应用程序中的一个代码片段(想法)。我相信每个异常类型应该有一个方法。看起来我可以从客户端发送accept头,响应将是JSON(感谢Jackson)。这确实有效,但我不推荐这种方法。它不提供显示自定义消息的可能性,以防您