您的位置:首页 > 其它

过滤器与拦截器_学习笔记

2020-07-09 10:06 369 查看

过滤器与拦截器

  • 拦截器(Interceptor)
  • 过滤器与拦截器的区别
  • 过滤器(Filter)

    过滤器是Java EE中的组件。

    过滤器是执行在Servlet之前的组件。

    过滤器可以对请求进行过滤,如果不满足自行指定的条件,可以拦截下来,不予放行,请求就不会被Servlet处理。

    过滤器也需要在web.xml中配置注册,通常,映射的路径范围较大,因为它通常用于处理多个甚至所有Servlet需要执行的任务。

    同一个应用中可以存在多个过滤器,形成“过滤器链”,当某个请求被服务器处理时,会依次执行各个过滤器,只有全部放行,才会被Servlet处理。

    1.过滤器的优点

    a.可以在不修改源代码的基础上,为应用添加新的功能。
    b.可以将多个组件相同的功能集中写在过滤器里面,方便代码的维护。

    2.如何写一个过滤器

    step1.写一个java类,实现Filter接口。

    step2.在doFilter方法里面,实现拦截处理逻辑。

    step3.配置过滤器。(web.xml)

    <filter>
    <filter-name>commentFilter2</filter-name>
    <filter-class>web.CommentFilter2</filter-class>
    <init-param>
    <param-name>size</param-name>
    <param-value>5</param-value>
    </init-param>
    </filter>
    <filter-mapping>
    <filter-name>commentFilter2</filter-name>
    <url-pattern>/comment</url-pattern>
    </filter-mapping>
    
    <filter>
    <filter-name>commentFilter</filter-name>
    <filter-class>web.CommentFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>commentFilter</filter-name>
    <url-pattern>/comment</url-pattern>
    </filter-mapping>

    容器启动后会检查配置文件,把里面所以有的过滤器先实例化,将实例化后的对象放到FilterChain对象中(过滤器链),顺序按照优先级存放(配置文件的先后顺序),

    package filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    
    @WebFilter(filterName = "CommentFilter",urlPatterns = "/comment")
    public class CommentFilter implements Filter {
    /**
    * 容器启动之后,会立即创建过滤器实例。
    * 注:
    * 	 只会创建一个实例!
    */
    public CommentFilter() {
    System.out.println("------------CommentFilter()-------------------");
    }
    /**
    * 容器在创建好过滤器实例之后,会立即
    * 调用该实例的init方法。
    * 注:
    * 		该方法只会调用一次!
    */
    public void init(FilterConfig config) throws ServletException {
    System.out.println("-----------CommentFilter----init()-----------------------");
    }
    /**
    * 容器在调用完过滤器的init方法之后,
    * 会调用doFilter方法来处理请求。
    * 注:(了解)
    *    ServletRequest是HttpServletRequest
    *    的父接口,ServletResponse是
    *    HttpServletResponse的父接口。
    *
    * FilterChain(过滤器链):
    * 		如果调用了该对象的doFilter方法,
    * 表示继续向后调用;否则,中断请求,返回
    * 处理结果。
    *
    */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
    System.out.println("------------commentFileter's doFilter()---------------");
    chain.doFilter(request, response);
    }
    
    public void destroy() {
    }
    }

    控制台输出:

    过滤器的配置与Servlet非常相似:

    <filter>
    <filter-name></filter-name>
    <filter-class></filter-class>
    </filter>
    
    <filter-mapping>
    <filter-name></filter-name>
    <url-pattern></url-pattern>
    </filter-mapping>

    拦截器(Interceptor)

    1基本概念

    拦截器是SpringMVC中的组件,执行时优先于控制器(其实,每个拦截器都会执行3次,1次在控制器之前,2次在控制器之后,通常关注的是在控制器之前执行的那一次)。

    2基本使用

    step1:写拦截器类

    自定义拦截器需要实现

    HandlerInterceptor
    接口,该接口中共3个抽象方法,其中,
    preHandle()
    方法是在控制器之前执行的,可以起到拦截效果,该方法的返回值表示是否拦截,为
    true
    时放行,为
    false
    时拦截。

    public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
    // 测试输出
    System.out.println("LoginInterceptor.preHandle()");
    
    // 拦截规则:
    // 如果未登录,重定向到登录,并拦截
    // 如果已登录,直接放行
    HttpSession session = httpServletRequest.getSession();
    if (session.getAttribute("username") == null) {
    httpServletResponse.sendRedirect("../user/login.do");
    return false;
    }
    return false;
    }
    
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    
    }
    
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    
    }
    }

    step2:在spring的配置文件中配置拦截器

    在spring的配置文件中配置拦截器

    <!-- 拦截器链 -->
    <mvc:interceptors>
    <!-- 第1个拦截器 -->
    <mvc:interceptor>
    <!-- 1. 黑名单 -->
    <mvc:mapping path="/user/*"/>
    <!-- 2. 白名单 -->
    <mvc:exclude-mapping path="/user/reg.do"/>
    <mvc:exclude-mapping path="/user/login.do"/>
    <mvc:exclude-mapping path="/user/handle_reg.do"/>
    <mvc:exclude-mapping path="/user/handle_login.do"/>
    <!-- 3. 拦截器类 -->
    <bean class="cn.tedu.spring.LoginInterceptor" />
    </mvc:interceptor>
    </mvc:interceptors>

    在配置时,可以使用星号

    *
    作为通配符,但是,它只能匹配1级路径,例如:
    /user/*
    可以通配
    /user/reg.do
    /user/login.do
    等,却无法匹配
    /user/a/list.do
    !如果需要表示多级路径中的通配,则需要使用2个星号
    **

    过滤器与拦截器的区别

    使用环境不同:过滤器是Java EE中的组件,任何Java Web项目都可以使用;拦截器是SpringMVC中的组件,仅当项目中使用了SpringMVC框架后才可以使用!

    执行时间节点不同:过滤器是执行在Servlet之前的,拦截器是执行在Controller之前的(暂不考虑拦截器在控制器之后的2次执行)!

    使用复杂程度不同:过滤器只能配置1个路径(

    <url-pattern>
    )表示过滤范围,拦截器可以配置若干个
    <mvc:mapping>
    表示拦截范围,同时还可以使用若干个
    <mvc:exclude-mapping>
    表示例外(白名单),所以配置时更加灵活!

    当然,也有一些相同之处,例如:都在控制器之前执行,都可以起到“拦截效果”,都可以形成“链”。

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: