Servlet_5

1.java Servlet Filter(过滤器)
Filter是Servlet的过滤器,是Servlet 2.3规范中新增加的一个功能,主要用于完成一些通用的操作,如编码的过滤、判断用户的登录状态等。
Filter 被称为过滤器,其主要作用是对 Servlet 容器调用 Servlet 的过程进行拦截,从而在 Servlet 进行响应处理的前后实现一些特殊功能.

注意:过滤器是部署在服务器上的。
当用户通过浏览器访问服务器中的目标资源时,首先会被 Filter 拦截,在 Filter 中进行预处理操作,然后再将请求转发给目标资源。当服务器接收到这个请求后会对其进行响应,在服务器处理响应的过程中,也需要将响应结果经过滤器处理后,才发送给客户端。
本质上,Filter 过滤器就是一个实现了 javax.servlet.Filter 接口的类,在 javax.servlet.Filter 接口中定义了三个方法
方法声明 功能描述
init(FilterConfig filterConfig) init() 方法用于初始化过滤器,开发人员可以在 init() 方法中完成与构造方法类似的初始化功能,如果初始化代码中要使用到 FillerConfig 对象,那么,这些初始化代码就只能在 Filler 的 init() 方法中编写,而不能在构造方法中编写。
doFilter(ServletRequest request,ServletResponse response, FilterChain chain) doFilter() 方法有多个参数,其中,参数 request 和 response 为 Web 服务器或 Filter 链中的下一个 Filter 传递过来的请求和响应对象;
参数 chain 代表当前 Filter 链的对象,只有在当前 Filter 对象中的 doFilter() 方法内部需要调用 FilterChain 对象的 doFilter() 方法,才能把请求交付给 Filter 链中的下一个 Filter 或者目标程序处理。
destroy() destroy() 方法在 Web 服务器卸载 Filter 对象之前被调用,该方法用于释放被 Filter 对象打开的资源,例如关闭数据库和 I/O 流
表中的三个方法都是可以表现 Filter 生命周期的方法,其中 init() 方法在 Web 应用程序加载时会被调用,destroy() 方法在 Web 应用程序卸载(或关闭)时被调用,这两个方法都只会被调用一次,而 doFilter() 方法会被调用多次(只要客户端有请求时就会被调用),Filter 所有的工作集中在 doFilter() 方法中。
下面通过案例演示 Filter 程序如何对 Servlet 程序的调用过程进行拦截。
1、创建一个Servlet,充当目标资源

package com.wangxing.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 MyTestServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("MyTestServlet---");
		PrintWriter out=resp.getWriter();
		out.write("Hello MyServlet");
		out.close();
	}       
}

2.创建过滤器
1、创建新类,实现javax.servlet.Filter接口
2、重写init、doFilter、destroy方法
3、在doFilter中编写具体过滤动作
4、Web.xml配置过滤器

package com.wangxing.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;

