Servlet 学习(八)
Filter
1、功能
- Java Servlet 2.3 中新增加的功能,主要作用是对Servlet 容器的请求和响应进行检查和修改
- Filter 本身并不生成请求和响应对象,它只提供过滤作用
在Servlet 被调用之前,检查Request 对象
»可以对其Request Header 和Request 内容进行审查和修改
在Servlet 调用结束之后,检查Response 对象
»可以对其Response Header 和Response 内容进行审查和修改
- Filter 可以过滤的Web 组件包括Servlet,JSP,HTML等
- Filter主要负责拦截请求,和放行。
- Filter 过滤过程

2、接口Filter
- init( FilterConfig config )
Filter 的初始化方法
容器创建Filter 之后将调用这个方法
使用这个方法可以读取web.xml 文件中定义的初始化参数
- doFilter(ServletRequest req,ServletResponse resp ,FilterChain chain)
该方法完成实际的过滤操作
当客户请求访问与Filter 相关联的URL 时,将调用该方法
chain 用于访问后续的Filter 或Servlet
- destroy()
容器在销毁Filter 实例前调用该方法
该方法中可以释放该Filter 所占用的资源
- Filter的生命周期
Filter的创建和销毁由web服务器控制。
»服务器启动的时候,web服务器创建Filter的实例对象,并调用其init方法,完成对象的初始化功能。filter对象只会创建一次,init方法也只会执行一次。
»拦截到请求时,执行doFilter方法。可以执行多次。
»服务器关闭时,web服务器销毁Filter的实例对象。
3、接口FilterChain
- 过滤器链
- 一组过滤器对某些web资源进行拦截,那么这组过滤器就称为过滤器链。过滤器的执行顺序和<filter-mapping>有关

- 该接口中定义的方法
doFilter(ServletRequest req,ServletResponse resp )
»负责把所有的过滤器给串联起来
»使得一个过滤器执行完后,下一个可以继续执行
»被串联的多个过滤器按照配置文件中的映射顺序依次执行
4、创建Filter
- 实现Filter
package ecut.filter.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 HelloFilter implements Filter { public void init(FilterConfig config) throws ServletException {
} public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
// place your code here
System.out.println( "hello" ); // pass the request along the filter chain
chain.doFilter( req, resp ); System.out.println( "world" );
} public void destroy() {
} }
- 注册Filter
<filter>
<filter-name>HelloFilter</filter-name>
<filter-class>ecut.filter.filter.HelloFilter</filter-class>
</filter>
- 发布Filter
同Servlet 一样,url-pattern 可以写多个
url-mapping匹配规则有三种:
»精确匹配 —— 如/index.html,只会匹配index.html这个URL
»路径匹配 —— 如/*,会匹配所有的URL
»后缀匹配 —— 如*.html,会匹配所有以.html为后缀的URL
<filter-mapping>
<filter-name>HelloFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 测试案例
package ecut.filter.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 HelloServlet extends HttpServlet { private static final long serialVersionUID = -8731391727918781480L; @Override
protected void service( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException { System.out.println( "service" ); response.setContentType( "text/html" ); PrintWriter w = response.getWriter(); w.println( "<h2 style='text-align:center;'>你好 , Servlet .</h2>" ); } }
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>ecut.filter.servlet.HelloServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/filter/hello</url-pattern>
</servlet-mapping>
在浏览器中访问HelloServle
运行结果如下:
hello
service
world

5、在config中指定初始化参数
- 用 户在配置filter时,可以使用<init-param>为filter配置一些初始化参数,当web容器实例化Filter对象,调用其 init方法时,会把封装了filter初始化参数的filterConfig对象传递进来
- 在web.xml 中可以指定初始化参数
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>ecut.filter.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
- 访问初始化参数
在init 方法中通过FilterConfig 对象访问
字符集过滤器测试案例:
package ecut.filter.filter; import java.io.IOException;
import java.nio.charset.Charset; import javax.servlet.DispatcherType;
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; public class CharacterEncodingFilter implements Filter{ private static final String ENCODING_PARAM = "encoding" ; private static final String DEFAULT_ENCODING = "UTF-8" ; private String encoding ; @Override
public void init( FilterConfig filterConfig ) throws ServletException {
System.out.println( "CharacterEncodingFilter 初始化" );
// 获取 Filter 的初始化参数
encoding = filterConfig.getInitParameter( ENCODING_PARAM );
// 如果 未指定初始化参数 或 初始化参数值是 空串 则采用默认编码
encoding = ( encoding == null || encoding.trim().isEmpty() ) ? DEFAULT_ENCODING : encoding ;
// 如果指定的编码名称不被JVM所支持,则采用默认编码
// encoding = Charset.isSupported( encoding ) ? encoding : DEFAULT_ENCODING ;
/*
if( ! Charset.isSupported( encoding ) ) { // 如果指定的字符集名称是不支持的
encoding = DEFAULT_ENCODING ;
}
*/
} @Override
public void doFilter( ServletRequest req , ServletResponse resp , FilterChain chain )
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req ;
String uri = request.getRequestURI();
DispatcherType type = request.getDispatcherType();
System.out.println( "CharacterEncodingFilter ::: DispatcherType : " + type + " , URI : " + uri );
// place your code here
req.setCharacterEncoding( encoding );
resp.setCharacterEncoding( encoding );
// pass the request along the filter chain
chain.doFilter( req , resp );
} @Override
public void destroy() {
System.out.println( "CharacterEncodingFilter 销毁" );
} }
运行结果:

