过滤器

过滤器:

 * 概述:

   * 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);
	}
	
	@Override
	public 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值