spring boot 2 统一异常处理

spring mvc 针对controller层异常统一处理非常简单,使用 @RestControllerAdvice 或 @RestControllerAdvice 注解就可以轻@RestControllerAdvice

public class GatewayExceptionHandler {

    /*@ExceptionHandler(Exception.class)
    public JsonResult handleBusinessException(HttpServletRequest request, Exception e) {
        e.printStackTrace();
        String code = ErrorCodeEnum.SYSTEM_ERROR_STRING.getCode();
        String message = StringUtils.isNotEmpty(e.getMessage()) ? e.getMessage() : "Service Currently Unavailable";
        return JsonResult.ErrorResponse(code, message);
    }*/

    @ExceptionHandler(value = Exception.class)
    public Map errorHandler(Exception ex) {
        Map map = new HashMap();
        map.put("code", 100);
        map.put("msg", ex.getMessage());
        return map;
    }
}

下面记录一下,spring cloud gateway项目中重写 DefaultErrorWebExceptionHandler 类,实现自定义异常处理

首先写一个类继承 DefaultErrorWebExceptionHandler 类,重写方法

public class RmcloudExceptionHandler extends DefaultErrorWebExceptionHandler {

    /**
     * Create a new {@code DefaultErrorWebExceptionHandler} instance.
     *
     * @param errorAttributes    the error attributes
     * @param resourceProperties the resources configuration properties
     * @param errorProperties    the error configuration properties
     * @param applicationContext the current application context
     */
    public RmcloudExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }

    /**
     * 确定返回什么HttpStatus
     *
     * @param errorAttributes
     * @return
     */
    @Override
    protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) {
        //HttpStatus status = (HttpStatus) errorAttributes.get("status");
        // return HttpStatus.INTERNAL_SERVER_ERROR == status ? HttpStatus.OK : status;
        return HttpStatus.OK;
    }

    /**
     * 返回的错误信息json内容
     *
     * @param request
     * @param includeStackTrace
     * @return
     */
    @Override
    protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {

        Throwable error = this.getError(request);

        return JsonResult.responseReturnMap(RmcloudConstant.GATEWAY_ERRORCODE, this.buildMessage(request, error));
       
    }

    private String buildMessage(Throwable t) {
        return "未知错误!";
    }

    private String buildMessage(ServerRequest request, Throwable ex) {
        StringBuilder message = new StringBuilder("api-gateway Failed to handle request [");
        message.append(request.methodName());
        message.append(" ");
        message.append(request.uri());
        message.append("]");
        if (ex != null) {
            message.append(": ");
            message.append(ex.getMessage());
        }
        return message.toString();
    }

    private HttpStatus determineHttpStatus(Throwable error) {
        return error instanceof ResponseStatusException ? ((ResponseStatusException) error).getStatus() : HttpStatus.INTERNAL_SERVER_ERROR;
    }

}

然后,配置自定义的ExceptionHandler


import com.vcredit.rmcloud.gateway.exception.RmcloudExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;

import java.util.Collections;
import java.util.List;

/**
* webflux全局异常处理器配置配置
* 由于webflux的函数式编程方式中不能通过controllerAdvice只能通过每个RouterFunction中添加filter的方式实现异常处理,
* 这里通过注入一个自定义ErrorWebExceptionHandler来达到全局异常处理的目的
*
* @author lee
*/
@Configuration
@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
public class ErrorHandlerConfiguration {

private final ServerProperties serverProperties;

private final ApplicationContext applicationContext;

private final ResourceProperties resourceProperties;

private final List<ViewResolver> viewResolvers;

private final ServerCodecConfigurer serverCodecConfigurer;

public ErrorHandlerConfiguration(ServerProperties serverProperties,
ResourceProperties resourceProperties,
ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer,
ApplicationContext applicationContext) {
this.serverProperties = serverProperties;
this.applicationContext = applicationContext;
this.resourceProperties = resourceProperties;
this.viewResolvers = viewResolversProvider
.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}

@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public ErrorWebExceptionHandler errorWebExceptionHandler(
ErrorAttributes errorAttributes) {
RmcloudExceptionHandler exceptionHandler = new RmcloudExceptionHandler(
errorAttributes, this.resourceProperties,
this.serverProperties.getError(), this.applicationContext);
exceptionHandler.setViewResolvers(this.viewResolvers);
exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
return exceptionHandler;
}
}

JsonResult内容

@Data
@NoArgsConstructor
@AllArgsConstructor
public class JsonResult<T> {

    private static String successCode = "";

    private String errorCode;

    private String msg;

    private T data;

    private Long timestamp;

    public static <T> JsonResult<T> successResponse(T data) {
        return new JsonResult<>(successCode, "Success", data, System.currentTimeMillis());
    }

    public static <T> JsonResult<T> errorResponse(String errorMessage) {
        return new JsonResult<>(RmcloudConstant.GATEWAY_ERRORCODE, errorMessage, null, System.currentTimeMillis());
    }

    public static <T> JsonResult<T> errorResponse(String status, String errorMessage) {
        return new JsonResult<>(status, errorMessage, null, System.currentTimeMillis());
    }

    public static Map<String, Object> responseReturnMap(String status, String errorMessage) {
        Map<String, Object> map = new HashMap<>();
        map.put("errorCode", status);
        map.put("msg", errorMessage);
        map.put("data", null);
        return map;
    }
}

最后感谢chenqian56131,主要代码是从他github上淘来的,以上是结合实际项目的应用,记录下来,方便以后查阅。