SpringMVC(七)异常处理和拦截器

SpringMVC(七)异常处理 和拦截器

系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理

异常处理

编写异常类和错误页面
// 自定义异常
public class CustomException extends Exception {
   private String message;

   @Override
   public String getMessage() {
       return message;
   }

   public CustomException(String message) {
       this.message = message;
   }
}
<!--error.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
   <title>Title</title>
</head>
<body>
执行失败!
${message}
</body>
</html>
自定义异常处理器
// 自定义异常解析器,处理自定义和系统异常用的
public class CustomExceptionResolver implements HandlerExceptionResolver {
   @Override
   public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
       // 输出异常到控制台
       ex.printStackTrace();
       // 定义自定义异常对象
       CustomException ce = null;
       //判断ex是不是自定义异常
       if (ex instanceof CustomException) {
           //如果抛出的是系统自定义异常则直接转换
           ce = (CustomException) ex;
       } else {
           //如果抛出的不是系统自定义异常则重新构造一个系统错误异常
           ce = new CustomException("服务器忙!");
       }
       ModelAndView mv = new ModelAndView();
       mv.setViewName("error");
       mv.addObject("message", ce.getMessage());
       return mv;
   }
}
配置异常处理器
<!-- SpringMVC.xml 配置自定义异常处理器 -->
<bean id="handlerExceptionResolver"
     class="fun.chenqi.exception.CustomExceptionResolver"
/>
测试类:
@Controller
@RequestMapping("/error")
public class ErrorHander {

   @RequestMapping("/err")
   public String err(User user) throws Exception {
       if (StringUtils.isEmpty(user.getUsername()) || user.getUsername().trim().equals("")) {
           throw new CustomException("用户名不能为空!");
       }
       if (user.getAge() > 150) {
           throw new CustomException("年龄不合法!");
       }
       // 系统异常
       // int i = 1/0;
       return "ok";
   }
}
<form action="error/err" method="post">
   用户名称:<input type="text" name="username"><br/>
   用户年龄:<input type="text" name="age"><br/>
   <input type="submit" value=" 保存 ">
</form>

SpringMVC 中的拦截器

Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。用户可以自己定义一些拦截器来实现特定的功能。谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但是也有区别,接下来我们就来说说他们的区别:过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。它也是 AOP 思想的具体应用。我们要想自定义拦截器, 要求必须实现:HandlerInterceptor  接口。

编写一个普通类实现 HandlerInterceptor  接口
// 自定义拦截器
public class HandlerInterceptorDemo1 implements HandlerInterceptor {
   /**
    * 此方法是拦截的方法,它决定了程序能否继续访问
    * 它的返回值为true时,表示放行
    * 返回值为false时,表示不放行
    * 当此方法执行时,控制器的方法还没有执行。
    * 由于它有request和response对象,此处就可以决定最终结果视图由显示。
    *
    * @param request
    * @param response
    * @param handler
    * @return
    * @throws Exception
    */
   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       //        request.setAttribute("message","拦截器没放行");
       //        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
       System.out.println("preHandle拦截器拦截了...1111");
       return true;
   }

   /**
    * 放行之后,执行完控制器方法之后,就会执行此方法。
    * 此时已经有了响应数据。我们可以在此处对响应部分增强。
    * 在执行此方法时,结果视图还没有生成,所以此方法的request和response仍然可以控制最终响应的结果视图。
    *
    * @param request
    * @param response
    * @param handler
    * @param modelAndView
    * @throws Exception
    */
   @Override
   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
       System.out.println("postHandle执行了...111");
       // response.sendRedirect("http://www.baidu.com");
   }

   /**
    * 它的执行时机,是当结果视图也执行完成之后,此方法执行。
    * 只要是拦截器的preHandle方法返回值是true,此方法就一定会执行
    * 此方法可以做一些清理操作
    *
    * @param request
    * @param response
    * @param handler
    * @param ex
    * @throws Exception
    */
   @Override
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
       System.out.println("afterCompletion执行了...111");
   }
}
配置拦截器
<!--SpringMVC.xml 配置拦截器-->
<mvc:interceptors>
   <mvc:interceptor>
       <mvc:mapping path="/**"/>
       <bean id="handlerInterceptorDemo1" class="fun.chenqi.interceptors.HandlerInterceptorDemo1"></bean>
   </mvc:interceptor>
</mvc:interceptors>
<%-- 自定义拦截器 --%>
<a href="inter/testInterceptor">自定义拦截器</a>

发表评论