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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47899292/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 02:43:39  来源:igfitidea点击:

How to throw an exception back in JSON in Spring Boot

javajsonspringspring-mvcspring-boot

提问by Prateek Narendra

I have a Request Mapping -

我有一个请求映射 -

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

If the startTime and endTime are invalid, I want to throw a 500 error but return the exception string in JSON. However, I get a HTML Page instead saying

如果 startTime 和 endTime 无效,我想抛出 500 错误但返回 JSON 中的异常字符串。但是,我得到了一个 HTML 页面,而不是说

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Wed Dec 20 10:49:37 IST 2017
There was an unexpected error (type=Internal Server Error, status=500).
Datetime is invalid

白标错误页面

此应用程序没有明确的 /error 映射,因此您将其视为后备。

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

I instead wanted to return 500 with a JSON

相反,我想用 JSON 返回 500

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

How do I go about this?

我该怎么做?

采纳答案by Ataur Rahman Munna

Suppose you have a custom Exception class NotFoundExceptionand its implementations something like this:

假设您有一个自定义 Exception 类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();
    }
}

Now you want to throw some exception from controller. If you throw a exception then you must catch it from a standard Error Handler class, say for example in spring they provide @ControllerAdviceannotation to apply to make a class Standard Error Handler. When it is applied to a class then this spring component (I mean the class you annotated) can catch any exception thrown from controller. But We need to map exception class with proper method. So we defined a method with your exception NotFoundExceptionhandler something like below.

现在你想从控制器抛出一些异常。如果您抛出异常,则必须从标准错误处理程序类中捕获它,例如在 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;
    }
}

You want to sent http status to internal server error(500), so here we used @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR). Since you used Spring-boot so you do not need to make a json string except a simple annotation @ResponseBodycan do that for you automagically.

您想将http 状态发送到内部服务器 error(500),因此我们在这里使用@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR). 由于您使用了 Spring-boot,因此您不需要制作 json 字符串,除非一个简单的注释@ResponseBody可以自动为您完成。

回答by Mark Bramnik

This is how I did it in my application:

这就是我在我的应用程序中所做的:

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

}

Explanation:

解释:

  1. You create a controller Advice, mark it with a special annotation and define just like any other bean (in my case it was a java configuration, but it doesn't really matter)

  2. For each Exception you would like to handle like this - define a handler that will generate a response in a format you want

  3. There is a static method createJson - you can use a different way, it also doesn't matter really.
  1. 你创建了一个控制器 Advice,用一个特殊的注解标记它并像任何其他 bean 一样定义(在我的例子中它是一个 java 配置,但它并不重要)

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

  3. 有一个静态方法 createJson - 您可以使用不同的方式,这也无关紧要。

Now this is only one way to work (its available in more recent spring boot versions) - but there are others:

现在这只是一种工作方式(在最近的 Spring Boot 版本中可用) - 但还有其他的:

All the methods I'm aware of (and even more) are listed here.

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

回答by Hiren

you can create NotFoundExceptionclass with @ResponseStatusannotation like below:

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

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public class NotFoundException extends RuntimeException {
   public NotFoundException() {
   }

   public NotFoundException(String message) {
    super(message);
   }

}

回答by Mohit Sharma

Javax has a interface name as ExceptionMapper. Please refer the below code snippet, For every RuntimeException in your application it will map it to a Json Response entity.

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

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();
    }


}

}

}

回答by Neeraj Benjwal

Create a custom exception.

创建自定义异常。

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

}

Create a custom response entity.

创建自定义响应实体。

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

}

Create a ControllerAdvice with ExceptionHandler for custom exception, it will handle the custom exception, populate and return the custom response as below.

为自定义异常创建一个带有 ExceptionHandler 的 ControllerAdvice,它将处理自定义异常,填充并返回自定义响应,如下所示。

@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 the custom exception based on your condition.

根据您的条件抛出自定义异常。

throw new SecurityException("Date time format is invalid");

Now run and test you app. E.G. :

现在运行并测试您的应用程序。EG :

enter image description here

在此处输入图片说明