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

时间:2017-12-20 05:23:18

标签: 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)&&SanityChecker.checkDateSanity(endTime))
      {
          return 0;
      }
      else
      {
          throw new NotFoundException("Datetime is invalid");
      }
  }

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

  

Whitelabel错误页面

     

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

     

Wed Dec 20 10:49:37 IST 2017
  出现意外错误(type = Internal Server Error,status = 500)   日期时间无效

我想要用JSON

返回500
{"error":"Date time format is invalid"}

我该怎么做?

6 个答案:

答案 0 :(得分:6)

假设您有一个自定义的异常类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_SERVER_ERROR)。因为你使用了Spring-boot所以你不需要创建一个json字符串,除了一个简单的注释@ResponseBody可以自动为你做。

答案 1 :(得分:4)

创建自定义例外。

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

}

使用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 new SecurityException("Date time format is invalid");

现在运行并测试你的应用程序。例如。 :

enter image description here

答案 2 :(得分:1)

这就是我在申请中的表现:

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

}

说明:

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

    < / LI>
  2. 对于您想要处理的每个异常 - 定义一个处理程序,它将以您想要的格式生成响应

  3. 有一个静态方法createJson - 你可以使用不同的方式,它也没关系。
  4. 现在这只是一种工作方式(它在最近的春季启动版本中可用) - 但还有其他方法:

    我所知道的所有方法(甚至更多)都列在here

答案 3 :(得分:1)

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

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

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

}

答案 4 :(得分:1)

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


}

}

答案 5 :(得分:0)

Spring提供了一些方法来实现此目的,根据您的情况,一些方法比其他方法更明智。

(此处提供有关多个选项的出色教程。https://www.baeldung.com/spring-exceptions-json

我最喜欢的是这个,因为我想发回适当的错误消息和适当的http响应,而无需在实用程序类中创建超类或创建辅助方法,也无需在任何地方复制样板。

如果您想通知调用者该事件导致了错误(并使用正确的JSON),请使用Spring的ResponseStatusException。它使您可以访问httpReponse对象,因此还可以发回“ ok”以外的其他响应。

它想要一个异常作为它的参数之一。对于我的一种情况,我想通知呼叫者他们正在尝试注册已经存在的用户。通常,查找用户不应引发异常,但是在这种情况下,我创建了自己的异常,然后将其以ResponseStatusException的形式扔回到调用方,如下所示:

  @PostMapping("/register")
  public ResponseEntity register(@RequestBody AccountUserDto user) {
    UserDetails userExists = userDetailsService.loadUserByEmail(user.getEmail());

  if (userExists != null) {
      UserExistsException exc = new UserExistsException("Error: Email address " + user.getEmail() +  " is already in use.");
        throw new ResponseStatusException(
        HttpStatus.BAD_REQUEST, "User Exists", exc);
  }
....(fall through and create user)