zoukankan      html  css  js  c++  java
  • Filter

    本节内容:

    • filter的简介
    • 快速入门
    • filter的API详解
    • filter的配置
    • 案例一:自动登录
    • 案例二:解决全局代码

    一、filter的简介

    filter是对客户端访问资源的过滤,符合条件放行,不符合条件不放行,并且可以对目标资源访问前后进行逻辑处理。

    二、快速入门

    【步骤】:

    1. 编写一个过滤器的类实现Filter接口
    2. 实现接口中尚未实现的方法(着重实现doFilter方法)
    3. 在web.xml中进行配置(主要是配置要对哪些资源进行过滤)
    public class QuickFilter1 implements Filter{
        
        @Override
        //Filter创建的时候执行init方法
        public void init(FilterConfig filterConfig) throws ServletException {
            
        }
    
        @Override
        //doFilter是Filter的核心过滤的方法
        /*
         * request: 内部封装是客户端http请求的内容
         * response: 代表是响应
         * FilterChain: 过滤器链对象
         */
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            
            System.out.println("quick1 running....");
            //放行请求。如果不放行,请求将不会到达你想访问的资源
            chain.doFilter(request, response); 
        }
    
        @Override
        //Filter对象销毁的时候执行destory方法
        public void destroy() {
            System.out.println("destroy...");
        }
    
    }
    QuickFilter1.java --过滤器
    public class Servlet1 extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            
            System.out.println("Servlet1 running....");
            response.getWriter().write("Servlet1 running....");
            
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    }
    Servlet1.java --作为被拦截的资源
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
      <display-name>WEB24</display-name>
      
      <filter>
          <filter-name>QuickFilter1</filter-name>
          <filter-class>com.ithiema.web.filter.QuickFilter1</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>QuickFilter1</filter-name>
          <url-pattern>/*</url-pattern> <!-- 配置对哪些资源拦截 -->
      </filter-mapping> 
    
      <servlet>
        <description></description>
        <display-name>Servlet1</display-name>
        <servlet-name>Servlet1</servlet-name>
        <servlet-class>com.ithiema.web.servlet.Servlet1</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>Servlet1</servlet-name>
        <url-pattern>/servlet1</url-pattern>
      </servlet-mapping>
     </web-app>
    web.xml

    浏览器访问servlet1资源,在控制台可以看出先走的QuickFilter1,然后在到Servlet1资源。

    filter的访问流程:

     

    至于图中的哪个filter在前面,根据各个filter在web.xml文件中的位置,注意是看<filter-mapping>的位置,不是看<filter>的位置。

    三、filter的API详解

    (1)filter生命周期及其与生命周期相关的方法

    Filter接口有三个方法,并且这个三个都是与Filter的生命相关的方法

    • init(Filterconfig):代表filter对象初始化方法。即filter对象创建时执行。
    • doFilter(ServletRequest,ServletResponse,FilterCha):代表filter执行过滤的核心方法,如果某资源在已经被配置到这个filter进行过滤的话,那么每次访问这个资源都会执行doFilter方法。
    • destory():代表是filter销毁方法,当filter对象销毁时执行该方法。

    Filter对象的生命周期:

    • Filter何时创建:服务器启动时就创建该filter对象。
    • Filter何时销毁:服务器关闭时filter销毁。

    (2)Filter的AP详解

    1)init(FilterConfig)
    其中参数config代表 该Filter对象的配置信息的对象,内部封装是该filter的配置信息。

    2)destory()方法
    filter对象销毁时执行

    3)doFilter方法
    doFilter(ServletRequest,ServletResponse,FilterChain)
    其中的参数:

    ServletRequest/ServletResponse:每次在执行doFilter方法时 web容器负责创建一个request和一个response对象作为doFilter的参数传递进来。该request个该response就是在访问目标资源的service方法时的request和response。
    FilterChain:过滤器链对象,通过该对象的doFilter方法可以放行该请求。

    四、filter的配置

    配置示例:

      <filter>
          <filter-name>QuickFilter2</filter-name>
          <filter-class>com.ithiema.web.filter.QuickFilter2</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>QuickFilter2</filter-name>
          <url-pattern>/*</url-pattern> 
      </filter-mapping> 

    url-pattern配置:

    • 完全匹配 /sertvle1
    • 目录匹配 /aaa/bbb/*  --最多的
      • /user/*:访问前台的资源进入此过滤器
      • /admin/*:访问后台的资源时执行此过滤器
    • 扩展名匹配 *.abc  *.jsp

    【注意】:url-pattern可以使用servlet-name替代,也可以混用。比如:

      <filter-mapping>
          <filter-name>QuickFilter2</filter-name>
          <!--<url-pattern>/Servlet1</url-pattern>-->
          <servlet-name>Servlet1</servlet-name> <!-- 和上面那行配置是等效的 -->
      </filter-mapping> 

    dispatcher:访问的方式(了解)。dispatcher是可以配置在<filter-mapping>中的属性,没配置的话,它有个默认值。

    • REQUEST:默认值,代表直接访问某个资源时执行filter。重定向也叫直接访问,只不过是客户端自动去访问的,不是你在浏览器自己输入去访问的。
    • FORWARD:转发时才执行filter
    • INCLUDE: 包含资源时执行filter
    • ERROR:发生错误时、进行跳转时执行filter
      <filter>
          <filter-name>QuickFilter2</filter-name>
          <filter-class>com.ithiema.web.filter.QuickFilter2</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>QuickFilter2</filter-name>
          <url-pattern>/*</url-pattern> 
          <dispatcher>FORWARD</dispatcher>
      </filter-mapping> 

    总结Filter的作用:

    • 公共代码的提取
    • 可以对request和response中的方法进行增强(装饰者模式或动态代理)
    • 进行权限控制

    五、案例一:自动登录

    自动登录的filter是功能增强的,并不是进行拦截的。带着用户名和密码的cookie,就帮忙自动登上去,没带也放行,该访问谁访问谁。

    public class LoginServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            
            request.setCharacterEncoding("UTF-8"); //POST提交要写这个,可以在filter里写上这句话,这样每个接收数据的Servlet中就不用写这句话了
                                                 //但是这种方式对GET不生效
            
            HttpSession session = request.getSession();
            
            //获取数据
            String username = request.getParameter("username");//中文 张三
            String password = request.getParameter("password");
            
            UserService service = new UserService();
            User user = null;
            try {
                user = service.login(username,password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            
            
            if(user!=null){
                //登录成功
                //判断用户是否勾选自动登录,如果登录,将用户名和密码设置进cookie
                String autoLogin = request.getParameter("autoLogin");
                if(autoLogin!=null){
                    //对中文张三进行编码,要存入cookie中
                    String username_code = URLEncoder.encode(username, "UTF-8");
                    
                    Cookie cookie_username = new Cookie("cookie_username",username_code);
                    Cookie cookie_password = new Cookie("cookie_password",password);
                    //设置cookie的持久化时间
                    cookie_username.setMaxAge(60*60);
                    cookie_password.setMaxAge(60*60);
                    //设置cookie的携带路径
                    cookie_username.setPath(request.getContextPath());
                    cookie_password.setPath(request.getContextPath());
                    //发送cookie
                    response.addCookie(cookie_username);
                    response.addCookie(cookie_password);
                }
                
                //将登录的用户的user对象存到session中
                session.setAttribute("user", user);
                //重定向到首页
                response.sendRedirect(request.getContextPath());
                
            }else{
                //失败 转发到登录页面 提出提示信息
                request.setAttribute("loginInfo", "用户名或密码错误");
                request.getRequestDispatcher("/login.jsp").forward(request, response);
            }
            
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    }
    LoginServlet.java
    public class AutoLoginFilter implements Filter{
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse resp = (HttpServletResponse) response;
            HttpSession session = req.getSession();
            
            //获得cookie中用户名和密码 进行登录的操作
            //定义cookie_username
            String cookie_username = null;
            //定义cookie_password
            String cookie_password = null;
            //获得cookie
            Cookie[] cookies = req.getCookies();
            if(cookies!=null){
                for(Cookie cookie : cookies){
                    //获得名字是cookie_username和cookie_password
                    if("cookie_username".equals(cookie.getName())){
                        cookie_username = cookie.getValue();
                        //解码,恢复中文用户名
                        cookie_username = URLDecoder.decode(cookie_username, "UTF-8");
                    }
                    if("cookie_password".equals(cookie.getName())){
                        cookie_password = cookie.getValue();
                    }
                }
            }
            
            //判断username和password是否是null
            if(cookie_username!=null&&cookie_password!=null){
                //登录的代码
                UserService service = new UserService();
                User user = null;
                try {
                    user = service.login(cookie_username,cookie_password);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                //将登录的用户的user对象存到session中
                session.setAttribute("user", user);
            }
            
            //放行
            chain.doFilter(req, resp);
            
        }
        
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            
        }
    
        @Override
        public void destroy() {
            
        }
    }
    AutoLoginFilter.java
    public class User {
    
        private int id;
        private String username;
        private String password;
        private String email;
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        public String getEmail() {
            return email;
        }
        public void setEmail(String email) {
            this.email = email;
        }
            
        
    }
    User.java
    <!-- 自动登录的filter -->
     <filter>
          <filter-name>AutoLoginFilter</filter-name>
          <filter-class>com.ithiema.web.filter.AutoLoginFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>AutoLoginFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
    web.xml
    <!-- 登录 注册 购物车... -->
    <div class="container-fluid">
        <div class="col-md-4">
            <img src="img/logo2.png" />
        </div>
        <div class="col-md-5">
            <img src="img/header.png" />
        </div>
        <div class="col-md-3" style="padding-top:20px">
            <ol class="list-inline">
                
                <c:if test="${empty user }">
                    <li><a href="login.jsp">登录</a></li>
                    <li><a href="register.jsp">注册</a></li>
                </c:if>
                <c:if test="${!empty user }">
                    <li>欢迎您,${user.username }</li>
                    <li><a href="#">退出</a></li>
                </c:if>
                
                <li><a href="cart.jsp">购物车</a></li>
                <li><a href="order_list.jsp">我的订单</a></li>
            </ol>
        </div>
    </div>
    header.jsp

    六、案例二:解决全局的编码

    当用户输入中文提交时,无论是POST方式还是GET方式提交,在获取用户提交的数据时都会遇到编码问题。在前面的文章中,对编码的处理都是放在Servlet中,这样凡是Servlet中需要获取用户提交数据的,如果存在中文,都需要处理乱码。

    我们可以将编码处理挪到filter中,这样后面的Servlet就不需要单独处理了。

    public class EncodingFilter implements Filter{
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            
            //request.setCharacterEncoding("UTF-8");
            
            //在传递request之前对request的getParameter方法进行增强
            /*
             * 装饰者模式(包装)
             * 
             * 1、增强类与被增强的类要实现统一接口
             * 2、在增强类中传入被增强的类
             * 3、需要增强的方法重写,不需要增强的方法调用被增强对象的
             * 
             */
            //被增强的对象
            HttpServletRequest req = (HttpServletRequest) request;
            //增强对象
            EnhanceRequest enhanceRequest = new EnhanceRequest(req);
            
            chain.doFilter(enhanceRequest, response);
            
        }
    
        @Override
        public void destroy() {
            
        }
        
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            
        }
    }
    
    class EnhanceRequest extends HttpServletRequestWrapper{ //HttpServletRequest也是实现了HttpServletRequestWrapper
        
        private HttpServletRequest request;
    
        public EnhanceRequest(HttpServletRequest request) {
            super(request);
            this.request = request;
        }
        
        //对getParameter增强,注意并没有对getParameterMap做增强
        @Override
        public String getParameter(String name) {
            String parameter = request.getParameter(name);//乱码
            try {
                parameter = new String(parameter.getBytes("iso8859-1"),"UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return parameter;
        }
        
    }
    EncodingFilter.java
    public class EncodingServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            
            String parameter = request.getParameter("username");//直接获得中文
            
            System.out.println(parameter);
            
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    }
    EncodingServlet.java
      <!-- 编码统一处理的filter -->
      <filter>
          <filter-name>EncodingFilter</filter-name>
          <filter-class>com.ithiema.web.filter.EncodingFilter</filter-class>
      </filter>                
      <filter-mapping>
          <filter-name>EncodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
    web.xml
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <form action="/WEB24/encodingServlet" method="get">
            <input type="text" name="username">
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    encoding.jsp
  • 相关阅读:
    Html/CSS前端如何实现文字边框阴影
    酷炫,用Html5/CSS实现文字阴影
    前端“黑话”polyfill
    JavaScript之DOM对象获取(1)
    你知道二维码是怎么得来的吗?
    Spring5中的DispatcherServlet初始化
    一文搞懂并发和并行
    使用SecureCRT软件运维的配置习惯
    Linux双网卡绑定
    Linux网卡配置文件参数注释
  • 原文地址:https://www.cnblogs.com/zhaojiankai/p/7867866.html
Copyright © 2011-2022 走看看