SpringMVC学习系列(五)------异常处理

本文介绍了SpringMVC中两种全局异常处理的方法:配置方式和注解方式,并详细阐述了各自的实现过程及优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

    SpringMVC在请求过程中出现异常后都是交由异常处理器来处理的,自定义异常处理器可以实现一个系统的异常处理逻辑。

正文

异常处理的思路

    系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获得异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生。
    系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:
这里写图片描述
(一)配置方式实现全局异常处理

自定义异常类

    为了区别不同的异常,在这里我们自定义一个系统异常,日过controller、service、dao抛出此类异常说明是系统预期的异常信息。

package com.xiaojian.springmvc.exception;
/**
 * 自定义的异常
 * @author wyz
 *
 */
public class MyException extends Exception {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public MyException(String message) {
        super(message);
        this.message = message;
    }


    private String message;

    public String getMessage() {
        return message;
    }

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

    异常定义好以后,我们要自定义异常的处理逻辑,在这里我们需要自定义一个异常处理器,在SpringMVC中,要自定义异常处理器,就要自定义一个类,实现HandlerExceptionResolver接口:

package com.xiaojian.springmvc.exception;

import java.io.PrintWriter;
import java.io.StringWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
/**
 * 自定义全局异常处理器
 * @author wyz
 *
 */
public class GlobalExceptionResolver implements HandlerExceptionResolver {

    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
            Exception ex) {
        String msg ;
        if (ex instanceof MyException) {
            //如果是自定义异常
            MyException myException = (MyException) ex;
            msg = myException.getMessage();
        }else {
            ex.printStackTrace();
            StringWriter s = new StringWriter();
            PrintWriter printWriter = new PrintWriter(s);
            ex.printStackTrace(printWriter);
            msg = s.toString();
        }
        //处理其他的业务逻辑
        //返回错误页面
        ModelAndView model = new ModelAndView();
        model.addObject("msg", msg);
        model.setViewName("/WEB-INF/jsp/error.jsp");
        return model;
    }

}

在这个例子中,我返回了一个error的jsp页面,页面简单的取出了错误信息:

<body>
    <h1>错误页面</h1>
    ${msg}
</body>
</html>

除此之外,要想异常被正常拦截, 还要再springmvc.xml文件中配置异常处理器,或者直接在上面加上@Component注解,配置方式如下:

<bean id="handlerExceptionResolver" class="com.xiaojian.springmvc.exception.GlobalExceptionResolver" />

现在我们来测试一下,我们在controller的方法中修改一下,添加一个除零异常:

    @RequestMapping("/login")
    public ModelAndView login(User user, ModelAndView model, Date texttime) {

        int i = 10 / 0 ;
        System.out.println(user.getUsername());
        System.out.println(user.getPassword());
        System.out.println(texttime);
        model.addObject("data", "登录成功");
        model.addObject("texttime", new Date());
        model.setViewName("/WEB-INF/jsp/login.jsp");
        return model;
    }

访问页面:http://localhost:8080/demo/login.action
结果如下:
这里写图片描述
    以上就是通过配置的方式,自定义异常,下面还有一种更为方便的注解方式来实现相同的功能,推荐大家使用第二种。
(二)注解方式实现全局异常处理
    除了以上的全局异常处理,Spring官方还推荐我们使用注解的方式优雅的实现全局异常处理。即使用@ControllerAdvice 、@ExceptionHandler这两个注解来实现异常处理。
首先自定义异常类:

public class MyException extends RuntimeException  {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public MyException(String message) {
        super(message);
        this.message = message;
    }


    private String message;

    public String getMessage() {
        return message;
    }

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

然后自定义全局异常处理器:

@ControllerAdvice
public class GlobalExceptionResolver {

    @ExceptionHandler(value = MyException.class)
    @ResponseBody
    public String myExceptionHandler(MyException e) {
        return "{'msg':'222222'}";
    }   

    @ExceptionHandler(value = Exception.class)
    public ModelAndView exceptionHandler() {
        return new ModelAndView("/WEB-INF/jsp/error.jsp");
    };

}

在这个处理器中,我们在捕获到自定义异常的时候,向页面返回了一个json。
还要在springmvc中配置好这个处理器,使之被容器扫描:

<bean id="handlerExceptionResolver" class="com.xiaojian.springmvc.exception.GlobalExceptionResolver" />

在controller中定义异常:

    @RequestMapping("/login")
    public ModelAndView login(User user, ModelAndView model, Date texttime) {

        //int i = 10 / 0 ;
        if (true) {
            throw new MyException("这个是注解实现的自定义异常");
        }
        model.addObject("data", "登录成功");
        model.addObject("texttime", new Date());
        model.setViewName("/WEB-INF/jsp/login.jsp");
        return model;
    }

启动项目,访问http://localhost:8080/demo/login.action后显示如下:
这里写图片描述

总结

    以上两种就是全局异常处理的两种方式,在实际工作做,还是比较推荐使用第二种,相比于第一种,它主要有一下几点优点:

  • 使用注解的方式代码看上去更加的清晰。
  • 对于自定义异常的捕获会很方便。
  • 适用于对于返回json格式的情况(可以使用@ResponseBody注解方法对特定异常进行处理),使用HandlerExceptionResolver的话如果是ajax的请求,出现异常就会很尴尬,ajax并不认识ModelAndView。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值