Rest Service中的Spring Boot自定义异常

时间:2014-10-21 09:42:23

标签: java rest exception-handling spring-boot

我在基于Spring Boot的Rest服务中定义了一个全局异常处理:

@ControllerAdvice
public class GlobalExceptionController {

    private final Logger LOG = LoggerFactory.getLogger(getClass());

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR, reason = "Internal application error")
    @ExceptionHandler({ServiceException.class})
    @ResponseBody
    public ServiceException serviceError(ServiceException e) {
        LOG.error("{}: {}", e.getErrorCode(), e.getMessage());
        return e;
    }
}

和自定义的ServiceException:

public class ServiceException extends RuntimeException {

    private static final long serialVersionUID = -6502596312985405760L;

    private String errorCode;

    public ServiceException(String message, String errorCode, Throwable cause) {
        super(message, cause);
        this.errorCode = errorCode;
    }

    // other constructors, getter and setters omitted
}

到目前为止一切顺利,当一个异常被触发时,控制器按原样运行并响应:

{
   "timestamp": 1413883870237,
   "status": 500,
   "error": "Internal Server Error",
   "exception": "org.example.ServiceException",
   "message": "somthing goes wrong",
   "path": "/index"
}

但是字段 errorCode 未显示在JSON响应中。

那么如何在我的应用程序中定义自定义异常响应。

2 个答案:

答案 0 :(得分:21)

Spring Boot使用ErrorAttributes的实现来填充呈现为JSON的Map。默认情况下,使用DefaultErrorAttributes的实例。要包含自定义errorCode,您需要提供了解ErrorAttributes及其错误代码的自定义ServiceException实现。此自定义实现应该是您配置中的@Bean

一种方法是子类DefaultErrorAttributes

@Bean
public ErrorAttributes errorAttributes() {
    return new DefaultErrorAttributes() {

        @Override
        public Map<String, Object> getErrorAttributes(
                RequestAttributes requestAttributes,
                boolean includeStackTrace) {
            Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
            Throwable error = getError(requestAttributes);
            if (error instanceof ServiceException) {
                errorAttributes.put("errorCode", ((ServiceException)error).getErrorCode());
            }
            return errorAttributes;
        }

    };
}

答案 1 :(得分:3)

@Alex您可以使用注释 @ExceptionHandler(YourExceptionClass.class)来处理特定RestController中的特定异常。我认为这是处理业务应用程序中复杂场景的更好方法。此外,我建议您使用自定义异常转换器来处理不同类型的异常。您可以将spring oauth2 exception translator视为异常翻译的参考代码。

注意:以下代码仅用于理解此解决方案的概念。它不是生产就绪代码。随意讨论更多相关信息。

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

/**
* @author Harpreet
* @since 16-Aug-17.
*/
@RestController
public class RestTestController {

@RequestMapping(value = "name", method = RequestMethod.GET,
        produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseObject name(@RequestParam(value="name") String value){
    //your custom logic 
    if (value == null || value.length() < 2) {
        //throwing exception to invoke customExceptionHandler
        throw new NullPointerException("value of request_param:name is invalid");
    }
    ResponseObject responseObject = new ResponseObject();
    responseObject.setMessage(value)
            .setErrorCode(1);
    return responseObject;
}

// to handle null pointer exception
@ExceptionHandler(NullPointerException.class)
public ResponseObject customExceptionHandler
        (NullPointerException e) {
    ResponseObject responseObject = new ResponseObject();
    responseObject.setMessage(e.getMessage())
            .setErrorCode(-1);
    return responseObject;
}

// response data transfer class
static class ResponseObject{
    String message;
    Integer errorCode;

    public String getMessage() {
        return message;
    }

    public ResponseObject setMessage(String message) {
        this.message = message;
        return this;
    }

    public Integer getErrorCode() {
        return errorCode;
    }

    public ResponseObject setErrorCode(Integer errorCode) {
        this.errorCode = errorCode;
        return this;
    }
  }
 }