zoukankan      html  css  js  c++  java
  • spring拦截器和过滤器

    1.什么是拦截器
      拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略。它通过动态拦截Action调用的对象,允许开发者定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。
    2.拦截器作用
      拦截用户的请求并进行相应的处理,比如:判断用户是否登陆,是否在可购买时间内,记录日志信息等。

    3.Spring中两种实现方式
      通过实现HandlerInterceptor接口, 一般通过继承HandlerInterceptorAdapter抽象类实现。
      DispatcherServlet处理流程:DispatcherServlet处理请求时会构造一个Excecution Chain,即(可能多个)拦截器和真正处理请求的Handler
    即Interceptor是链式调用的。
      preHandle: 在执行Handler之前进行,即Controller方法调用之前执行,主要进行初始化操作。
      postHandle: 在执行Handler之后进行,即Controller 方法调用之后执行,主要对ModelAndView对象进行操作。
      afterCompletion: 在整个请求结束之后,即渲染对应的视图之后执行, 主要进行资源清理工作

      HandlerInterceptor接口有三个需要实现的方法:preHandle(),postHandle()和afterCompletion()。
    preHandle方法将在请求处理之前调用,SpringMVC中的Interceptor是链式调用的,每个Interceptor的调用都根据它的声明顺序依次执行,且最先执行其preHandle方法,所以可以在该方法中进行一些前置初始化操作或是预处理。该方法的返回值是布尔类型,如果返回false,表示请求结束,后续的Interceptor和Controller都不会再执行了,如果返回true就执行下一个拦截器的preHandle方法,一直到最后一个拦截器preHandle方法执行完成后调用当前请求的Controller方法。
      postHandle方法是在当前请求进行处理之后,也就是Controller方法调用结束之后执行,但是它会在DispatcherServlet进行视图渲染之前被调用,所以可以在这个方法中可以对Controller处理之后的ModelAndView对象进行操作。postHandle方法被调用的方向跟preHandle是相反的,也就是说先声明的Interceptor的postHandle方法反而后执行。
    afterCompletion方法需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。该方法会在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行,这个方法的主要作用是用于资源清理工作。

    SpringMVC的拦截器Interceptor和过滤器Filter功能非常相似,使用场景也差不多,看起来难以区分。比如两者都能在代码前后插入执行片段,都可以用来实现一些公共组件的功能复用(权限检查、日志记录等),其实它们并不一样,首先了解一下Interceptor和Filter

    一.Interceptor拦截器
    springmvc拦截器的配置
    1.自定义拦截器,实现HandlerInterceptor接口。
    package com.bybo.aca.web.interceptor;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    public class Login implements HandlerInterceptor {

    @Override
    public void afterCompletion(HttpServletRequest httpRequest,
    HttpServletResponse httpResponse, Object arg2, Exception arg3)
    throws Exception {
    }
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
    Object arg2, ModelAndView arg3) throws Exception {
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
    Object object) throws Exception {
    String urlString = request.getRequestURI();
    if(urlString.endsWith("forumList.html")){
    return true;
    }
    //请求的路径
    String contextPath=request.getContextPath();
    response.sendRedirect(contextPath + "/olForum/forumList.html?login=aaa");
    return false;
    }
    }

    2:springmvc配置文件中配置:
    <!-- 扫描controller(controller层注入) -->
    <context:component-scan base-package="com.bybo.aca.web.controller"/>
    <mvc:interceptors>
    <mvc:interceptor>
    <!-- 进行拦截:/**表示拦截所有controller -->
    <mvc:mapping path="/**" />
       <!-- 不进行拦截 -->
    <mvc:exclude-mapping path="/index.html"/>
    <bean class="com.bybo.aca.web.interceptor.Login"/>
    </mvc:interceptor>
    </mvc:interceptors>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
    p:prefix="/WEB-INF/views/" p:suffix=".jsp"/>
    </beans>

    二.Filter过滤器
    Filter是Spring过滤器,要定义一个Filter类有以下步骤:
    首先定义一个Filter类,继承javax.servlet.Filter类,重写其init、doFilter、destroy方法。
    init()方法会在Filter初始化后进行调用,在init()方法里面我们可以通过FilterConfig访问到初始化参数( getInitParameter()或getInitParameters() )、ServletContext (getServletContext)和当前Filter部署的名称( getFilterName() )等信息。
    destroy()方法将在Filter被销毁之前调用。
    而doFilter()方法则是真正进行过滤处理的方法,在doFilter()方法内部,我们可以过滤请求的request和返回的response,同时我们还可以利用FilterChain把当前的request和response传递给下一个过滤器或Servlet进行处理。

    public class FilterTest implements Filter {
    @Autowired
    private PointService pointService;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    System.out.println("init yes");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    System.out.println("filter test");
    filterChain.doFilter(servletRequest, servletResponse); // 传递给下一个Filter进行处理
    return;
    }

    @Override
    public void destroy() {
    System.out.println("destroy yes");
    }
    }

    然后在配置中使该Filter生效:

    <filter>
    <filter-name>filtertest</filter-name>
    <filter-class>FilterTest</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>filtertest</filter-name>
    <url-pattern>/point/*</url-pattern>
    </filter-mapping>


    这样,当我们访问/point/*类型的url,控制台输出如下:
    init yes
    filter test
    controller
    三.比较
    同时配置过滤器和拦截器然后请求,结果如下:
    init yes
    filter test
    interceptortest pre
    controller
    interceptortest post
    interceptortest after
    可以看到filter优先于interceptor被调用。
    过滤器和拦截器主要区别如下:
    1.二者适用范围不同。Filter是Servlet规范规定的,只能用于Web程序中,而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。
    2.规范不同。Filter是在Servlet规范定义的,是Servlet容器支持的,而拦截器是在Spring容器内的,是Spring框架支持的。
    3.使用的资源不同。同其他代码块一样,拦截器也是一个Spring的组件,归Spring管理,配置在Spring文件中,因此能使用Spring里的任何资源、对象(各种bean),而Filter不行。
    4.深度不同。Filter只在Servlet前后起作用,而拦截器能够深入到方法前后、异常跑出前后等,拦截器的使用有更大的弹性

  • 相关阅读:
    导入excel
    aspx页面调用发送邮件验证码(结合前两篇)
    随机生成数字(ashx文件,调用上篇所写发送邮件代码)
    C#邮箱发送验证码
    linq查询一个字段的总和
    随部分div增高总的div也随着增高
    视图显示库存余量
    利用存储过程把两个表的数据插入到一个新表中(存储过程中写两个游标)
    使用kindeditor文本编辑器
    MSSQLServer 2016 安装遇到的问题
  • 原文地址:https://www.cnblogs.com/bcl88/p/10412553.html
Copyright © 2011-2022 走看看