首页 > 其他 > 详细

Servlet学习6--过滤器

时间:2020-09-21 23:43:10      阅读:69      评论:0      收藏:0      [点我收藏+]

一.过滤器Filter

  1. Filter介绍

    Servlet有三大组件:Servlet,Filter,Listener.

    Filter中文意思为过滤,在Web中,过滤器可以在请求到达目标资源之前先对请求进行拦截,也就是可以先对请求进行一些处理,之后再放行去访问目标资源;也可以在响应返回到客户端之前对响应进行拦截,也就是可以对响应做一些处理,再返回给客户端。

    技术分享图片

  2. 过滤器作用

    通过Filter,能够对web服务器管理的所有web资源,比如jsp,servlet,静态图片,静态html等文件进行拦截过滤,从而实现一些特殊的功能。比如登录验证,统一编码处理,敏感词汇过滤等。

  3. Filter接口

    在Servlet中,提供了一个接口javax.servlet.Filter,只要实现该接口的类,就可以称为过滤器。

    Filter接口有三个方法需要重写:

    • init():初始化方法,在服务器启动后会创建Filter对象,然后调用init方法,只会执行一次,用于加载资源。
    • doFilter():核心方法,对于请求和响应的过滤,都是在该方法中完成,每一次请求被拦截的资源时会执行。
    • destroy():销毁方法,在服务器关闭后,Filter对象被销毁,会执行该方法,只执行一次,一般用于释放资源。
  4. 创建Filter过滤器

    • 创建一个类实现javax.servlet.Filter接口
    • 重写接口中的方法
    • 配置Filter(web.xml或者注解)
    import javax.servlet.*;
    import java.io.IOException;
    
    public class FilterDemo1 implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("Filter 初始化");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("Filter 调用");
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
            System.out.println("Filter 销毁");
        }
    }
    
    

    注意:在Filter的doFilter方法内部如果没有调用doFilter(request,response)方法,那么服务器中的资源是不会被访问到的。doFilter(request,response)就是一个放行

  5. Filter细节

    1. web.xml配置

      • 注册Filter

        <filter>
            <filter-name>Demo1</filter-name>
            <filter-class>com.zzy.www.filter.FilterDemo1</filter-class>
            <init-param>
            	<param-name>path</param-name>
                <param-value>/WEB_INF/a.txt</param-value>
            </init-param>
        </filter>
        

        <filter-name>:设置过滤器的名字,内容不能为空

        <filter-class>:指定过滤器的完整的类名

        <init-param>:用于为过滤器指定初始化参数,<param-name>指定参数的名称,<param-value>指定参数的值。(在过滤器中可以使用FilterConfig接口对象来访问初始化参数)(多个参数就有多个<init-param>)

      • 映射Filter

        <filter-mapping>
        	<filter-name>Demo1</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        

        <filter-name>:用于设置Filter的注册名称,这个值必须是在注册Filter时<filter>中声明过的过滤器名字。

        <url-pattern>:设置Filter要拦截的请求路径。Filter的全路径匹配只支持/*,不支持/

        <filter-mapping>还有两个标签<servlet-name><dispatcher>

        <servlet-name>:指定过滤器要拦截的Servlet名称

        <dispatcher>:指定过滤器拦截的资源被Servlet调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认是REQUEST。

        • REQUEST:默认值,只要不是由RequestDispatch的forward()或include()方法转发的,都会被该Filter拦截。
        • FORWARD:当前Filter只会拦截由RequestDispatcher的forward()方法所转发的请求,其他的请求不会拦截。
        • INCLUDE:只要是通过<jsp:include page="xxx.jsp"/>嵌入进来的页面,每一个嵌入的页面,都会走一次值为INCLUDE的过滤器。
        • ERROR:当前Filter只会拦截转向错误页面的请求,其他请求不会拦截。
        • ASYNC:会拦截AsyncContext对象发出的请求。

        如果是注解的方式配置,则是设置dispatcherTypes属性

    2. 过滤器执行流程

      • 执行过滤器
      • 执行放行后的资源
      • 返回执行过滤器放行代码下边的代码

      技术分享图片

    3. 过滤器生命周期

      • 当服务器启动时,会创建Filter对象,并调用init()方法,只会调用一次。
      • 当访问资源时,路径与Filter的拦截路径匹配时,会执行Filter中的doFilter()方法,该方法是真正实现拦截操作的方法。
      • 当服务器关闭时,会调用Filter的destroy()方法进行销毁,只会调用一次。
    4. 过滤器链(多个过滤器)

      ? 如果在web中设置了多个过滤器,那么这些过滤器执行过程是以一种链的形式执行的。

      也就是每一个Filter串一起形成一条链,按照链的顺序依次执行,一个Filter执行完filterChain的doFilter()方法后,转而执行另一个Filter,直到最后一个Filter,最后一个Filter的filterChain.doFilter()会自动跳转到最终的请求资源。

      ? 在请求到达Filter之后,Filter可以拦截请求对象,并能对请求进行修改,修改过后再转向下一个Filter或资源。

      ? 当最终的资源执行完毕,形成了响应对象后,会按照Filter链的顺序逆序再次访问Filter,此时的Filter能够拦截到响应对象,并能对响应进行修改,最后客户端接收到的是被FIlter修改过的响应。

      技术分享图片

  6. Filter的特点

    • Filter是单例多线程的
    • FIlter是在web应用被加载时创建并初始化的,这点与Servlet不同(Servlet是在servlet第一次被访问时创建)
    • 客户端每提交一次该Filter可以过滤的请求,服务器就会执行一次doFilter()方法,doFilter()方法是可以被多次执行的
    • 由于Filter是单例多线程的,所以一般为了保证线程安全,是不会在FIlter类定义可以修改的成员变量的,因为会出现线程安全问题。

二.Filter例子

  1. Filter解决乱码问题

    之前编写servlet时候,在处理POST请求乱码时,需要在获取请求参数前设置request的编码request.setCharacterEncoding("utf-8");

    在响应时候,也需要处理乱码问题,之前是使用response.setContentType("text/html;charset=utf-8");

    这种处理方式很繁琐,需要在每一个servlet中都声明这些编码,可以通过使用过滤器,提取这些公有代码到过滤器中。

    @WebServlet("/LoginServlet")
    public class LoginServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String username = request.getParameter("username");
            System.out.println("username: " + username);
    
            response.getWriter().println("用户名为:" + username);
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    }
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录</title>
    </head>
    <body>
    <form action="/BookTest/LoginServlet" method="post">
        <label for="username">姓名:</label><input type="text" id="username" placeholder="请输入姓名" name="username"> <br>
        <input type="submit" value="登录">
    </form>
    </body>
    </html>
    
    @WebFilter(filterName = "FilterTest1", urlPatterns = "/*")
    public class FilterTest1 implements Filter {
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            HttpServletRequest request = (HttpServletRequest)req;
            HttpServletResponse response = (HttpServletResponse)resp;
    
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
    
            chain.doFilter(req, resp);
        }
    
        public void init(FilterConfig config) throws ServletException {
    
        }
    
    }
    
    
  2. 登陆验证

    针对用户访问网站,当用户未登录时只能访问首页,登陆页面,其他页面是没有权限访问的,必须登陆才能访问,此时过滤器可以做一个权限管控,如果用户已登录,就放行;否则则跳转到登录页面。

    比如用户访问news.jsp页面.未登录前先访问news.jsp是会自动跳转到登录页面的,只有登录后访问才能直接访问news.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>news</title>
    </head>
    <body>
        <h1>Welcome!</h1>
    </body>
    </html>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录</title>
    </head>
    <body>
    <form action="/BookTest/LoginServlet" method="post">
        <label for="username">姓名:</label><input type="text" id="username" placeholder="请输入姓名" name="username"> <br>
        <label for="password">密码:</label><input type="password" id="password" placeholder="请输入密码" name="password"><br>
        <input type="submit" value="登录">
    </form>
    </body>
    </html>
    
    @WebServlet("/LoginServlet")
    public class LoginServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String username = request.getParameter("username");
            System.out.println("username: " + username);
    
            if (username != null) {
                HttpSession s = request.getSession();
    
                if (s.getAttribute("username") == null) {
                    s.setAttribute("username", username);
                }
            }
    
            response.sendRedirect("/BookTest/news.jsp");
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    }
    
    @WebFilter(filterName = "FilterTest2",urlPatterns = "/*")
    public class FilterTest2 implements Filter {
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            HttpServletRequest request = (HttpServletRequest)req;
            HttpServletResponse response = (HttpServletResponse)resp;
    
            // 获取访问地址
            String path = request.getServletPath();
            System.out.println(path);
            if (path.startsWith("/news.jsp")) {
                HttpSession s = request.getSession();
                System.out.println(s);
                // 说明还没登录
                if (s == null) {
                    // 跳转到登录界面
                    response.sendRedirect("/BookTest/login.html");
                } else {
                    String name = (String)s.getAttribute("username");
                    System.out.println("name = " + name);
                    if (name == null) {
                        response.sendRedirect("/BookTest/login.html");
                    }
                }
            }
            chain.doFilter(req, resp);
        }
    
        public void init(FilterConfig config) throws ServletException {
    
        }
    
    }
    

Servlet学习6--过滤器

原文:https://www.cnblogs.com/LucasBlog/p/13709249.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!