Filter过滤器

定义

过滤器filter,也可以理解成拦截器,就是在访问web资源之前或之后,对其进行拦截,然后做一些处理后,再传给过滤器链中的下一个过滤器,或进入请求的servlet进行处理。filter可以用于对request过滤,也可以对response过滤。但常见的一般都用于拦截request,相当于在请求资源前先做一个预处理。
在这里插入图片描述
在这里插入图片描述

作用

不用的时候,直接去掉web.xml、@注解中注册的过滤器,不会影响servlet,不需要修改servlet部分代码等,所以易维护。

  • 自动登录 CheckLoginFilter
  • 统一设置编码格式 EncodeFilter
  • 访问权限控制 AuthorityFilter
  • 敏感字符过滤
  • 输入验证
  • 访问量统计
  • 数据压缩
    等等…

一个简单的filter示例

生命周期:init() —> doFilter() —> destroy()

public class MyFilter implements Filter {
	//销毁方法,销毁时调用
    public void destroy() {
    }
    //filter过滤器处理部分
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        chain.doFilter(req, resp);
    }

	//初始化方法,接收FilterConfig类型的参数,参数中包括一些Filter的配置
    public void init(FilterConfig config) throws ServletException {

    }

}
  1. init()阶段:
    public void init(FilterConfig config)
    filter的创建和销毁,都由WEB服务器负责。web 应用程序启动时,web 服务器将创建filter 的实例,并调用init方法进行初始化。
    注意:filter只创建一次,且在启动时创建,init()方法也执行一次

  2. destroy()阶段:
    public void destroy()
    销毁过滤器时,只调用一次

  3. doFilter()阶段:
    public void doFilter(HttpServletRequest request,HttpServletResponse response, FilterChain chain)
    三个参数,其中FilterChain可以理解成一个过滤器链,这个链上有很多filter。

  • FilterChain对象负责调用链中的下一个过滤器或资源。FilterChain接口只有一个方法
    public void doFilter(HttpServletRequest request,HttpServletResponse response),该方法作用就是传递req、resp给下一个过滤器。

配置

web.xml配置

  • filter执行顺序由配置里的<filter-mapping></filter-mapping>的顺序决定,越靠前越先执行
  • 和servlet不同的是filter的url-pattern设置要拦截的资源路径
<!-- 跨域 -->
    <filter>
        <filter-name>crossOriginFilter</filter-name>
        <filter-class>com.bluemsun.filter.CrossOriginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>crossOriginFilter</filter-name>
        <!-- /* 匹配服务器下所有路径资源-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

作用的资源路径

<!--通配符* 所有资源:作用于服务器所有路径下的资源-->
<url-pattern>/*</url-pattern>

<!--后缀名匹配:作用于服务器所有的jsp资源-->
<url-pattern>*.jsp</url-pattern>

<!--目录匹配:xxx路径下的所有资源-->
<url-pattern>/xxx/*</url-pattern>

<!--作用于xxx路径下所有的do资源-->
<url-pattern>/user/*.do</url-pattern>

<!--匹配某一具体资源-->
<url-pattern>/user/login</url-pattern>

跨域Filter

public class CrossOriginFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //强制类型转换成Http
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        //允许跨域的域名。单个域名、*(匹配所有域名)
        //request.getHeader("Origin") 即直接获取请求头的origin的值,即请求方的域名
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));

        //若要使用cookie,需要设置值为true,表示允许发送cookie(可选)
        response.setHeader("Access-Control-Allow-Credentials", "true");

        //服务器支持的所有请求头字段
        response.setHeader("Access-Control-Allow-Headers",
                "Origin," +
                        "Access-Control-Request-Headers," +
                        "Access-Control-Allow-Headers," +
                        "Content-Type," +
                        "Keep-Alive," +
                        "User-Agent," +
                        "Cache-Control," +
                        "Cookie," +

                        "DNT," +
                        "X-Requested-With," +
                        "X-Mx-ReqToken," +
                        "X-Requested-With," +
                        "If-Modified-Since," +
                        "Accept," +
                        "Connection," +
                        "X-XSRF-TOKEN," +
                        "X-CSRF-TOKEN," +
                        "Authorization");

        //(预检请求)的响应结果,规定了服务器允许客户端使用的请求方法, 如:POST, GET 和 OPTIONS
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");

        //设置(预检请求)的返回结果的过期时间,这里设置响应最大有效时间为 86400 秒,即24 小时
        //即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息可以被缓存多久
        response.setHeader("Access-Control-Max-Age", "86400");

        //设置除了简单响应首部以外,需要暴露给外部的其他首部
        response.setHeader("Access-Control-Expose-Headers", "Authorization");

        chain.doFilter(request, response);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

登录验证Filter

public class CheckLoginFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //强制类型转换成Http
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        String uri = request.getRequestURI();
        //静态资源,放行
        if (uri.endsWith(".jsp")) {
            chain.doFilter(request, response);
            return;
        }

        //login请求直接放行,过滤除login以外的请求(这里负责login的url是 /userServlet)
        if(!uri.contains("userServlet")){
            //获取用户登录信息(获取session)
            HttpSession session = request.getSession();
            User currentUser = (User) session.getAttribute("currentUser");

            //如果检查到用户没有登录,可以直接重定向到登录页面
            if (currentUser == null) {
                response.sendRedirect("/login.jsp");
                return;
            }
        }
        
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

filter调用顺序

1. 配置位置不同,执行顺序不同:

3种情况:

  • web.xml配置:filter执行顺序由配置里的<filter-mapping></filter-mapping>的顺序决定,mapping越靠前越先执行
  • 注解配置:filter的执行顺序跟名称的字母顺序有关,例如AFilter会比BFilter先执行
  • 两处都配置:web.xml中的filter优先执行

2. chain.doFilter(request, response)之前OR之后

  • request进行过滤:放在chain.doFilter()之前

  • response进行过滤:放在chain.doFilter()之后

手写一个编码EncodeFilter(展示流程)

参考博客:
Java Web之过滤器(Filter):
https://blog.csdn.net/yuzhiqiang_1993/article/details/81288912?spm=1001.2014.3001.5506

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值