SpringMVC—异常处理

SpringMVC异常处理

一、引言

  一般项目开发中有两类异常:

  • 预期异常
  • 运行时异常

其中预期异常一般是由程序员主动抛出的异常,而运行时异常很难控制,只能通过规范代码编写、增加测试等手段来减少该类异常。

  通常项目是分层开发的,由外到内可分为前端项目、前端控制器、控制层、业务层、持久层。如果在控制层、业务层或持久层出现异常,SpringMVC框架如何处理呢?我们可以在前端控制器中定义全局异常处理器,之后如果控制层、业务层或持久层出现异常,直接往外抛异常即可。关于全局异常处理器,有如下定义方法:

  1. 基于注解的异常处理

  2. 基于配置的异常处理

二、示例

2.1 基于注解的异常处理

  首先,定义一个业务异常,该异常作为预期异常在项目中手动抛出。

java 复制代码
public class CustomException extends RuntimeException {
	
    private AppHttpCodeEnum appHttpCodeEnum;

    public CustomException(AppHttpCodeEnum appHttpCodeEnum){
        this.appHttpCodeEnum = appHttpCodeEnum;
    }

    public AppHttpCodeEnum getAppHttpCodeEnum() {
        return appHttpCodeEnum;
    }
}

其中AppHttpCodeEnum类是一个枚举类,用于指定http响应状态码和响应信息,定义如下。

java 复制代码
public enum AppHttpCodeEnum {

    // 成功段0
    SUCCESS(200,"操作成功"),
    // 登录段1~50
    NEED_LOGIN(1,"需要登录后操作"),
    LOGIN_PASSWORD_ERROR(2,"密码错误"),
    // TOKEN50~100
    TOKEN_INVALID(50,"无效的TOKEN"),
    TOKEN_EXPIRE(51,"TOKEN已过期"),
    TOKEN_REQUIRE(52,"TOKEN是必须的"),
    // SIGN验签 100~120
    SIGN_INVALID(100,"无效的SIGN"),
    SIG_TIMEOUT(101,"SIGN已过期"),
    // 参数错误 500~1000
    PARAM_REQUIRE(500,"缺少参数"),
    PARAM_INVALID(501,"无效参数"),
    PARAM_IMAGE_FORMAT_ERROR(502,"图片格式有误"),
    SERVER_ERROR(503,"服务器内部错误"),
    // 数据错误 1000~2000
    DATA_EXIST(1000,"数据已经存在"),
    AP_USER_DATA_NOT_EXIST(1001,"用户数据不存在"),
    DATA_NOT_EXIST(1002,"数据不存在"),
    // 数据错误 3000~3500
    NO_OPERATOR_AUTH(3000,"无权限操作"),
    NEED_ADMIND(3001,"需要管理员权限");

    int code;
    String errorMessage;

    AppHttpCodeEnum(int code, String errorMessage){
        this.code = code;
        this.errorMessage = errorMessage;
    }

    public int getCode() {
        return code;
    }

    public String getErrorMessage() {
        return errorMessage;
    }
}

之后,通过@ControllerAdvice和@ExceptionHandler注解定义全局异常处理器,分别捕获自定义的业务异常和不可控异常。

java 复制代码
@ControllerAdvice  //控制器增强类
public class ExceptionCatch {

    /**
     * 处理不可控异常
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseResult exception(Exception e){
        e.printStackTrace();
        return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
    }

    /**
     * 处理可控异常  自定义异常
     * @param e
     * @return
     */
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult exception(CustomException e){
        return ResponseResult.errorResult(e.getAppHttpCodeEnum());
    }
} 

其中ResponseResult类是一个向前端返回的统一结果类。

java 复制代码
public class ResponseResult<T> implements Serializable {

    private String host;

    private Integer code;

    private String errorMessage;

    private T data;

    public ResponseResult() {
        this.code = 200;
    }

    public ResponseResult(Integer code, T data) {
        this.code = code;
        this.data = data;
    }

    public ResponseResult(Integer code, String msg, T data) {
        this.code = code;
        this.errorMessage = msg;
        this.data = data;
    }

    public ResponseResult(Integer code, String msg) {
        this.code = code;
        this.errorMessage = msg;
    }

    public static ResponseResult errorResult(int code, String msg) {
        ResponseResult result = new ResponseResult(code, msg);
        return result;
    }


    public static ResponseResult errorResult(AppHttpCodeEnum enums) {
        return setAppHttpCodeEnum(enums, enums.getErrorMessage());
    }

    public static ResponseResult errorResult(AppHttpCodeEnum enums, String errorMessage) {
        return setAppHttpCodeEnum(enums, errorMessage);
    }

    public static ResponseResult okResult(int code, String msg) {
        ResponseResult result = new ResponseResult(code, msg);
        return result;
    }

    public static ResponseResult okResult(Object data) {
        ResponseResult result = setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        if (data != null) {
            result.setData(data);
        }
        return result;
    }

    public static ResponseResult okResult(AppHttpCodeEnum enums) {
        ResponseResult result = setAppHttpCodeEnum(enums);
        return result;
    }


    public static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums) {
        return okResult(enums.getCode(), enums.getErrorMessage());
    }

    private static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums, String errorMessage) {
        return okResult(enums.getCode(), errorMessage);
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    public T getData() {
        return data;
    }

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

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }
}

2.2 基于配置的异常处理

  SpringMVC提供了一个自定义异常处理器的接口,我们通过实现@HandlerExceptionResolver接口来捕获异常。

java 复制代码
public class GlobalExceptionResolver implements HandlerExceptionResolver {
​
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
            Exception exception) {
        //根据实际业务编写代码
        return null;
    }
}

然后在spring配置文件中配置刚才新建的全局异常处理器,或者加上@Component注解。

xml 复制代码
<!--全局异常捕捉 -->
<bean class="包名.GlobalExceptionResolver" />
相关推荐
Thomas.Sir12 分钟前
第6课:SpringBoot4.x 核心注解全解:Component、Bean、Scope、Lazy等IOC相关注解
java·spring boot
paopaokaka_luck14 分钟前
美食推荐系统(协同过滤算法推荐、AI助手、HanLP中文分词、 ECharts可视化分析、菜谱学习与话题交流)
java·spring boot·mysql·tomcat·echarts
开源推荐官16 分钟前
2026 年开源商城源码选型参考:技术栈、功能与适用场景梳理
java·架构·开源
sunburn-30 分钟前
数据库操作完整教程:从基础到实战
java·数据库·mysql
文丑颜不良啊36 分钟前
LeetCode576~600题目解析
java·leetcode
Linux运维技术栈1 小时前
CVE-2026-91403 高危漏洞预警:Java JSSE 信任链被攻破 全场景修复方案与Linux系统级彻底清理实操
java·linux·安全·jdk·信任链
秋饼1 小时前
Spring AI + MCP 工具调用可靠性实战:参数校验、权限防线与人工确认生产级落地
java·ai·技术分享·后端开发
步行cgn1 小时前
RESTful 是什么?怎么记住它?
java
随性而行3601 小时前
企业微信 Webhook 接收不到消息?网络连通性、URL 签名验签与 API 返回错误码排查指南
java·网络·人工智能·后端·微信·企业微信
薛之谦_1 小时前
JD Hotkey 项目实战:京东开源的热点探测与秒杀系统
java·安全