解决中文乱码问题,使用过滤器后还需要 response.setContentType( "text/html" );否则仍然会乱码, 或者在响应中文中直接指定字符集response.setContentType( "text/html;charset=UTF-8" );
6、实现对指定的调度进行过滤
- 在web.xml 中可以指定过滤的请求REQUEST:直接访问目标资源时执行过滤器。包括:在地址栏中直接访问、表单提交、超链接、重定向,只要在地址栏中可以看到目标资源的路径,就是REQUEST;
- FORWARD:转发访问执行过滤器。包括RequestDispatcher#forward()方法、< jsp:forward>标签都是转发访问;
- INCLUDE:包含访问执行过滤器。包括RequestDispatcher#include()方法、< jsp:include>标签都是包含访问;
- ERROR:当目标资源在web.xml中配置为< error-page>中时,并且真的出现了异常,转发到目标资源时,会执行过滤器。
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
- 使得filter将会作用于直接从客户端过来的request,通过forward过来的request,通过include过来的request和通过<error-page>过来的request。如果没有指定任何< dispatcher >元素,默认值是REQUEST。
测试案例:
package ecut.filter.servlet; import java.io.IOException; import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @WebServlet( "/filter/action/login" )
public class LoginActionServlet extends HttpServlet { private static final long serialVersionUID = -7857947923197325636L; @Override
protected void service( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException { String username = request.getParameter( "username" );
String password = request.getParameter( "password" ); System.out.println( "username : " + username + " , password : " + password ); request.setAttribute( "username" , username ); RequestDispatcher dispatcher = request.getRequestDispatcher( "/filter/success/login" ); dispatcher.forward( request, response ); } }
package ecut.filter.servlet; import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @WebServlet( "/filter/success/login" )
public class LoginSuccessServlet extends HttpServlet { private static final long serialVersionUID = 2707448998600792264L; @Override
protected void service( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException { //String username = (String)request.getAttribute( "username" ); String username = request.getParameter( "username" );
System.out.println( "success : " + username ); response.setContentType( "text/html" ); response.getWriter().println( "<h1>" + username + " </h1>" ); } }
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Filter</title>
</head>
<body> <h5>登录</h5>
<form action="/s/action/login" method="post" >
<input type="text" name="username" placeholder="用户名">
<input type="password" name="password" placeholder="输入密码">
<input type="submit" value="登录">
</form> </body>
</html>
运行结果:
hello
CharacterEncodingFilter ::: DispatcherType : REQUEST , URI : /s/filter/action/login
IdentifyBrowserFilter ::: User Agent : mozilla/5.0 (windows nt 6.1; win64; x64; rv:59.0) gecko/20100101 firefox/59.0
username : 郑 , password : 123
CharacterEncodingFilter ::: DispatcherType : FORWARD , URI : /s/filter/success/login
success : 郑
world
8、使用注解
- Servlet 3.0 允许使用注解来标注Filter
- @WebFilter用以标注一个实现过Filter 接口的类
- 使用@WebFilter 标注不如web.xml 文件中可以通过映射顺序来控制过滤器的执行顺序
- @WebFilter 的常用属性
String filterName 指定当前Filter 的名称,相当于xml 中的filter-name
String[] value 指定当前Filter 对应的url (与url-pattern 对应)
String[] urlPatterns 与value 作用相同
DispatcherType[] dispatcherTypes 指定当前Filter 关联的dispatcher 类型
»默认值是DispatcherType.REQUEST
»javax.servlet.DispatcherType 是Servlet 3.0 新定义的枚举
boolean asyncSupported 指定是否支持异步操作
WebInitParam[] initParams 用于设置Filter 初始化参数
9、使用过滤器过滤浏览器
测试案例:
package ecut.filter.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 IdentifyBrowserFilter implements Filter { @Override
public void init( FilterConfig config ) throws ServletException {
} @Override
public void doFilter( ServletRequest req , ServletResponse resp , FilterChain chain )
throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req ;
HttpServletResponse response = (HttpServletResponse) resp ; String userAgent = request.getHeader( "user-agent" ); userAgent = userAgent.toLowerCase(); System.out.println( "IdentifyBrowserFilter ::: User Agent : " + userAgent ); // 如果在 userAgent 中找到了 trident 则说明目前正在使用 IE 访问
if( userAgent.indexOf( "trident" ) != - 1 ) {
String uri = request.getRequestURI();
System.out.println( "uri : " + uri );
int index = uri.lastIndexOf( "/" );
uri = uri.substring( 0 , index ) ;
System.out.println( "uri : " + uri ); index = uri.lastIndexOf( "/" );
uri = uri.substring( index ) ;
System.out.println( "uri : " + uri );
//解析字符串,如果访问的是IE目录下的就继续
if( "/ie".equals( uri ) ) {
chain.doFilter( req , resp );
} else {//如果访问的不是IE目录下的就重定向到ie.html
response.sendRedirect( request.getContextPath() + "/pages/filter/ie/ie.html" );
} } else {
// 如果是 非 IE 浏览器,则可以通过 FilterChain 向后传递 请求 和 响应
chain.doFilter( req , resp );
} } @Override
public void destroy() {
} }
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>珍爱生命,远离IE</title>
<link rel="stylesheet" href="/s/pages/filter/ie/ie.css" >
</head>
<body> <h2>珍爱生命,远离IE</h2> <h2>请使用现代浏览器: Chrome 、FireFox </h2> </body>
</html>
@CHARSET "UTF-8";
h2 {
text-align: center;
}
h2:first-child {
color: red ;
font-weight: bold ;
}
h2:last-child {
color: blue ;
}
运行结果:

转载请于明显处标明出处
http://www.cnblogs.com/AmyZheng/p/9024091.html
Servlet 学习(八)的更多相关文章
- Servlet学习(八)——Session
1.Session技术 Session技术是将数据存储在服务器端的技术,会为每个客户端都创建一块内存空间存储客户的数据,但客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内存空间.所以说Ses ...
- JSP&Servlet学习手册
JSP&Servlet学习手册 沙琪玛 书 目录 JSP 指令... 3 书写方式... 3 指令列表... 3 JSP 内置对象... 3 内置对象特点... 3 常用内置对象... 3 o ...
- Python Tutorial 学习(八)--Errors and Exceptions
Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...
- Servlet 学习笔记
Servlet 运行在服务器上的 java 类: Servlet 容器为 javaWeb 应用提供运行时环境,负责管理 servlet 和 jsp 生命周期,以及管理他们的共享数据. 现在我们知道了 ...
- Servlet学习:(三)Servlet3.0 上传文件
转: Servlet学习:(三)Servlet3.0 上传文件 2018年08月03日 11:57:58 iDark_CSDN 阅读数:362 一.注意事项 客户端(浏览器) 表单的提交方法必须是 ...
- SVG 学习<八> SVG的路径——path(2)贝塞尔曲线命令、光滑贝塞尔曲线命令
目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...
- Servlet学习(九)——request
request运行流程在Servlet学习(四)——response已介绍,不再赘述 1.通过抓包工具获取Http请求 因为request代表请求,所以我们可以通过该对象分别获得Http请求的请求行, ...
- # jsp及servlet学习笔记
目录 jsp及servlet学习笔记 JSP(Java Server Page Java服务端网页) 指令和动作: servlet(小服务程序) jsp及servlet学习笔记 JSP(Java Se ...
- Servlet学习笔记(四)
目录 Servlet学习笔记(四) 一.会话技术Cookie.session 1. 什么是会话技术? 2. 会话技术有什么用? 3. Cookie 3.1 什么是Cookie? 3.2 使用Cooki ...
- Servlet学习笔记(三)
目录 Servlet学习笔记(三) 一.HTTP协议 1.请求:客户端发送欸服务器端的数据 2.响应:服务器端发送给客户端的数据 3.响应状态码 二.Response对象 1.Response设置响应 ...
随机推荐
- vue天气查询
天气查询包括回车查询和点击查询两种功能 回车查询 1.按下回车(v-on+.enter) 2.查询数据(axios+接口+v-model) 3.渲染数据(v-for+arr) 点击查询 1.点击城市查 ...
- Linux shell sed 命令详解
详细的sed命令详解,请参考https://my.oschina.net/u/3908182/blog/1921761 sed命令常见用途 查找关键词做全局替换 查找某行的关键词做替换 查找关键字所在 ...
- UVA 10795 A Different Task(模拟)
题目链接:https://vjudge.net/problem/UVA-10795 一道比较有思维含量的一道题: 注意一种分治的思想和“除了柱子x和柱子y之外的那个柱子”编号的问题. 首先在初始局面和 ...
- 毕向东java基础总结
Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java ...
- git和github的关系以及简单易懂的理解
git和github的关系 写在前面:我身边好多人问我git和github的区别,想必对于好多人没学过的大佬们恐怕也是一脸懵逼,但是不知道也是不行的,所以我今天就来讲一讲这二者的区别和联系. 用一 ...
- vue 一些学习笔记
var, let, const 区别 //-----------------var----------------- var a = []; for(var i= 0; i < 10; i++) ...
- 专题一 Java基础语法
小辨析: println 输出字符后,下一个输出的字符会换行展示 print 输出字符后,下一个输出字符不会会换展示 system.out.println() 空格 分支结构:if-else使用说明 ...
- JS高级---体会面向对象和面向过程的编程思想
体会面向对象和面向过程的编程思想 ChangeStyle是自定义的构造函数,再通过原型添加方法的函数. 实例化对象,导入json参数,和创建cs,调用原型添加的方法函数 过渡,先熟悉记忆 <!D ...
- The Preliminary Contest for ICPC Asia Xuzhou 2019 J Random Access Iterator (树形DP)
每次循环向下寻找孩子时,随机选取一个孩子,设dp[u]为从u出发,不能得出正确答案的概率,则从u出发,走一次的情况下不能得出正确答案的概率是 P = (dp[v1]+dp[v2]+dp[v3]+--d ...
- JQuery checkbox多选框组选中提交,当选择某(无)一项,其他项禁止选中
在项目中难免会遇到一些表单的提交,尤其是多选框中,当用户选择了某一项时,禁止其他项的选择.所以为了避免这样的冲突,所以我们前端就得控制一下了,下面就来个简单demo,记录一下,有需要的伙伴可以拿去耍耍 ...