SpringMVC --- 拦截器

一、简介

  1. SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术。
  2. 可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链中的拦截器会按着定义的顺序执行。
  3. 拦截器和过滤器的功能比较类似,有区别
    • 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。
    • 拦截器是SpringMVC框架独有的。
    • 过滤器配置了/*,可以拦截任何资源。
    • 拦截器只会对控制器中的方法进行拦截。
  4. 拦截器也是AOP思想的一种实现方式
  5. 想要自定义拦截器,需要实现HandlerInterceptor接口。

二、拦截器实现步骤

  1. 创建类,实现HandlerInterceptor接口,重写需要的方法
package com.ycw.ssm.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;

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

/**
 * @author ycw
 */
public class MyInterceptor1 implements HandlerInterceptor {
    /**
     * controller方法执行前,进行拦截的方法
     * return true放行
     * return false拦截
     * 可以使用转发或者重定向直接跳转到指定的页面。
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler)
            throws Exception {
        System.out.println("拦截器执行了...");
        return true;
    }

}

  1. 在springmvc.xml中配置拦截器类


    
        
        
        
        
        
    

  1. 配置多个拦截器
    再编写一个拦截器的类,配置2个拦截器


    
        
        
        
        
        
    
    
        
        
        
        
    

三、HandlerInterceptor接口中的方法

  1. preHandle方法是controller方法执行前拦截的方法
    • 可以使用request或者response跳转到指定的页面
    • return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
    • return false不放行,不会执行controller中的方法。
  2. postHandle是controller方法执行后执行的方法,在JSP视图执行前。
    • 可以使用request或者response跳转到指定的页面
    • 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
  3. postHandle方法是在JSP执行后执行
    • request或者response不能再跳转页面了

四、原理剖析

拦截器在SpringMVC框架中实现是非常简单的,但是当我们感觉简单的时候肯定有别人帮我们完成了一些工作,帮我们干了一些工作的就是我们使用的SpringMVC框架了。

SpringMVC框架的入口是一个使用Servlet实现的前端控制器:
org.springframework.web.servlet.DispatcherServlet
我们的每次请求都会先经过这个入口的处理才能到达目标资源。该类中,最重要的一个方法是 doDispatch() ,在这个方法中,完成了整个执行流程的任务分配:
我们来看看部分的核心代码:

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

        try {
            ModelAndView mv = null;
            Object dispatchException = null;
            try {
                processedRequest = this.checkMultipart(request);
                multipartRequestParsed = processedRequest != request;

                //返回 HandlerExecutionChain  其中包含了拦截器队列
                mappedHandler = this.getHandler(processedRequest);

                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    this.noHandlerFound(processedRequest, response);
                    return;
                }

                //获取到适合处理当前请求的适配器,最终用来调用Controller中的方法
                HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());

                //调用拦截器链中所有拦截器的preHandle方法
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    //如果有拦截器的preHandle方法返回值为false,则结束该方法的执行
                    return;
                }
                //调用请求的Controller中的方法,获取到ModelAndView对象
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                //调用拦截器链中所有拦截器的postHandle方法,和执行preHandle方法的顺序相反
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            } catch (Exception var19) {
                dispatchException = var19;
            }
            //处理视图渲染
            this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        } catch (Exception var20) {
            //如果在执行过程中有异常,执行后续的收尾工作,执行对应拦截器中的afterCompletion方法
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20);
        }
    }
  1. mappedHandler = this.getHandler(processedRequest);
    返回 HandlerExecutionChain 其中包含了拦截器队列

  2. HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
    获取到适合处理当前请求的适配器,最终用来调用Controller中的方法

  3. mappedHandler.applyPreHandle(processedRequest, response)
    调用拦截器链中所有拦截器的preHandle方法

  4. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    调用请求的Controller中的方法,获取到ModelAndView对象

  5. mappedHandler.applyPostHandle(processedRequest, response, mv);
    调用拦截器链中所有拦截器的postHandle方法,和执行preHandle方法的顺序相反

  6. this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    处理结果视图的渲染,简单说就是页面的跳转问题

  7. this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20);
    如果在执行过程中有异常,执行后续的收尾工作,执行对应拦截器中的afterCompletion方法

通过上面对DispatcherServlet中核心代码的分析,相信大家对拦截器的执行流程有了大致的理解。

你可能感兴趣的:(SpringMVC --- 拦截器)