public class MyTestFilter implements Filter {

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		System.out.println("init方法初始化过滤器");
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("doFilter方法过滤请求/响应对象");
		//FilterChain chain--过滤器链对象
		//doFilter(req,resp)--将请求/响应对象传递给下一个过滤性/目标资源
		 chain.doFilter(req, resp);        
		
	}
	@Override
	public void destroy() {
		 System.out.println("destory方法销毁过滤器对象");	
	}
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>TestFilterDemo1</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <filter>
  <filter-name>myfilter1</filter-name>
  <filter-class>com.wangxing.filter.MyTestFilter</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>myfilter1</filter-name>
  <url-pattern>/*</url-pattern> 
  </filter-mapping>
  <servlet>
  <servlet-name>mytest</servlet-name>
  <servlet-class>com.wangxing.servlet.MyTestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  <servlet-name>mytest</servlet-name>
  <url-pattern>/mytest</url-pattern>
  
  </servlet-mapping>
</web-app>


注意:过滤器可以直接对用户的请求作出响应,而不需要Servlet/目标资源的处理。
2.Java Servlet Filter的两种映射方式
创建 Filter 后,在 web.xml 中的对应配置信息就是 Filter 映射。Filter 的映射方式可分为两种。
1.使用通配符拦截用户的所有请求【–所有请求】

 <filter>
  <filter-name>myfilter1</filter-name>
  <filter-class>com.wangxing.filter.MyTestFilter</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>myfilter1</filter-name>
  <url-pattern>/*</url-pattern> 
  </filter-mapping>

例如:
当FORWARD表示通过RequestDispatcher 的 forward() 方法访问资源的时候才会使用当前配置的过滤器。当我们发送一个请求的时候,没有使用RequestDispatcher 的 forward() 方法时,是不会使用当前配置的过滤器。
2.拦截不同方式的访问请求
在 web.xml 文件中,每一个 元素都可以配置一个 Filter 所负责拦截的资源。在 元素中有一个特殊的子元素 ,该元素用于指定过滤器所拦截的资源被 Servlet 容器调用的方式。 元素的值共有四个。
名称 功能描述
REQUEST 当用户直接访问页面时,Web 容器将会调用过滤器。如果目标资源通过 RequestDispatcher 的 include() 或 forward() 方法访问,那么该过滤器将不会被调用
INCLUDE 如果目标资源通过 RequestDispatcher 的 include() 方法访问,那么该过滤器将会被调用。除此之外,该过滤器不会被调用
FORWARD 如果目标资源通过 RequestDispatcher 的 forward() 方法访问,那么该过滤器将会被调用。除此之外,该过滤器不会被调用
ERROR 如果目标资源通过声明式异常处理机制调用,那么该过滤器将会被调用。除此之外,该过滤器不会被调用
例如:

 <filter>
  <filter-name>myfilter1</filter-name>
  <filter-class>com.wangxing.filter.MyTestFilter</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>myfilter1</filter-name>
  <url-pattern>/*</url-pattern> 
  </filter-mapping>

例如:
当FORWARD表示通过RequestDispatcher 的 forward() 方法访问资源的时候才会使用当前配置的过滤器。当我们发送一个请求的时候,没有使用RequestDispatcher 的 forward() 方法时,是不会使用当前配置的过滤器。
3.拦截不同访问路径的访问请求
通过设置 元素中的指定不同的访问路径,来确定哪些资源可以访问当前过滤器,哪些资源不可以访问当前过滤器。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>TestFilterDemo2</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <filter>
  <filter-name>myfilter1</filter-name>
  <filter-class>com.wangxing.filter.MyTestFilter</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>myfilter1</filter-name>
  <url-pattern>/mytest</url-pattern> 
  </filter-mapping>
    <filter>
  	<filter-name>myfilter2</filter-name>
  	<filter-class>com.wangxing.filter.MyOtherFilter</filter-class>
   </filter>
   <filter-mapping>
  	<filter-name>myfilter2</filter-name>
  	<url-pattern>/myother</url-pattern>
  </filter-mapping> 
  <servlet>
  <servlet-name>mytest</servlet-name>
  <servlet-class>com.wangxing.servlet.MyTestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  <servlet-name>mytest</servlet-name>
  <url-pattern>/mytest</url-pattern>
  </servlet-mapping>
  <servlet>
  <servlet-name>myother</servlet-name>
  <servlet-class>com.wangxing.servlet.OtherTestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  <servlet-name>myother</servlet-name>
  <url-pattern>/myother</url-pattern>
  
  </servlet-mapping>
</web-app>

http://localhost:8080/TestFilterDemo3/mytest

http://localhost:8080/TestFilterDemo3/myother

3.FilterChain(过滤器链)详解
在一个 Web 应用程序中可以注册多个 Filter 程序,每个 Filter 程序都可以针对某一个 URL 进行拦截。如果多个 Filter 程序都对同一个 URL 进行拦截,那么这些 Filter 就会组成一个Filter 链(也称过滤器链)。
Filter 链用 FilterChain 对象表示,FilterChain 对象中有一个 doFilter() 方法,该方法的作用是让 Filter 链上的当前过滤器放行,使请求进入下一个 Filter。

在上图中,当浏览器访问 Web 服务器中的资源时,需要经过两个过滤器 Filter1 和 Filter2。首先 Filter1 会对这个请求进行拦截,在 Filter1 中处理完请求后,通过Filter 链 FilterChain 对象调用 doFilter() 方法将请求传递给 Filter2,Filter2 处理用户请求后同样FilterChain 对象调用 doFilter() 方法,最终将请求发送给目标资源。当 Web 服务器对这个请求做出响应时,也会被过滤器拦截,但这个拦截顺序与之前相反,最终将响应结果发送给客户端浏览器。

例如:

<filter>
  	<filter-name>base</filter-name>
  	<filter-class>com.wangxing.filter.BaseFilter</filter-class>
  </filter>
   <filter-mapping>
  	<filter-name>base</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping> 
  
  <filter>
  	<filter-name>myfilter2</filter-name>
  	<filter-class>com.wangxing.filter.MyOtherFilter</filter-class>
  </filter>
   <filter-mapping>
  	<filter-name>myfilter2</filter-name>
  	<url-pattern>/mytest</url-pattern>
  </filter-mapping> 

   <filter>
  	<filter-name>myfilter1</filter-name>
  	<filter-class>com.wangxing.filter.MyTestFilter</filter-class>
  </filter>
   <filter-mapping>
  	<filter-name>myfilter1</filter-name>
  	<url-pattern>/mytest</url-pattern>
  </filter-mapping> 
  

  <servlet>
  	<servlet-name>mytest</servlet-name>
  	<servlet-class>com.wangxing.servlet.MyTestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>mytest</servlet-name>
  	<url-pattern>/mytest</url-pattern>
  </servlet-mapping>
  http://localhost:8080/TestFilterDemo3/mytest


过滤器链中的每一个过滤器在执行的时候,与在web.xml文件中配置的顺序一致。
4.FilterConfig接口及其使用方法详解
FilterConfig接口与我们前面学习的ServletConfig接口相似。
FilterConfig 是 Servlet API 提供的一个用于获取 Filter 程序在 web.xml 文件中的配置信息的接口,该接口封装了 Filter 程序在 web.xml 中的所有注册信息,并且提供了一系列获取这些配置信息的方法。

例如

package com.wangxing.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 MyTestFilter implements Filter {

	
	@Override
	public void init(FilterConfig config) throws ServletException {
		System.out.println("init方法初始化过滤器");
		//测试FilterConfig接口对象的常用方法
		//String getFilterName()--- web.xml 文件中为 Filter 所设置的名称.
		String filtername=config.getFilterName();
		System.out.println("filtername=="+filtername);
		//String getInitParameter(String name)---得到web.xml文件中配置的指定的初始化参数值
		String myname=config.getInitParameter("myname");
		System.out.println("myname=="+myname);
		//Enumeration getInitParameterNames()---得到web.xml文件中配置的初始化参数的名称。
		Enumeration<String> initnameString=config.getInitParameterNames();
		 // 遍历所有的初始化参数名,得到相应的参数值并打印
		 while(initnameString.hasMoreElements()){
			 String paramname=initnameString.nextElement();
			 String value=config.getInitParameter(paramname);
			 System.out.println("初始化信息=="+paramname+"="+value);
		 }
	}
	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("MyTestFilter---doFilter方法过滤请求/响应对象");
		chain.doFilter(req, resp);
		
	}
	@Override
	public void destroy() {
		System.out.println("destroy方法销毁过滤器对象");
		
	}
}
package com.wangxing.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 MyTestServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("MyTestServlet----");
		PrintWriter out=resp.getWriter();
		out.write("<h1>Hello MyTestServlet</h1>");
		
	}

}

运行结果

5.Servlet Filter实现全站统一编码,解决中文乱码问题

package com.wangxing.filter;

import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class CharacterRequest extends HttpServletRequestWrapper{
    private HttpServletRequest request;
    private String encoding="utf-8";
	public CharacterRequest(HttpServletRequest request,String encoding) {
		super(request);
		this.request=request;
		this.encoding=encoding;
		
	}
	public String getParameter(String name){
		String value=request.getParameter(name);
		if(value==null){
			return null;
		}
		//得到请求的提交方式
		String method=request.getMethod();
		if ("get".equalsIgnoreCase(method)) {
			try{
				//tomcat8以后默认编码格式是utf-8;7之前的都是iso8859-1
				value=new String(value.getBytes(this.encoding),this.encoding);
				
			}catch(UnsupportedEncodingException e){
				throw new RuntimeException(e);
			}
		}
		return value;
	}

}
package com.wangxing.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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*
 * 编码过滤器【全站统一编码,解决中文乱码问题】
 */
