过滤器

来源:互联网 发布:大数据应用的主要领域 编辑:程序博客网 时间:2024/05/14 11:26

过滤器:

 * 概述:

   * Filter的作用:

      起到过滤的作用.


   * Filter执行的时机:

     * 在执行对应的Servlet之前.(过滤Request对象中的内容)

     * 在执行对应的Servlet之后.(过滤Response对象中的内容)


   * 发展:

     * Filter最早在Servlet 2.3版本提供.

     * Filter在Servlet 2.5版本完善.


    运行原理:




 * 如何使用Filter:

   * Filter是JavaEE提供的一个接口.(自定义Filter需要实现该接口,并重写所有方法)
   * Filter提供的方法:
     * init()
     * doFilter()

     * destroy() 


   * 实现步骤:

     * 创建Java类,实现Filter接口,并且重写所有方法.
     * 在web.xml文件中进行配置.
         
 <filter><filter-name>MyFilter1</filter-name><filter-class>app.java.filter.MyFilter1</filter-class> </filter> <filter-mapping><filter-name>MyFilter1</filter-name><url-pattern>/*</url-pattern> </filter-mapping>



MyFIlter1.java:

package app.java.filter;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;/** * 自定义过滤器: *  * 实现Filter接口,并且重写该接口提供所有的方法. * @author JYL * */public class MyFilter1 implements Filter {/** * Filter的构造函数: *  * 执行时机:在Tomcat服务器启动时. *  * 执行次数:在Filter的生命周期中只执行一次. *    * Filter与Servlet一样,都是单例多线程的.(线程安全问题) */public MyFilter1() {System.out.println("这是MyFilter1的构造函数...");}/** * init(FilterConfig config)方法: *  * 作用:用于过滤器的初始化. *  * 执行时机:在Tomcat服务器启动时. *  * 执行次数:在Filter的生命周期中只执行一次. */public void init(FilterConfig config) throws ServletException {System.out.println("这是MyFilter1的init()方法...");}/** * doFilter(ServletRequest request, ServletResponse response,FilterChain chain)方法: *  * 作用:用于过滤器的过滤. *  * 执行时机:客户端访问当前Filter拦截的资源路径时. *  * 执行次数:在Filter的生命周期中,每次拦截,每次执行. */public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {System.out.println("这是MyFilter1的doFilter()方法...");//过滤器的放行chain.doFilter(request, response);}/** * destroy()方法: *  * 作用:用于过滤器的销毁. *  * 执行时机:在Tomcat服务器关闭时. *  * 执行次数:在Filter的生命周期中只执行一次. */public void destroy() {System.out.println("这是MyFilter1的destroy()方法...");}}

web.xml:

  <filter>  <filter-name>MyFilter1</filter-name>  <filter-class>app.java.filter.MyFilter1</filter-class>  </filter>    <filter>  <filter-name>MyFilter2</filter-name>  <filter-class>app.java.filter.MyFilter2</filter-class>  <init-param>  <param-name>mingjiao</param-name>  <param-value>zhangwuji</param-value>  </init-param>  </filter>



 * Filter的生命周期:

   * 出生:Hello World
     * init()方法
   * 活着:Love World
     * doFilter()方法
   * 死去:GoodBye World

     * destroy()方法


 * 过滤器链:

   * 问题:
     * 如何定义过滤器被执行的先后顺序?
     * Filter的doFilter()方法具有一个参数FilterChain,通过调用chain.doFilter()方法可以放行.
       * 在过滤器链中,执行chain.doFilter()方法,是否还是放行的作用?
       * 如果是,应该被放行到哪里去了?(单个Filter时,直接被放行到对应的Web资源[Servlet、JSP])
   * 解决以上问题:
     * chain.doFilter()方法依旧是放行方法.
     * 如果执行的不是过滤器链中最后一个过滤器的话,执行chain.doFilter()方法,会被放行到下一个过滤器里.
     * 如果执行的是过滤器链中最后一个过滤器的话,chain.doFilter()方法,才会被放行到对应Web资源中.

     * 过滤器链中的过滤器执行的先后顺序由web.xml文件中的<filter-mapping>标签定义的先后顺序决定.


再建一个filter:

package app.java.filter;import java.io.IOException;import java.util.Enumeration;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;public class MyFilter2 implements Filter {public void destroy() {}public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {System.out.println("这是MyFilter2的doFilter()方法...");chain.doFilter(request, response);}public void init(FilterConfig config) throws ServletException {System.out.println("这是MyFilter2的init()方法...");Enumeration enums = config.getInitParameterNames();while (enums.hasMoreElements()) {String name = (String) enums.nextElement();String value = config.getInitParameter(name);System.out.println(name+" : "+value);}}}


xml:

 <filter>  <filter-name>MyFilter1</filter-name>  <filter-class>app.java.filter.MyFilter1</filter-class>  </filter>    <filter>  <filter-name>MyFilter2</filter-name>  <filter-class>app.java.filter.MyFilter2</filter-class>  <init-param>  <param-name>mingjiao</param-name>  <param-value>zhangwuji</param-value>  </init-param>  </filter>



   * 实际开发的意义:

     * 单个Filter完成单个任务.


 * FilterConfig
   * 读取web.xml文件中的初始化参数.
   * 在web.xml文件中是如何配置的:
          <filter><filter-name>MyFilter2</filter-name><filter-class>app.java.filter.MyFilter2</filter-class><init-param><param-name>mingjiao</param-name><param-value>zhangwuji</param-value></init-param>  </filter>


   * FilterConfig的用法与ServletConfig一致.

   * 在web.xml文件中配置全局初始化参数<context-param>,通过ServletContext对象读取.


 * Filter的映射配置:<url-pattern>
   * 完全匹配:/xxxx
   * 目录匹配:/aaaa/
   * 扩展名匹配:*.do
   * 优先级别:完全匹配 -> 目录匹配 -> 扩展名匹配


   * 如果当前Filter拦截对应Servlet的话:
     * 还可以使用<servlet-name>标签  就是把<filter-mapping>里的<url-pattern>标签改为<servlet-name>
   
   * Filter拦截Servlet默认情况是拦截直接请求.
     * 在web.xml文件中配置<filter-mapping>标签中具有<dispatcher>
     * <dispatcher>标签在同一个Filter的配置中,可以配置多个.
     * <dispatcher>标签的值:
       * REQUEST:是默认值,表示一次请求.
       * FORWARD:表示请求转发到.
       * INCLUDE:表示包含(例如JSP包含另一个JSP等)

       * ERROR:表示JSP的<%@ page errorPage=""%>


在MyFilter2.java中对MyServlet2进行拦截:


xml:

  <filter-mapping>  <filter-name>MyFilter2</filter-name>  <servlet-name>MyServlet2</servlet-name>  <dispatcher>REQUEST</dispatcher>  <dispatcher>FORWARD</dispatcher>  </filter-mapping>  <filter-mapping>  <filter-name>MyFilter1</filter-name>  <url-pattern>/*</url-pattern>  </filter-mapping> 


MyServlet1.java:

package app.java.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class MyServlet1 extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.getRequestDispatcher("/servlet2").forward(request, response);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}

MyServlet2.java:

package app.java.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class MyServlet2 extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {System.out.println("这是Servlet2.........");}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}

此时访问Servlet2可以直接访问2,也可以通过1的请求转发访问:

直接访问servlet2:


访问servlet1:


没有执行拦截的任务

 * Filter的生命周期:

   * 出生:Hello World
     * init()方法
   * 活着:Love World
     * doFilter()方法
   * 死去:GoodBye World

     * destroy()方法



   * 扩展:

     * 面向对象:这个人就是对象,

                          年龄、性别等是属性,

                           出生、上学、结婚等方法.
       * 类与对象的区别:
         * 类:比作女生.
 * 对象:就是范冰冰.
       * 实现、继承、多态、封装等概念.


     * 面向过程:这个人从出生,长大、上学、工作、...、去世.



 

 * Filter的案例:

   * 全站乱码案例:
     * 利用Servlet的doGet()和doPost()方法中,可以解决中文乱码:
       * doGet()
         String value = request.getParameter("");
value = new String(value.getBytes("ISO8859-1"),"utf-8");

response.setContentType("text/html;charset=utf-8");


       * doPost()
         request.setCharacterEncoding("utf-8");

response.setContentType("text/html;charset=utf-8");


     * 以上问题:
       * 实际开发时,Web应用程序的逻辑比较复杂(多个Servlet).
       * 上述的解决方案,仅能解决当前Servlet的中文乱码问题.

       * 如果使用上述方案,解决中文乱码问题:代码重复性太多.


使用过滤器来解决:

EncodingFilter.java:

package app.java.filter.demo1;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 当前Filter用于解决全站中文乱码问题. * @author JYL */public class EncodingFilter implements Filter {public void destroy() {}public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {//1 进行Request与Response对象的类型强转HttpServletRequest request = (HttpServletRequest)req;HttpServletResponse response = (HttpServletResponse)resp;//2 解决中文乱码问题:1)请求的中文乱码(GET\POST);2)响应的中文乱码.request.setCharacterEncoding("utf-8");//针对post方式response.setContentType("text/html;charset=utf-8");//3 放行chain.doFilter(request, response);}public void init(FilterConfig arg0) throws ServletException {}}


TestServlet.java:(Servlet)

package app.java.filter.demo1;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class TestServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");System.out.println(username+" : "+password);response.getWriter().println("中文解决了,真好!!!!");}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");System.out.println(username+" : "+password);response.getWriter().println("中文解决了,真好!!!!");}}


index.jsp:

  <body>    <c:if test="${empty user }">    <h1><a href="login.jsp">去登录</a></h1>    </c:if>    <c:if test="${not empty user }">    <h1>欢迎你,${user }!</h1>    </c:if>    <form action="test" method="post">    用户名:<input type="text" name="username"><br>    密码:<input type="password" name="password"><br>    <input type="submit" value="提交">    </form>    <a href="test?username=张无忌&password=123">GET方式发送的请求</a>  </body>

xml:

 <filter>  <filter-name>EncodingFilter</filter-name>  <filter-class>app.java.filter.demo1.EncodingFilter</filter-class>  </filter> <filter-mapping>  <filter-name>EncodingFilter</filter-name>  <url-pattern>/*</url-pattern>  </filter-mapping>



针对get方式:

偷梁换柱:


MyRequest:

package app.java.filter.demo1;import java.io.UnsupportedEncodingException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;/** * 自定义的Request对象 * @author JYL */public class MyRequest extends HttpServletRequestWrapper {public MyRequest(HttpServletRequest request) {super(request);}@Overridepublic String getParameter(String name) {//此处的getParameter有可能是get也有可能是post                                     //而这个方法是针对Get方式的,所以要进行判断String value = super.getParameter(name);if(super.getMethod().equalsIgnoreCase("GET")){try {value = new String(value.getBytes("ISO-8859-1"),"utf-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}}return value;}}

EncodingFilter.java:

package app.java.filter.demo1;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 当前Filter用于解决全站中文乱码问题. * @author JYL */public class EncodingFilter implements Filter {public void destroy() {}public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {//1 进行Request与Response对象的类型强转HttpServletRequest request = (HttpServletRequest)req;HttpServletResponse response = (HttpServletResponse)resp;//2 解决中文乱码问题:1)请求的中文乱码(GET\POST);2)响应的中文乱码.request.setCharacterEncoding("utf-8");//针对post方式response.setContentType("text/html;charset=utf-8");//3 创建自定义的Request对象MyRequest myRequest = new MyRequest(request);//3 放行chain.doFilter(myRequest, response);}public void init(FilterConfig arg0) throws ServletException {}}

TestServlet.java:

package app.java.filter.demo1;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class TestServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");System.out.println(username+" : "+password);response.getWriter().println("中文解决了,真好!!!!");}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");System.out.println(username+" : "+password);response.getWriter().println("中文解决了,真好!!!!");}}



   * 自动登录案例:

     * 



登录页面:

  <body>    <c:if test="${empty user }">    <h1><a href="login.jsp">去登录</a></h1>    </c:if>    <c:if test="${not empty user }">    <h1>欢迎你,${user }!</h1>    </c:if>    <form action="test" method="post">    用户名:<input type="text" name="username"><br>    密码:<input type="password" name="password"><br>    <input type="submit" value="提交">    </form>    <a href="test?username=张无忌&password=123">GET方式发送的请求</a>  </body>


处理登录的servlet:

package app.java.filter.demo2;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 当前Servlet用于处理用户登录逻辑. *  * */public class LoginServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doPost(request, response);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");if(username==null||password==null||"".equals(username)||"".equals(password)){// 说明用户没有输入用户名和密码request.setAttribute("error_msg", "请输入你的用户名和密码!");request.getRequestDispatcher("/login.jsp").forward(request, response);}else if(username.equals("admin")&&password.equals("admin")){// 获取自动登陆的值,进行判断String autologin = request.getParameter("autologin");if("on".equals(autologin)){Cookie cookie = new Cookie("user",username+"#"+password);cookie.setMaxAge(60*60*24*7);cookie.setPath("/");response.addCookie(cookie);}request.getSession().setAttribute("user", username);response.sendRedirect("/day0106/index.jsp");}}}

过滤器:

package app.java.filter.demo2;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;/** * 当前Filter用于完成用户自动登录功能. * @author JYL */public class AutoLoginFilter implements Filter {public void destroy() {}public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest)req;Cookie[] cookies = request.getCookies();if(cookies != null){for (Cookie cookie : cookies) {if(cookie != null){String name = cookie.getName();if("user".equals(name)){// 曾经登录过String value = cookie.getValue();String username = value.split("#")[0];String password = value.split("#")[1];request.getSession().setAttribute("user", username);chain.doFilter(request, resp);}else{// 没有登陆过chain.doFilter(request, resp);}}}}else{// 没有登陆过chain.doFilter(request, resp);}}public void init(FilterConfig arg0) throws ServletException {}}


xml:

<filter>  <filter-name>AutoLoginFilter</filter-name>  <filter-class>app.java.filter.demo2.AutoLoginFilter</filter-class>  </filter> <filter-mapping>  <filter-name>AutoLoginFilter</filter-name>  <url-pattern>/index.jsp</url-pattern>  </filter-mapping>




 * Filter的生命周期:

   * 出生:Hello World
     * init()方法
   * 活着:Love World
     * doFilter()方法
   * 死去:GoodBye World

     * destroy()方法

0 0
原创粉丝点击