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. 作用对处理器进行预处理和后置处理
  2. 链式调用(责任链模式):
    1. 在客户端和处理器之间,可以配置多个拦截器。
    2. 多个拦截器和处理器形成一条拦截器链,按配置顺序依次执行。

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 → 拦截

      image.png

  • 多个拦截器(拦截器链)

    • 放行按配置顺序执行 preHandle → 处理请求 → 按配置相反顺序执行postHandle → 请求完成,渲染视图 → 按配置相反顺序执行 afterCompletion

    • 拦截:preHandle → 拦截 → 从上一个拦截器开始,反向执行 afterCompletion

      image-20220401112432374

2、异常处理机制

2.1、异常

Java 异常

异常的处理方式

  • 传统思路:在可能发生异常的位置手动处理(捕获或向上抛出)。

  • Spring MVC

    1. 每层都将本层异常向上抛出

    2. 最后由 DispatcherServlet 调用 ExceptionHandler 统一处理

      image-20220401113456712

2.2、ExceptionHandler

两种使用方式

  1. 简单映射异常处理器:Spring MVC 定义的 SimpleMappingExceptionResolver 类。
  2. 自定义异常处理器:实现 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、自定义

自定义异常处理器,配置即可使用

  1. 自定义异常处理器:实现 HandlerExceptionResolver 接口

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/error/default");
        return mv;
    }
    
  2. 配置:注册 Bean 即可

    <bean class="indi.jaywee.utils.MyExceptionResolver"/>
    
posted @ 2021-08-21 23:53  Jaywee  阅读(211)  评论(0编辑  收藏  举报

👇