SpringBoot,第一战:异常处理

153 阅读2分钟

介绍野图BOSS

如题,今天我们来战SpringBoot是如何统一处理全局异常的。既然是第一战,那就要来点不一样的,通常SpringBoot中的全局异常处理主要起作用的两个注解是@ControllerAdvice和@ExceptionHandler ,但是今天,我们用另一种方式,来更快更漂亮的拿下我们的Exception这个BOSS!

准备配置武器

第一步,规划武器模型

配置参数

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--lombok 依赖-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

<!--阿里 FastJson依赖-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>

第二步,升级武器物理伤害

消息code类

public enum ResultCode {
    SUCCESS("200"),//成功
    FAIL("400"),//失败
    NOT_FOUND("404"),//接口不存在
    INTERNAL_SERVER_ERROR("500"),//服务器内部错误
    ERROR("9999");

    private final String code;

    ResultCode(String code) {
        this.code = code;
    }

    public String code() {
        return code;
    }
}

第三步,升级武器法术伤害

返回的消息类

@Data
public class Result<T> {
    private String code;

    private String msg;

    private T data;

    public Result setCode(ResultCode resultCode) {
        this.code = resultCode.code();
        return this;
    }

    public Result setMsg(String msg) {
        this.msg = msg;
        return this;
    }

    public Result setData(T data) {
        this.data = data;
        return this;
    }
}

第四步,提升武器等级

返回工具类

public class ResultGenerator {
    private static final String DEFAULT_SUCCESS_MESSAGE = "成功";

    public static Result getSuccessResult() {
        return new Result()
                .setCode(ResultCode.SUCCESS)
                .setMsg(DEFAULT_SUCCESS_MESSAGE);
    }

    public static <T> Result<T> getSuccessResult(T data) {
        return new Result()
                .setCode(ResultCode.SUCCESS)
                .setMsg(DEFAULT_SUCCESS_MESSAGE)
                .setData(data);
    }

    public static Result getFailResult(String msg) {
        return new Result()
                .setCode(ResultCode.FAIL)
                .setMsg(msg);
    }

    public static Result getErrorResult(String msg) {
        return new Result()
                .setCode(ResultCode.ERROR)
                .setMsg(msg);
    }
}

第五步,根据爱好自定义武器外观

自定义异常

public class ServiceException extends RuntimeException {
    public ServiceException() {
    }

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

    public ServiceException(String message, Throwable cause) {
        super(message, cause);
    }
}

合成武器

使用WebMvcConfigurer拦截异常

public class WebMvcConfigurer extends WebMvcConfigurationSupport {
    //统一异常处理
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        exceptionResolvers.add(new HandlerExceptionResolver() {
            public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
                Result result = new Result();
                if (e instanceof ServiceException) {//业务失败的异常,如“账号或密码错误”
                    result.setCode(ResultCode.FAIL).setMsg(e.getMessage());
                    log.info(e.getMessage());
                } else if (e instanceof NoHandlerFoundException) {
                    result.setCode(ResultCode.NOT_FOUND).setMsg("接口 [" + request.getRequestURI() + "] 不存在");
                } else if (e instanceof ServletException) {
                    result.setCode(ResultCode.FAIL).setMsg(e.getMessage());
                } else {
                    result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMsg("接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员");
                    String message;
                    if (handler instanceof HandlerMethod) {
                        HandlerMethod handlerMethod = (HandlerMethod) handler;
                        message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s",
                                request.getRequestURI(),
                                handlerMethod.getBean().getClass().getName(),
                                handlerMethod.getMethod().getName(),
                                e.getMessage());
                    } else {
                        message = e.getMessage();
                    }
                    log.error(message, e);
                }
                responseResult(response, result);
                return new ModelAndView();
            }

        });
    }

    private void responseResult(HttpServletResponse response, Result result) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setStatus(200);
        try {
            response.getWriter().write(JSON.toJSONString(result));
        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
    }
}

开始战斗

@RestController
public class TestController {
    @GetMapping("getString")
    public Result getString(String name){

        if(StringUtils.isEmpty(name)){
            throw new ServiceException("参数为空");
        }else if ("boss".equals(name)) {
            // 这里没有查询操作,当请求参数是boss的时候,模拟成查询结果为空
            throw new ServiceException("结果为空");
        }
        // 这里模拟一下除自定义异常外的其他异常
        int i = 0;
        i = 5/i;
        return ResultGenerator.getFailResult("失败");
    }
}

成功击杀

最后看效果,是不是很简单:

装备掉落,如有需要,请自行拾荒:gitee.com/mochengyanl…