SpringMVC4️⃣拦截器 & 异常处理机制
-
AOP 思想
-
类似 Filter,但原理不同
过滤器(Filter) 拦截器(Interceptor) 说明 Servlet 规范定义 Spring 组件 实现原理 函数回调 Java 反射(动态代理) 使用范围 依赖于 Tomcat 等容器,仅在 Java Web 工程使用 任何使用 Spring 框架的工程 触发时机 在服务器和 Servlet 之间 在 Servlet 和 Controller 之间 配置方式 web.xml 的 url-pattern Spring 配置文件的 mvc:interceptor 拦截范围 任何要访问的资源,包括静态资源 Controller 请求
1、拦截器
处理器拦截器(HandlerInterceptor)
- 作用:对处理器进行预处理和后置处理。
- 链式调用(责任链模式):
- 在客户端和处理器之间,可以配置多个拦截器。
- 多个拦截器和处理器形成一条拦截器链,按配置顺序依次执行。
1.1、HandlerInterceptor
API
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception { return true; }
default void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
@Nullable ModelAndView modelAndView) throws Exception {}
default void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
@Nullable Exception ex) throws Exception {}
}
SpringMVC 执行流程:
接口调用(Controller) → DispatcherServlet → 处理器映射器 → 处理器适配器 → 视图解析器
preHandle() | postHandle() | afterCompletion() | |
---|---|---|---|
含义 | 预处理 | 后置处理 | 请求完成后处理 |
执行时机 | 接口方法调用前 | 接口调用后,DispatcherServlet 渲染视图前 | 渲染视图后 |
多个拦截器的执行顺序 | 与配置顺序相同 | 与配置顺序相反 | 与配置顺序相反 |
应用举例 | 初始化操作或预处理请求(如用户认证) | 设置 session 或 cookie | 清理资源 |
1.2、自定义拦截器
实现 HandlerInterceptor 接口
public class UserInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
User user = (User) request.getSession().getAttribute("user");
System.out.println(user);
return user != null;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("请求处理后");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("请求结束后");
}
}
配置 Interceptor(Spring MVC 配置文件)
-
/
:拦截请求,不拦截页面。 -
/*
:拦截包下所有资源,不包括子包。 -
/**
:拦截文件夹,包括子包。<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/user/**"/> <bean class="indi.jaywee.interceptor.UserInterceptor"/> </mvc:interceptor> </mvc:interceptors>
1.3、执行顺序 (❗)
拦截器的执行顺序
-
单个拦截器:
-
放行:preHandle → 处理请求 → postHandle → 请求完成,渲染视图 → afterCompletion()
-
拦截:preHandle → 拦截
-
-
多个拦截器(拦截器链)
-
放行:按配置顺序执行 preHandle → 处理请求 → 按配置相反顺序执行postHandle → 请求完成,渲染视图 → 按配置相反顺序执行 afterCompletion
-
拦截:preHandle → 拦截 → 从上一个拦截器开始,反向执行 afterCompletion
-
2、异常处理机制
2.1、异常
异常的处理方式:
-
传统思路:在可能发生异常的位置手动处理(捕获或向上抛出)。
-
Spring MVC:
-
每层都将本层异常向上抛出。
-
最后由 DispatcherServlet 调用
ExceptionHandler
统一处理。
-
2.2、ExceptionHandler
两种使用方式
- 简单映射异常处理器:Spring MVC 定义的 SimpleMappingExceptionResolver 类。
- 自定义异常处理器:实现 HandlerExceptionResolver 接口。
2.2.1、简单映射
直接配置即可使用
视图名会与视图解析器结合生效。
-
exceptionMappings:异常映射,将指定异常映射到指定视图名。
-
defaultErrorView:默认错误页面,当发生的异常匹配不到异常映射中的任何配置时生效。
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="defaultErrorView" value="/error/default"/> <property name="exceptionMappings"> <map> <entry key="java.lang.ArithmeticException" value="/error/1"/> </map> </property> </bean>
2.2.2、自定义
自定义异常处理器,配置即可使用
-
自定义异常处理器:实现 HandlerExceptionResolver 接口
@Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { ModelAndView mv = new ModelAndView(); mv.setViewName("/error/default"); return mv; }
-
配置:注册 Bean 即可
<bean class="indi.jaywee.utils.MyExceptionResolver"/>