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 学习(八)的更多相关文章

  1. Servlet学习(八)——Session

    1.Session技术 Session技术是将数据存储在服务器端的技术,会为每个客户端都创建一块内存空间存储客户的数据,但客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内存空间.所以说Ses ...

  2. JSP&Servlet学习手册

    JSP&Servlet学习手册 沙琪玛 书 目录 JSP 指令... 3 书写方式... 3 指令列表... 3 JSP 内置对象... 3 内置对象特点... 3 常用内置对象... 3 o ...

  3. Python Tutorial 学习(八)--Errors and Exceptions

    Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...

  4. Servlet 学习笔记

    Servlet 运行在服务器上的 java 类: Servlet 容器为 javaWeb 应用提供运行时环境,负责管理 servlet 和 jsp 生命周期,以及管理他们的共享数据. 现在我们知道了 ...

  5. Servlet学习:(三)Servlet3.0 上传文件

    转: Servlet学习:(三)Servlet3.0 上传文件 2018年08月03日 11:57:58 iDark_CSDN 阅读数:362   一.注意事项 客户端(浏览器) 表单的提交方法必须是 ...

  6. SVG 学习<八> SVG的路径——path(2)贝塞尔曲线命令、光滑贝塞尔曲线命令

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  7. Servlet学习(九)——request

    request运行流程在Servlet学习(四)——response已介绍,不再赘述 1.通过抓包工具获取Http请求 因为request代表请求,所以我们可以通过该对象分别获得Http请求的请求行, ...

  8. # jsp及servlet学习笔记

    目录 jsp及servlet学习笔记 JSP(Java Server Page Java服务端网页) 指令和动作: servlet(小服务程序) jsp及servlet学习笔记 JSP(Java Se ...

  9. Servlet学习笔记(四)

    目录 Servlet学习笔记(四) 一.会话技术Cookie.session 1. 什么是会话技术? 2. 会话技术有什么用? 3. Cookie 3.1 什么是Cookie? 3.2 使用Cooki ...

  10. Servlet学习笔记(三)

    目录 Servlet学习笔记(三) 一.HTTP协议 1.请求:客户端发送欸服务器端的数据 2.响应:服务器端发送给客户端的数据 3.响应状态码 二.Response对象 1.Response设置响应 ...

随机推荐

  1. sklearn 线性回归

    # import numpy as np import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplo ...

  2. 【Vue CLI】从安装到构建项目再到目录结构的说明

    目录 1. 构建我们的项目 2. 目录结构说明 2.1 build目录 2.2 config目录 2.3 src目录 2.4 static目录 "Vue CLI是一个基于Vue.js进行快速 ...

  3. Spring整合JDBC和Druid连接池

    我的博客名为黑客之谜,喜欢我的,或者喜欢未来的大神,点一波关注吧!顺便说一下,双十二快到了,祝大家双十二快乐,尽情的买买买~ 如果转载我的文章请标明出处和著名,谢谢配合. 我的博客地址为: https ...

  4. CSS3的一个伪类选择器:nth-child()

    CSS3的一个伪类选择器“:nth-child()”. Table表格奇偶数行定义样式: 语法: :nth-child(an+b) 为什么选择她,因为我认为,这个选择器是最多学问的一个了.很可惜,据我 ...

  5. Bugku-CTF加密篇之+[]- (+++++ +++++ [->++ +++++ +++<] >++.+ +++++ .<+++ [->-- -<]>- -.+++ +++.< ++++[ ->.........)

    +[]- +++++ +++++ [->++ +++++ +++<] >++.+ +++++ .<+++ [->-- -<]>- -.+++ +++.< ...

  6. localhost: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

    在开启hadoop时候报错:localhost: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password). 此时 ssh ...

  7. Gradle是什么?

    Gradle是什么? Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建工具.它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的 ...

  8. 脚本中的random几率问题详解

    random解释: 没有固定数值,随即给的意思,数值越大就几率越低,跟爆率也不多,如下脚本,所有都抽不到的话,就会执行最后面没有检测条件的那个.   [@main] #if random 10 #ac ...

  9. python练习:斐波那契数列的递归实现

    python练习:斐波那契数列的递归实现 重难点:递归的是实现 def fib(n): if n==0 or n==1: return 1 else: return fib(n-1)+fib(n-2) ...

  10. 「POI2010」Bridges

    传送门 Luogu团队题链接 解题思路 首先二分答案,然后在所有边权小于二分值的边和所有点组成的图中判欧拉回路. 由于可能出现混合图,所以要用到网络流. 把所有无向边钦定一个方向,那么原图就是一个有向 ...