public class EncodingFilter implements Filter	 {
	private String encoding="utf-8";
	@Override
	public void init(FilterConfig confing) throws ServletException {
		this.encoding=confing.getInitParameter("encoding");
		
	}
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
	 //转换ServletRequest为HttpServletRequest
		HttpServletRequest req=(HttpServletRequest)request;
		//转换ServletResponse为HttpServletRequest
		HttpServletResponse resp=(HttpServletResponse)response;
	    //设置请求和响应的字符编码
		//解决post请求的中文乱码
		req.setCharacterEncoding(this.encoding);
	    resp.setCharacterEncoding(this.encoding);
	    resp.setContentType("text/html;charset="+this.encoding);
	    //解决get请求的中文乱码
	    //重写getParameter方法
	    //对request进行包装
	    CharacterRequest characterRequest = new CharacterRequest(req,this.encoding);
	    chain.doFilter(characterRequest, resp);	
	
	}
	@Override
	public void destroy() {
		// TODO Auto-generated method stub		
	}
}
package com.wangxing.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 MyTestServlet  extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("MyTestServlet---");
		String myname=req.getParameter("myname");
		System.out.println("myname=="+myname);
		PrintWriter out=resp.getWriter();
		out.write("Hello MyServlet==myname=="+myname);
		out.close();
	}
}

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>EncodingFilter</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <filter>
  <filter-name>encodingfilter</filter-name>
  <filter-class>com.wangxing.filter.EncodingFilter</filter-class>
  <init-param>
  <param-name>encoding</param-name>
  <param-value>utf-8</param-value>  
  </init-param>
  </filter>
  <filter-mapping>
  <filter-name>encodingfilter</filter-name>
  <url-pattern>/*</url-pattern>
  </filter-mapping>
  <servlet>
  <servlet-name>mytest</servlet-name>
  <servlet-class>com.wangxing.servlet.MyTestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  <servlet-name>mytest</servlet-name>
  <url-pattern>/mytest</url-pattern> 
  </servlet-mapping>
</web-app>

运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值