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);
}
}
说明:
我知道的所有方法(甚至更多)都列出了。假设您有一个自定义的异常类
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)。这确实有效,但我不推荐这种方法。它不提供显示自定义消息的可能性,以防您