过滤器Filter【详解】

过滤器Filter


1、 现有问题

在以往的Servlet中,有冗余的代码,多个Servlet都有重复的代码

  • 比如编码格式设置

  • 登录信息认证

2、 概念

过滤器(Filter)是处于客户端与服务器目标资源之间的一道过滤技术。

过滤器

image-20230524220124509

image-20231121163149436

3、 过滤器作用

  • 执行顺序在Servlet之前,客户端发送请求时,会先经过Filter,再到达目标Servlet中;响应时,会根据执行流程再次反向执行Filter

  • 可以解决多个Servlet共性代码的冗余问题(例如:乱码处理、登录验证)

扫描二维码关注公众号,回复: 17397079 查看本文章

4、 编写过滤器

Servlet API中提供了一个Filter接口,开发人员编写一个Java类实现了这个接口即可,这个Java类称之为过滤器(Filter)

  • 编写Java类实现Filter接口

  • doFilter方法中编写拦截逻辑

  • 设置拦截路径@WebFilter("path"),path写法

    • /* 拦截所有请求路径

    • /a 拦截指定的/a请求

    • *.do 拦截指定的后缀请求

    • 也可以写对多个 {"/a","/b"}

5、 过滤器链和优先级

5.1 过滤器链

客户端对服务器请求之后,服务器调用Servlet之前会执行一组过滤器(多个过滤器),那么这组过滤器就称为一条过滤器链。

每个过滤器实现某个特定的功能,当第一个Filter的doFilter方法被调用时,Web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则Web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

过滤器链

image-20230524220221983

5.2 过滤器优先级

在一个Web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。 优先级:

  • 如果为注解的话,是按照类全名称的字符串顺序决定作用顺序

6、 过滤器应用1:全局编码

以前: 在每个servlet为了防止乱码,在进行操作之前,都先设置请求和响应的编码格式.

现在: 使用拦截器,对所有请求拦截器,设置编码,然后放行


@WebFilter("/*")
public class EncodingFilter implements Filter {
​
    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }
​
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 设置编码格式
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
​
​
        // 放行
        chain.doFilter(request,response);
    }
​
    @Override
    public void destroy() { }
}

7、 过滤器应用2: 身份认证拦截器

以前: 在web项目中,在每个Servlet中都要对身份进行认证

现在: 使用拦截器,将身份过滤的代码前置到拦截器,对每个请求先身份认证

@WebFilter("/*")
// @WebFilter("/hw/*")
// @WebFilter("*.do")
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }
​
    /**
     * 对请求的身份进行认证
     * 请求中获得session,且session中有登录时存入的数据,说明登录成功,放行
     * 请求中获得session,但是session中没有数据,说明没有登录,重定向到登录页
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
​
        // 获取session
        HttpServletRequest req = (HttpServletRequest) request;
        HttpSession session = req.getSession( );
​
        String requestURI = req.getRequestURI( );
​
        /**
         * 因为是拦截所有 /*
         * 所以要放行 静态资源以及第一次登录的请求
         */
        if(requestURI.contains("login")) {
            // 放行
            chain.doFilter(request, response);
        } else {
            // 从session获得数据
            String username = (String) session.getAttribute("username");
            // 判断
            if (username != null){
                // 放行
                chain.doFilter(request, response);
             } else {
                HttpServletResponse resp = (HttpServletResponse) response;
                resp.sendRedirect("/index.jsp");
            }
        }
​
    }
​
    @Override
    public void destroy() { }
}

猜你喜欢

转载自blog.csdn.net/weixin_61898502/article/details/142712520