filter 订阅
Filter 技术是servlet 2.3 新增加的功能。servlet2.3是sun公司于2000年10月发布的,它的开发者包括许多个人和公司团体,充分体现了sun公司所倡导的代码开放性原则。在众多参与者的共同努力下,servlet2.3比以往功能都强大了许多,而且性能也有了大幅提高。 展开全文
Filter 技术是servlet 2.3 新增加的功能。servlet2.3是sun公司于2000年10月发布的,它的开发者包括许多个人和公司团体,充分体现了sun公司所倡导的代码开放性原则。在众多参与者的共同努力下,servlet2.3比以往功能都强大了许多,而且性能也有了大幅提高。
信息
外文名
Filter
发    布
2000年10月
体    现
代码开放性原则
作    用
改变request和修改response
出    自
sun公司
中文名
过滤器
所    属
servlet 2.3
Filter特点功能
它新增加的功能包括:1. 应用程序生命周期事件控制;2. 新的国际化;3. 澄清了类的装载规则;4. 新的错误及安全属性;5. 不赞成使用HttpUtils 类;6. 各种有用的方法;7. 阐明并扩展了几个servlet DTD;8. filter功能.
收起全文
精华内容
参与话题
问答
  • java过滤器Filter

    万次阅读 多人点赞 2019-07-31 19:08:31
    Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码、做一些业务逻辑判断如是否有权限访问页面等。其工作原理是,只要你在web.xml文件配置好要拦截的客户端请求,它...

    一、简介

    Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码、做一些业务逻辑判断如是否有权限访问页面等。其工作原理是,只要你在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就可以对请求或响应 (Request、Response)统一设置编码,简化操作;同时还可进行逻辑判断,如用户是否已经登陆、有没有权限访问该页面等等工作。它是随你的 web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁,以下通过代码示例来了解它 的使用。

    二、实例

    package test.filter; 
    import ...; 
    /**
     * 介绍过滤器的使用,以设置编码为例
     */
    public class MyFilter implements Filter { 
      private FilterConfig config = null; 
      private boolean isFilter = false;
      
      public void destroy() { 
       System.out.println("MyFilter准备销毁..."); 
      } 
      
      public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain) throws IOException, ServletException { 
       // 强制类型转换 
       HttpServletRequest request = (HttpServletRequest)arg0; 
       HttpServletResponse response = (HttpServletResponse)arg1; 
       // 获取web.xm设置的编码集,设置到Request、Response 中   
       request.setCharacterEncoding(config.getInitParameter("charset"));   
       response.setContentType(config.getInitParameter("contentType"));   
       response.setCharacterEncoding(config.getInitParameter("charset"));   
       // 将请求转发到目的地继续执行
       chain.doFilter(request, response);
      } 
      
      public void init(FilterConfig arg0) throws ServletException { 
       this.config = arg0; 
       if(isFilter){
          System.out.println("MyFilter初始化..."); 
       }
      } 
      
      private void setIsFilter(boolean isFilter){
    	this.isFilter = isFilter;
      }
    }

    然后在web. xml中配置该过滤器:

     <filter>
     	<filter-name>MyFilter</filter-name>
     	<filter-class>test.filter.MyFilter</filter-class>
     	<init-param>
     		<param-name>isFilter</param-name>
     		<param-value>true</param-value>
     	</init-param>
     </filter>
     <filter-mapping>
     	<filter-name>MyFilter</filter-name>
     	<url-pattern>/*</url-pattern>
     	<dispatcher>REQUEST</dispatcher> <!-- 没有配置dispatcher就是默认request方式的 -->
     	<dispatcher>FORWARD</dispatcher>
     	<dispatcher>ERROR</dispatcher>
     	<dispatcher>INCLUDE</dispatcher>
     </filt

    三、详细介绍

    在doFilter方法中通常都做些什么呢,下面列举一下:

    1、通过控制对chain.doFilter的方法的调用,来决定是否需要访问目标资源。

    比如,可以在用户权限验证等等。判断用户是否有访问某些资源的权限,有权限放行,没权限不执行chain.doFilter方法。
    2、在调用chain.doFilter方法之前,做些处理来达到某些目的。
    比如,解决中文乱码的问题等等。可以在doFilter方法前,执行设置请求编码与响应的编码。甚至可以对request接口进行封装装饰来处理get请求方式的中文乱码问题(重写相应的request.getParameter方法)。
    3、在调用chain.doFilter方法之后,做些处理来达到某些目的。
    比如对整个web网站进行压缩。在调用chain.doFilter方法之前用类A对response对象进行封装装饰,重写getOutputStream和重写getWriter方法。在类A内部中,将输出内容缓存进ByteArrayOutputStream流中,然后在chain.doFilter方法执行后,获取类A中ByteArrayOutputStream流缓存数据,用GZIPOutputStream流进行压缩下。

    Filter不仅可以通过url-pattern来指定拦截哪些url匹配的资源。而且还可以通过servlet-name来指定拦截哪个指定的servlet(专门为某个servlet服务了,servlet-name对应Servlet的相关配置)。

    filter-mapping标签中dispatcher指定过滤器所拦截的资源被Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher> 子元素用来指定 Filter 对资源的多种调用方式进行拦截。

    REQUEST:

    当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问或ERROR情况时,那么该过滤器就不会被调用。

    INCLUDE:

    如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。

    FORWARD:

    如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。

    ERROR:

    如若在A.jsp页面page指令中指定了error属性=examError.jsp,那么A.jsp中若出现了异常,会跳转到examError.jsp中处理。而在跳转到examError.jsp时,若过滤器配置了ERROR的dispather那么则会拦截,否则不会拦截。

    四、高级配置(允许代理注入spring bean)

    web.xml中配置过滤器DelegatingFilterProxy:

     

    <filter>
        <filter-name>permission</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
     <filter-mapping>
        <filter-name>permission</filter-name>
        <url-pattern>*.htm</url-pattern>
    </filter-mapping>

    在spring bean配置中加入:

    <bean id="permission" class="你的bean"></bean>

    bean的id必须和filter-name一样。如果想不一样,可以这样配置:

    <filter>
        <filter-name>permission</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
         <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>targetBeanName</param-name>
            <param-value>test</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>permission</filter-name>
        <url-pattern>*.htm</url-pattern>
    </filter-mapping>

    在spring bean配置中加入:

    <bean id="test" class="你的bean"></bean>

    以上你的spring bean必须实现Filter接口。

    那这样子做是为了什么呢?

    答:这样做就可以将DelegatingFilterProxy所代理的filter作为spring的bean,受到spring的管理,也就是通过Spring容器来管理filter的生命周期,还有就是如果filter中需要一些Spring容器的实例,可以通过spring直接注入,另外读取一些配置文件这些便利的操作都可以通过Spring来配置实现。

    其中如果设置"targetFilterLifecycle"为True,则Filter.init()和Filter.destroy()有效;若为false,则这两个方法失效。

    如果大家有用到shiro(一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理等)的话,通常就会用到这个DelegatingFilterProxy了!

     

    展开全文
  • Java集合Stream类filter的使用

    万次阅读 多人点赞 2018-05-11 11:49:42
    之前的Java集合中removeIf的使用一文写了使用removeIf来实现按条件对集合进行过滤。这篇文章使用同样是JDK1.8新加入的Stream中filter方法来实现同样的效果。

    之前的Java集合中removeIf的使用一文写了使用removeIf来实现按条件对集合进行过滤。这篇文章使用同样是JDK1.8新加入的Streamfilter方法来实现同样的效果。并且在实际项目中通常使用filter更多。关于Stream的详细介绍参见Java 8系列之Stream的基本语法详解
    同样的场景:你是公司某个岗位的HR,收到了大量的简历,为了节约时间,现需按照一点规则过滤一下这些简历。比如要经常熬夜加班,所以只招收男性

    //求职者的实体类
    public class Person {
        private String name;//姓名
        private Integer age;//年龄
        private String gender;//性别
    
        ...
        //省略构造方法和getter、setter方法
        ...
    
        //重写toString,方便观看结果
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", gender='" + gender + '\'' +
                    '}';
        }
    }
    

    这里就不展示使用传统Iterator来进行过滤了,有需要做对比的可以参见之前的Java集合中removeIf的使用
    使用Streamfilter进行过滤,只保留男性的操作:

    Collection<Person> collection = new ArrayList();
    collection.add(new Person("张三", 22, "男"));
    collection.add(new Person("李四", 19, "女"));
    collection.add(new Person("王五", 34, "男"));
    collection.add(new Person("赵六", 30, "男"));
    collection.add(new Person("田七", 25, "女"));
    
    Stream<Person> personStream = collection.stream().filter(new Predicate<Person>() {
        @Override
        public boolean test(Person person) {
             return "男".equals(person.getGender());//只保留男性
        }
    });
    
    collection = personStream.collect(Collectors.toList());//将Stream转化为List
    System.out.println(collection.toString());//查看结果
    

    运行结果如下:

    [Person{name=‘张三’, age=22, gender=‘男’}, Person{name=‘王五’, age=34, gender=‘男’}, Person{name=‘赵六’, age=30, gender=‘男’}]
    Process finished with exit code 0

    上面的demo没有使用lambda表达式,下面的demo使用lambda来进一步精简代码:

    Collection<Person> collection = new ArrayList();
    collection.add(new Person("张三", 22, "男"));
    collection.add(new Person("李四", 19, "女"));
    collection.add(new Person("王五", 34, "男"));
    collection.add(new Person("赵六", 30, "男"));
    collection.add(new Person("田七", 25, "女"));
    
    Stream<Person> personStream = collection.stream().filter(
            person -> "男".equals(person.getGender())//只保留男性
    );
    
    collection = personStream.collect(Collectors.toList());//将Stream转化为List
    System.out.println(collection.toString());//查看结果
    

    效果和不用lambda是一样的。

    不过读者在使用filter时不要和removeIf弄混淆了:

    • removeIf中的test方法返回true代表当前元素会被过滤掉
    • filter中的test方法返回true代表当前元素会保留下来
    展开全文
  • Java Web之过滤器(Filter

    万次阅读 多人点赞 2018-07-31 16:58:40
    过滤器(Filter) 过滤器实际上就是对web资源进行拦截,做一些处理后再交给servlet。 通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理 大概流程图如下 应用场景 自动登录 统一设置...

    过滤器(Filter)


    过滤器实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理
    通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理

    大概流程图如下

    这里写图片描述

    应用场景
    自动登录
    统一设置编码格式
    访问权限控制
    敏感字符过滤等


    创建Filter

    在Servlet中我们一般都会对request和response中的字符集编码进行配置,如果Servlet过多字符集编码发生变化时修改起码会很麻烦,这些通用的字符集编码配置等工作我们可以放到Filter中来实现。
    下面我们来创建一个处理字符集编码的Filter。

    右键包名—>new ---->Filter

    这里写图片描述

    输入过滤器名称,跟创建Servlet一样,这里我们直接使用 @WebFilter 注解,不再去web,xml中进行配置了。

    这里写图片描述

    创建完成后默认代码,可以看到,CharsetFilter实现了Filter接口,实现了3个方法。3个方法的作用已经在注释中写清楚了。

    package filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    
    @WebFilter(filterName = "CharsetFilter")
    public class CharsetFilter implements Filter {
        public void destroy() {
            /*销毁时调用*/
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            /*过滤方法 主要是对request和response进行一些处理,然后交给下一个过滤器或Servlet处理*/
           
            chain.doFilter(req, resp);//交给下一个过滤器或servlet处理
        }
    
        public void init(FilterConfig config) throws ServletException {
    
            /*初始化方法  接收一个FilterConfig类型的参数 该参数是对Filter的一些配置*/
    
        }
    
    }
    
    

    配置Filter

    可配置的属性有这些

    这里写图片描述

    常用配置项
    urlPatterns
    配置要拦截的资源

    1. 以指定资源匹配。例如"/index.jsp"
    2. 以目录匹配。例如"/servlet/*"
    3. 以后缀名匹配,例如"*.jsp"
    4. 通配符,拦截所有web资源。"/*"

    **initParams **
    配置初始化参数,跟Servlet配置一样

    例如

    initParams = {
            @WebInitParam(name = "key",value = "value")
    }
    

    dispatcherTypes **
    配置拦截的类型,可配置多个。默认为
    DispatcherType.REQUEST**
    例如

    dispatcherTypes = {DispatcherType.ASYNC,DispatcherType.ERROR}
    

    其中DispatcherType是个枚举类型,有下面几个值

    	FORWARD,//转发的
        INCLUDE,//包含在页面的
        REQUEST,//请求的
        ASYNC,//异步的
        ERROR;//出错的
    

    下面我们来对CharsetFilter 代码进行一下修改

    package filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.annotation.WebInitParam;
    import java.io.IOException;
    
    @WebFilter(filterName = "CharsetFilter",
            urlPatterns = "/*",/*通配符(*)表示对所有的web资源进行拦截*/
            initParams = {
                    @WebInitParam(name = "charset", value = "utf-8")/*这里可以放一些初始化的参数*/
            })
    public class CharsetFilter implements Filter {
        private String filterName;
        private String charset;
    
        public void destroy() {
            /*销毁时调用*/
    
            System.out.println(filterName + "销毁");
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            /*过滤方法 主要是对request和response进行一些处理,然后交给下一个过滤器或Servlet处理*/
    		System.out.println(filterName + "doFilter()");
            req.setCharacterEncoding(charset);
            resp.setCharacterEncoding(charset);
            chain.doFilter(req, resp);
        }
    
        public void init(FilterConfig config) throws ServletException {
    
            /*初始化方法  接收一个FilterConfig类型的参数 该参数是对Filter的一些配置*/
    
            filterName = config.getFilterName();
            charset = config.getInitParameter("charset");
    
            System.out.println("过滤器名称:" + filterName);
            System.out.println("字符集编码:" + charset);
    
        }
    
    }
    
    

    这样一个简单的字符集编码处理的过滤器就完成了
    我们看看执行打印的结果
    这里写图片描述

    需要注意的是
    过滤器是在服务器启动时就会创建的,只会创建一个实例,常驻内存,也就是说服务器一启动就会执行Filter的init(FilterConfig config)方法.
    当Filter被移除或服务器正常关闭时,会执行destroy方法


    多个Filter的执行顺序

    在我们的请求到达Servle之间是可以经过多个Filter的,一般来说,建议Filter之间不要有关联,各自处理各自的逻辑即可。这样,我们也无需关心执行顺序问题。
    如果一定要确保执行顺序,就要对配置进行修改了,执行顺序如下

    1. 在web.xml中,filter执行顺序跟<filter-mapping>的顺序有关,先声明的先执行
    2. 使用注解配置的话,filter的执行顺序跟名称的字母顺序有关,例如AFilter会比BFilter先执行
    3. 如果既有在web.xml中声明的Filter,也有通过注解配置的Filter,那么会优先执行web.xml中配置的Filter

    我们写个小例子看一下

    新建3个Filter,加上之前的CharsetFilter一共四个

    这里写图片描述

    其中CharsetFilterABFilter是通过注解声明的

    CharsetFilter注解配置

    
    @WebFilter(filterName = "CharsetFilter",
            urlPatterns = "/*",/*通配符(*)表示对所有的web资源进行拦截*/
            initParams = {
                    @WebInitParam(name = "charset", value = "utf-8")/*这里可以放一些初始化的参数*/
            })
    

    ABFilter

    @WebFilter(filterName = "ABFilter",urlPatterns = "/*")
    

    AFilterBFilter是在web.xml配置的。
    执行顺序跟<filter>的顺序无关
    <filter-mapping>的顺序才决定执行顺序

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <filter>
            <filter-name>AFilter</filter-name>
            <filter-class>filter.AFilter</filter-class>
        </filter>
        <filter>
            <filter-name>BFilter</filter-name>
            <filter-class>filter.BFilter</filter-class>
        </filter>
    
        <!--这里BFilter在AFilter之前-->
        <filter-mapping>
            <filter-name>BFilter</filter-name>
            <url-pattern>/filter.jsp</url-pattern>
        </filter-mapping>
    
        <filter-mapping>
            <filter-name>AFilter</filter-name>
            <url-pattern>/filter.jsp</url-pattern>
        </filter-mapping>
    
       
    </web-app>
    

    每个Filter添加了打印语句,如下
    以ABFilter为例

    package filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    
    @WebFilter(filterName = "ABFilter",urlPatterns = "/*")
    public class ABFilter implements Filter {
        private String filterName;
    
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            System.out.println(filterName + "  doFilter()");
            chain.doFilter(req, resp);
        }
    
        public void init(FilterConfig config) throws ServletException {
            filterName= config.getFilterName();
            System.out.println("过滤器名称:" + filterName +" init");
        }
    
    }
    
    

    下面我们来访问filter.jsp看看打印结果

    这里写图片描述

    可以看到,执行结果符合预期。
    BFilter和AFilter是在web.xml中声明的,且BFilter的<filter-mapping>在前,故BFilter在AFilter之前执行。
    ABFilter和CharsetFilter是通过注解声明的,故他俩在BFilter和AFilter之后执行,但是ABFilter的名称以A开头,故在CharsetFilter之前执行

    这里写图片描述


    访问权限控制小例子##

    下面我们写一个访问控制权限控制的小例子。
    我们在浏览一些网站经常有这个情况,没有登录时是不允许我们访其主页的,只有登录过后才能访问。
    下面我们就用Filter简单实现一下。

    需求分析

    1. 登录时将登录的账号密码保存到cookie中,下次访问时携带账号和密码,过滤器中进行校验
    2. 用户没有登录直接访问主页时,要跳转到登录页面
    3. 登录过滤器不对登录页面进行过滤

    我们先来看一下项目结构

    这里写图片描述

    这里主要看一下LoginFilter的代码

    我们在LoginFilter中对非登录页面的其他jsp都会进行过滤,判断cookie中是否携带了account和pwd。
    如果有这两个数据表示之前登录过,那么对数据进行校验,正确的话就进行下一个操作。
    否则的话,跳转到登录界面

    package filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebFilter(filterName = "LoginFilter", urlPatterns = "*.jsp", dispatcherTypes = {})
    public class LoginFilter implements Filter {
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    
    
            System.out.println("LoginFilter doFilter");
    
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
    
            String url = request.getRequestURI();
    
            System.out.println("请求的url:" + url);
            /*登录页面不需要过滤*/
    
            int idx = url.lastIndexOf("/");
            String endWith = url.substring(idx + 1);
    
    
            if (!endWith.equals("login.jsp")) {
                /*不是登录页面  进行拦截处理*/
    
                System.out.println("不是登录页面,进行拦截处理");
    
                if (!isLogin(request)) {
                    System.out.println("没有登录过或者账号密码错误,跳转到登录界面");
                    response.sendRedirect("login.jsp");
                } else {
                    System.out.println("已经登录,进行下一步");
                    chain.doFilter(req, resp);
                }
    
            } else {
    
                System.out.println("是登录页面,不进行拦截处理");
                chain.doFilter(req, resp);
            }
    
    
        }
    
    
        private boolean isLogin(HttpServletRequest request) {
    
            Cookie[] cookies = request.getCookies();
    
            String account = "";
            String pwd = "";
    
            if (cookies != null && cookies.length > 0) {
                for (Cookie cookie : cookies) {
                    if (cookie.getName().equals("account")) {
                        account = cookie.getValue();
                    } else if (cookie.getName().equals("pwd")) {
                        pwd = cookie.getValue();
                    }
                }
            }
    
            if (account.equals("") || pwd.equals("")) {
                return false;
    
            } else if (account.equals("yzq") && pwd.equals("123")) {
                return true;
            }
    
    
            return false;
        }
    
        public void init(FilterConfig config) throws ServletException {
            System.out.println("LoginFilter  init");
        }
    
    }
    
    

    执行效果

    这里写图片描述

    可以看到,我们在没有登录的情况下直接去访问index.jsp页面时会自动跳转到登录页面,在登录成功后,再次直接访问index页面则可以访问。

    下面是demo

    访问控制demo


    如果你觉得本文对你有帮助,麻烦动动手指顶一下,可以帮助到更多的开发者,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

    展开全文
  • 一、引言 本来想记录一下关于用户登陆和登陆之后的权限管理、菜单管理的问题,想到解决这个问题用到Interceptor,但想到了Interceptor,就想到了Filter,于是...首先说一下Filter的使用地方,我们在配置web.x...

    一、引言

    本来想记录一下关于用户登陆和登陆之后的权限管理、菜单管理的问题,想到解决这个问题用到Interceptor,但想到了Interceptor,就想到了Filter,于是就想说一下它们的执行顺序和区别。关于Interceptor解决权限和菜单管理的问题,在放在下一篇写吧,就酱紫。

    二、区别

    1、过滤器(Filter)

    首先说一下Filter的使用地方,我们在配置web.xml时,总会配置下面一段设置字符编码,不然会导致乱码问题:

    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <servlet-name>/*</servlet-name>
    </filter-mapping>
    

    配置这个地方的目的,是让所有的请求都需要进行字符编码的设置,下面来介绍一下Filter。

    (1)过滤器(Filter):它依赖于servlet容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的,是用来做一些过滤操作,获取我们想要获取的数据,比如:在Javaweb中,对传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者Controller进行业务逻辑操作。通常用的场景是:在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符等。

    2、拦截器(Interceptor)

    拦截器的配置一般在SpringMVC的配置文件中,使用Interceptors标签,具体配置如下:

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean class="com.scorpios.atcrowdfunding.web.LoginInterceptor"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean class="com.scorpios.atcrowdfunding.web.AuthInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
    

    (2)拦截器(Interceptor):它依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在service或者一个方法前,调用一个方法,或者在方法后,调用一个方法,比如动态代理就是拦截器的简单实现,在调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在调用方法后打印出字符串,甚至在抛出异常的时候做业务逻辑的操作。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。

    三、代码


    下面在一个项目中我们使用既有多个过滤器,又有多个拦截器,并观察它们的执行顺序:
    (1)第一个过滤器:

    public class TestFilter1 implements Filter {  
      
    		@Override
      	    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {  
            //在DispatcherServlet之前执行  
    		System.out.println("############TestFilter1 doFilterInternal executed############");  
            filterChain.doFilter(request, response);  
            //在视图页面返回给客户端之前执行,但是执行顺序在Interceptor之后  
            System.out.println("############TestFilter1 doFilter after############");  
        }  
    }  
    

    (2)第二个过滤器:

    public class TestFilter2 implements Filter {  
     
    	@Override
        protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {  
    	    //在DispatcherServlet之前执行  
            System.out.println("############TestFilter2 doFilterInternal executed############");  
            filterChain.doFilter(request, response);  
            //在视图页面返回给客户端之前执行,但是执行顺序在Interceptor之后 
            System.out.println("############TestFilter2 doFilter after############");  
        }  
    }  
    

    (3)在web.xml中注册这两个过滤器:

    	<!-- 自定义过滤器:testFilter1 -->   
    	   <filter>  
    	        <filter-name>testFilter1</filter-name>  
    	        <filter-class>com.scorpios.filter.TestFilter1</filter-class>  
    	    </filter>  
    	    <filter-mapping>  
    	        <filter-name>testFilter1</filter-name>  
    	        <url-pattern>/*</url-pattern>  
    	    </filter-mapping>  
    	    <!-- 自定义过滤器:testFilter2 -->   
    	   <filter>  
    	        <filter-name>testFilter2</filter-name>  
    	        <filter-class>com.scorpios.filter.TestFilter2</filter-class>  
    	    </filter>  
    	    <filter-mapping>  
    	        <filter-name>testFilter2</filter-name>  
    	        <url-pattern>/*</url-pattern>  
    	    </filter-mapping>  
    

    再定义两个拦截器:
    (4)第一个拦截器:

    public class BaseInterceptor implements HandlerInterceptor{  
         
        /** 
         * 在DispatcherServlet之前执行 
         * */  
        public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {  
            System.out.println("************BaseInterceptor preHandle executed**********");  
            return true;  
        }  
     
        /** 
         * 在controller执行之后的DispatcherServlet之后执行 
         * */  
        public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {  
            System.out.println("************BaseInterceptor postHandle executed**********");  
        }  
         
        /** 
         * 在页面渲染完成返回给客户端之前执行 
         * */  
        public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)  
                throws Exception {  
            System.out.println("************BaseInterceptor afterCompletion executed**********");  
        }  
    }  
    

    (5)第二个拦截器:

    public class TestInterceptor implements HandlerInterceptor {  
     
        public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {  
            System.out.println("************TestInterceptor preHandle executed**********");  
            return true;  
        }  
     
        public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {  
            System.out.println("************TestInterceptor postHandle executed**********");  
        }  
     
        public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {  
            System.out.println("************TestInterceptor afterCompletion executed**********");  
        }  
    }  
    

    (6)、在SpringMVC的配置文件中,加上拦截器的配置:

    	<!-- 拦截器 -->  
    	<mvc:interceptors>  
    	    <!-- 对所有请求都拦截,公共拦截器可以有多个 -->  
    	    <bean name="baseInterceptor" class="com.scorpios.interceptor.BaseInterceptor" />  
    		
    		<mvc:interceptor> 
    		    <!-- 对/test.html进行拦截 -->       
    	        <mvc:mapping path="/test.html"/>  
    	        <!-- 特定请求的拦截器只能有一个 -->  
    	        <bean class="com.scorpios.interceptor.TestInterceptor" />  
    	    </mvc:interceptor>  
    	</mvc:interceptors>  
    

    (7)、定义一个Controller控制器:

    package com.scorpios.controller;  
    import org.springframework.stereotype.Controller;  
    import org.springframework.web.bind.annotation.RequestMapping;  
    import org.springframework.web.servlet.ModelAndView;  
      
    @Controller  
    public class TestController {  
        @RequestMapping("/test")  
        public ModelAndView handleRequest(){  
            System.out.println("---------TestController executed--------");  
            return new ModelAndView("test");  
        }  
    }  
    

    (8)、测试结果:
    启动测试项目,地址如下:http://www.localhost:8080/demo,可以看到控制台中输出如下:
    这里写图片描述
    这就说明了过滤器的运行是依赖于servlet容器,跟springmvc等框架并没有关系。并且,多个过滤器的执行顺序跟xml文件中定义的先后关系有关。

    接着清空控制台,并访问:http://www.localhost:8080/demo/test,再次看控制台的输出:
    这里写图片描述
    从这个控制台打印输出,就可以很清晰地看到有多个拦截器和过滤器存在时的整个执行顺序了。当然,对于多个拦截器它们之间的执行顺序跟在SpringMVC的配置文件中定义的先后顺序有关。

    四、总结


    对于上述过滤器和拦截器的测试,可以得到如下结论:
    (1)、Filter需要在web.xml中配置,依赖于Servlet;
    (2)、Interceptor需要在SpringMVC中配置,依赖于框架;
    (3)、Filter的执行顺序在Interceptor之前,具体的流程见下图;
    这里写图片描述
    (4)、两者的本质区别:拦截器(Interceptor)是基于Java的反射机制,而过滤器(Filter)是基于函数回调。从灵活性上说拦截器功能更强大些,Filter能做的事情,都能做,而且可以在请求前,请求后执行,比较灵活。Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录不登录之类),太细的话,还是建议用interceptor。不过还是根据不同情况选择合适的。

    展开全文
  • spring cloud gateway之filter

    万次阅读 多人点赞 2018-12-17 21:45:21
    转载请标明出处: ...本文出自方志朋的博客 在上一篇文章详细的介绍了Gateway的Predict,Predict决定了请求由哪一个路由处理,在路由处理之前,需要经过“pre...由filter工作流程点,可以知道filter有着非常重要的作用...
  • list去重,根据对象某个属性、某几个属性去重 去除List中重复的String List unique = list.stream().distinct().collect(Collectors.toList()); 去除List中重复的对象 // Person 对象 ... ...
  • Gateway网关---Filter过滤器

    万次阅读 2020-07-01 13:08:49
    官网关于过滤器的文档地址https://cloud.spring.io/spring-cloud-gateway/2.2.x/reference/html/#gatewayfilter-factories 过滤请求头包含参数 X-Request-red 并且值是blue的 spring: cloud: gateway: ...
  • ElasticSearch filter查询

    万次阅读 2020-03-21 18:51:21
    #filter是不计算相关性的,同时可以cache.因此,filter速度要快于query. POST /lib5/items/_bulk {"index":{"_id": 1}} {"price": 40,"itemID": "ID100123"} {"index":{"_id": 2}} {"price": 50,"itemID"...
  • bilateral filter双边滤波器的通俗理解

    万次阅读 多人点赞 2018-09-23 17:50:35
    bilateral filter双边滤波器的通俗理解 图像去噪的方法很多,如中值滤波,高斯滤波,维纳滤波等等。但这些降噪方法容易模糊图片的边缘细节,对于高频细节的保护效果并不明显。相比较而言,bilateral filter双边...
  • MATLAB 中 filter 函数的使

    万次阅读 2014-08-20 20:47:42
    一维数字滤波滤波器filter 使用 filter 1-D digital filter expand all in page Syntax y = filter(b,a,X) [y,zf] = filter(b,a,X) [y,zf] = filter(b,a,X,zi) y = filter(b,a...
  • FFmpeg filter

    千次阅读 2018-06-10 17:08:44
    一、FFmpeg filter简介FFmpeg中的libavfilter提供了一整套的基于filter的机制。filter本身是一个插件的形式,可以快速的组装需要的效果。比如下面的filter,可以实现视频的水平镜像效果。ffplay.exe sample.rmvb -vf...
  • 导向滤波(Guided Filter)的解析与实现

    万次阅读 多人点赞 2017-07-10 17:54:31
    导引滤波(Guided Filter)是由Dr. Kaiming He等人提出的一种滤波算法(现在MATLAB的图像处理工具箱中已经内置了实现该算法的函数)。导引滤波不仅可以实现edge-preserving的图像平滑效果,亦可广泛应用于图像去雾、...
  • <filter-name>LoginFilter</filter-name> <filter-class>com.gpeight.hotel.filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>...
  • <filter-name>loginFilter</filter-name> <filter-class>com.lero.filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>/* </...
  • 一个虚拟摄像头Filter(Virtual Cam Capture Filter

    万次阅读 热门讨论 2018-02-25 14:54:31
    当我们运行一些多媒体程序或者OpenCV的例子的时候,经常要用摄像头作为输入源,但是并不是每个用户电脑上都装了USB摄像头,那怎么办呢?可以在你系统上安装一个虚拟摄像头的Directshow插件,那么你系统上就多了一个...
  • Kalman Filter 通俗讲解

    万次阅读 多人点赞 2018-06-03 16:44:05
    Kalman Filter,很多人刚听到这个名词时,总是会下意识认为这就是个滤波器。我这里想要重点声明的是,Kalman Filter不是滤波,它是一种信息融合的过程。 那么Kalman Filter到底是什么?它在那些方面有着应用,它的...
  • 要把shiro整合进入spring,出现了这个错误,'shiroFilter' 这个bean已经定义过了的,着急在线等。。 严重: Exception starting filter shiroFilter org.springframework.beans.factory.NoSuchBeanDefinitionException...
  • adapter.getFilter().filter(s.toString()); } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void afterTextChanged(Editable s) { } }); }...

空空如也

1 2 3 4 5 ... 20
收藏数 165,359
精华内容 66,143
关键字:

filter