SpringMVC学习04:异常处理器和拦截器
异常处理器
当程序发生错误时,错误最终会传递给DispatcherServlet
,由DispatcherServlet
进行异常处理.
下面演示使用SpringMVC的异常处理机制处理异常
-
创建自定义异常类
package cn.maoritian.exception; public class SysException extends Exception { // 存储提示信息的 private String message; // 构造方法 public SysException(String message) {this.message = message; } // get,set方法 public String getMessage() {return message; } public void setMessage(String message) {this.message = message; } }
-
创建异常处理器,异常处理器必须实现
HandlerExceptionResolver
接口,其resolveException()
方法执行异常处理.package cn.maoritian.exception; // 自定义异常处理器 public class MyExceptionResolver implements HandlerExceptionResolver { public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { myException e = null; if (ex instanceof myException) { e = (myException) ex; } else { e = new myException("其他错误"); } ModelAndView mv = new ModelAndView(); mv.addObject("errorMsg", e.getMessage()); // 封装错误信息 mv.setViewName("error"); // 跳转页面 return mv; } }
-
向Spring容器中注入异常处理器
<!--配置异常处理器--> <bean id="myExceptionResolver" class="cn.maoritian.exception.MyExceptionResolver"/>
这样,SpringMVC就能处理异常了.
拦截器
拦截器的配置
SpringMVC中的拦截器只能拦截Controller
中的方法,下面演示拦截器的使用
-
自定义拦截器需要继承
HandlerInterceptor
接口,该接口中定义了三个方法,都已有其默认实现:preHandle(...)
: 该方法在处理器方法实际执行之前执行postHandle(...)
: 该方法在处理器方法实际执行完毕以后执行afterCompletion(...)
: 该方法在整个请求处理完成后执行
其中
preHandle(..)
方法返回一个boolean
值,可以通过这个方法来决定是否继续执行处理链中的部件。当方法返回true
时,处理器链会继续执行;若方法返回false
,DispatcherServlet
即认为拦截器自身已经完成了对请求的处理(比如说,已经渲染了一个合适的视图),那么其余的拦截器以及执行链中的其他处理器就不会再被执行了。package samples; public class TimeBasedAccessInterceptor extends HandlerInterceptor { private int openingTime; private int closingTime; public void setOpeningTime(int openingTime) {this.openingTime = openingTime; } public void setClosingTime(int closingTime) {this.closingTime = closingTime; } public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Calendar cal = Calendar.getInstance(); int hour = cal.get(HOUR_OF_DAY); if (openingTime <= hour && hour < closingTime) { return true; } response.sendRedirect("http://host.com/outsideOfficeHours.html"); return false; } }
-
向Spring容器中注入拦截器
<mvc:interceptors> <mvc:interceptor> <!-- 拦截的方法 --> <mvc:mapping path="/**" /> <!-- 具体的拦截器 --> <bean id="officeHoursInterceptor" class="cn.maoritian.interceptor.TimeBasedAccessInterceptor"> <property name="openingTime" value="9"/> <property name="closingTime" value="18"/> </bean> </mvc:interceptor> </mvc:interceptors>
多个拦截器的执行顺序
多个拦截器的执行顺序是由外向内分层执行的
配置两个拦截器如下:
<!-- 配置三个拦截器 -->
<mvc:interceptors>
<!-- 配置拦截器1 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.maoritian.controller.cn.maoritian.interceptor.MyInterceptor1"/>
</mvc:interceptor>
<!-- 配置拦截器2 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.maoritian.controller.cn.maoritian.interceptor.MyInterceptor2"/>
</mvc:interceptor>
<!-- 配置拦截器3 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.maoritian.controller.cn.maoritian.interceptor.MyInterceptor3"/>
</mvc:interceptor>
</mvc:interceptors>
访问该域名下Handler
时,服务器输出如下:
Interceptor1的preHandle()方法执行了
Interceptor2的preHandle()方法执行了
Interceptor3的preHandle()方法执行了
Handler中的方法执行了
Interceptor3的postHandle()方法执行了
Interceptor2的postHandle()方法执行了
Interceptor1的postHandle()方法执行了
跳转到的jsp中的java脚本执行了
Interceptor3的afterCompletion()方法执行了
Interceptor2的afterCompletion()方法执行了
Interceptor1的afterCompletion()方法执行了