Servlet过滤器
Servlet过滤器
1.过滤器的基本概念
1.1.基本概念
过滤器(Filter)属于tomcat服务器中的Servlet功能。在普通的javaweb服务中,jsp中的请求要被Servlet来处理,但是很多对请求做一些操作或者判断,比如用户的每次请求都要判断是不是已经登录,这个时候就可以使用到过滤器,过滤器的作用就相当于Servlet的一个门,jsp的请求从这个门进来,也要从这个门出去
通过过滤器Filter技术,对web服务器管理的所有web资源,例如:jsp,Servlet,静态图片或静态html进行拦截,从而实现一些功能。例如:实现URL级别的权限访问控制,过滤敏感词,压缩响应信息等一些高级功能
1.2.过滤器的生命周期
过滤器只有三个方法:init(),doFilter(),destory()。
在tomcat在启动的就执行init()方法创建过滤器,
当jsp有请求传进来的时候就会调用doFilter()方法来执行。doFilter()方法来中一定要有chain.doFilter()这个方法,这个是放行,使过滤器中的请求能进进入下一个过滤器或者Servlet
在程序结束的时候调用destroy()方法来销毁过滤器实例
1.3.过滤器的执行流程
1.文字描述过滤器执行过程
过滤器在程序中的执行流程是:
1.用户访问服务器
2.过滤器:对Servlet请求进行拦截
3.请求先进入过滤器,过滤器处理请求
4.过滤器处理完之后,再放行,此时请求到达下一个过滤器或Servlet/JSP
5.下一个过滤器处理再传给Servlet,或者直接Servlet处理
6.Servlet处理完后,再回到过滤器,最后再由tomcat服务器响应用户
2.过滤器执行过程的时序图:

3.代码描述过滤器的执行过程
为了用代码说明过滤器的执行过程,这里用三个代码来说明,第一个脚本是第一个过滤器oneFilter.java;第二个脚本是第二个过滤器secFilter.java;第三个脚本是Servlet脚本,整个执行过程就是按照代码里面的序号来执行的
第一个过滤器:
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 oneFilter implements Filter{
// 创建实例
public HelloFilter(){
System.out.println("1. 创建过滤器实例");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("2. 执行过滤器初始化方法");
}
// 过滤器业务处理方法: 在请求到达servlet之前先进入此方法处理公用的业务逻辑操作
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("3. 执行过滤器业务处理方法");
// 放行 (去到Servlet)
// 如果有下一个过滤器,进入下一个过滤器,否则就执行访问servlet
chain.doFilter(request, response);
System.out.println("7. Servlet处理完成,又回到过滤器");
}
@Override
public void destroy() {
System.out.println("8. 销毁过滤器实例");
}
}
第二个过滤器
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 secFilter implements Filter{
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("4.第二个过滤器开始执行");
// 放行,访问Servlet
chain.doFilter(request, response);
System.out.println("6.第二个过滤器执行结束");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
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;
/**
* Servlet:
* 处理用户http request
*
*/
public class IndexServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("5.处理用户请求");
}
}
整个执行过程就是1->2->3->4->5->6->7->8;
4.Filter开发步骤
Filter开发要分为两步:
1.编写java类实现Filter接口,并实现其doFilter方法,在web.xml文件中使用和元素对编写的filter类进行注册,并设置它多能拦截的资源
2.在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链
web服务器根据Filter在web.xml文件中的注册顺序,决定先调用那个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个Filter链的FilterChain对象传递给该方法
2.过滤器的常用方法
2.1.过滤器常用API
interface Filter 过滤器核心接口
void init(filterConfig);初始化方法,在服务器启动时调用
Void doFilter(request,response,filterChain); 过滤器拦截的业务处理方法
Void destroy(); 销毁过滤器实例时候调用
在init中涉及到filterConfig接口,这个接口的作用是获取在web.xml中配置的Filter的初始化参数信息
常用方法如下:
getInitParameter(String name);指定参数名字来获取参数值
getInitParameterNames();获取所有Filter的参数名
在doFilter中使用到FilterChain接口,该接口的作用是,形成一个Filter执行链。
void doFilter(request,response);执行下一个过滤器或放行
代码示例如下:
web.xml的配置文件,主要包括两个过滤器的配置和第一个过滤器的初始化参数
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--过滤器配置-->
<filter>
<!--配置初始化参数-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>path</param-name>
<param-value>/home/cenyu</param-value>
</init-param>
<!--内部名称-->
<filter-name>oneFilter</filter-name>
<!--过滤器类的全名-->
<filter-class>d_filter.onrFilter</filter-class>
</filter>
<filter-mapping>
<!--filter内部名-->
<filter-name>oneFilter</filter-name>
<!--拦截所有资源-->
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--配置第二个过滤器-->
<filter>
<filter-name>secFilter</filter-name>
<filter-class>d_filter.secFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>secFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
三个接口的使用方式:
package d_filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.util.Enumeration;
@WebFilter(filterName = "onrFilter")
public class onrFilter implements Filter {
public onrFilter(){
System.out.println("1.创建过滤器实例");
}
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("3.执行过滤器业务处理方法");
chain.doFilter(req, resp);
System.out.println("5.Servlet处理完成,又回到过滤器");
}
public void init(FilterConfig config) throws ServletException {
System.out.println("2.执行过滤器初始化方法");
//获取过滤器在web.xml中配置的初始化参数
String encoding=config.getInitParameter("encoding");
System.out.println(encoding);
//获取过滤器在web.xml中配置的所有初始化参数的名称
Enumeration<String> enums = config.getInitParameterNames();
//遍历参数名称和值
while (enums.hasMoreElements()){
//获取国有参数名称:encoding, path
String name = enums.nextElement();
//获取名相应的值
String value = config.getInitParameter(name);
System.out.println(name+"\t"+value);
}
}
}
2.2.xml配置文件中配置指定的请求拦截
<filter-mapping>
<!--filter内部名-->
<filter-name>oneFilter</filter-name>
<!--1.拦截所有资源-->
<!--/*表示拦截多有的请求-->
<url-pattern>/*</url-pattern>
<!--2.拦截指定的jsp-->
<!--拦截多个jsp时,可以直接在下面再写一个,也可以使用通用写法-->
<url-pattern>/index.jsp</url-pattern>
<url-pattern>/list.jsp</url-pattern>
<!--连接所有jsp-->
<url-pattern>*.jsp</url-pattern>
<!--3.根据servlet的内存名连接-->
<servlet-name>indexServlet</servlet-name>
<!--或者这里放servlet的匹配url来拦截servlet-->
<url-pattern>/index</url-pattern>
<!--4.指定拦截指定的类型-->
<!--拦截请求,默认拦截的类型-->
<dispatcher>REQUEST</dispatcher>
<!--拦截转发-->
<dispatcher>FORWARD</dispatcher>
<!--拦截包含的页面,例:(RequestDispatcher.include(/page.jsp));对page.jsp也进行拦截-->
<dispatcher>INCLUDE</dispatcher>
<!--拦截错误页面配置-->
<dispatcher>ERROR</dispatcher>
</filter-mapping>
3.过滤器案例
3.1.案例:处理中文编码
问题来源
在项目中,java默认是ISO-8859-1编码,而中文常用的是UTF-8或者gbk。于是几乎每一个Servlet都要设计编码处理,即处理请求中数据中文的问题!
如果在每一个Servlet中写处理方法则过于繁琐,此时可以把公用代码抽取出来,然后写在过滤器中,就可以了。
代码实现思路
1.login.jsp:登录,输入“中文”
2.loginServlet.java;直接处理登录请求
3.EncodingFilter.java:过滤器处理请求数据编码:分GET/POST两种式的提交处理
代码实现:
本例中jsp写一个有POST和GET请求的表单,一个过滤器,一个Servlet处理程序
jsp页面:
<%--
Created by IntelliJ IDEA.
User: cenyu
Date: 16-12-19
Time: 下午3:12
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/login" method="post">
用户名:<input type="text" name="userName"><br/>
<input type="submit" value="POST提交">
</form>
<hr/>
<form action="${pageContext.request.contextPath}/login" method="get">
用户名:<input type="text" name="userName"><br/>
<input type="submit" value="GET提交">
</form>
</body>
</html>
过滤器
package encodeFilter_demo;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 编码处理统一写到这里(Servlet中不需要在处理编码)
* Created by cenyu on 16-12-19.
*/
@WebFilter(filterName = "EncodingFilter")
public class EncodingFilter implements Filter {
public void destroy() {
}
//过滤器业务处理方法:处理的公用的业务逻辑操作
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//转型
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
//1处理公用业务
request.setCharacterEncoding("UTF-8"); //POST提交有效
response.setContentType("text/html;chartset=UTF-8");
//放行
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
Servlet程序;
package encodeFilter_demo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
*编码统一处理案例中的Servlet脚本
* Created by cenyu on 16-12-19.
*/
@WebServlet("/login")
public class loginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求数据
String name = request.getParameter("userName");
System.out.println("用户:"+name);
}
}
过滤器的web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--编码处理过滤器配置-->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>encodeFilter_demo.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
3.2.过滤敏感词汇
效果:实现模拟过滤论坛过敏词汇
实现思路:
1.dis.jsp 讨论区页面
2.disServlet.java 处理请求
- 获取请求参数
- 保存到request域
- 跳转到dis.jsp(从request取数据显示(处理后))
3.dataFilter.java 过滤器
- 编码
- 无效数据处理
即:在上一个案例基础上,再添加无效数据过滤的相关代码
代码示例:
jsp的显示和接收页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>无效数据过滤</title>
</head>
<body>
${requestScope.content}
<form name="frmdis" action="${pageContext.request.contextPath}/disServlet" method="post">
发表评论:<textarea rows="6" cols="3" name="content"></textarea>
<br/>
<input type="submit" value="提交">
</form>
</body>
</html>
过滤器中的代码:
package encodeFilter_demo;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 无效数据过滤
*/
@WebFilter(filterName = "dataFilter")
public class dataFilter implements Filter {
//初始化无效数据
private List<String> dirtyData;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;chartset=UTF-8");
//中午数据已经处理完成,下面进行无效数据过滤
String content = req.getParameter("content");
//如果volue中出现dirtyData中数据,用****替换
if (content != null && !"".equals(content)) {
for (String data : dirtyData) {
//判断当前输入数据(value),是否包含无效数据
if (content.contains(data)) {
content = content.replace(data, "***");
request.setAttribute("content",content);
break;
}
}
}
//放行
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
//模拟无效几个数据
dirtyData = new ArrayList<String>();
dirtyData.add("NND");
dirtyData.add("三胖");
}
}
Servlet中的代码:
package encodeFilter_demo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by cenyu on 16-12-19.
*/
@WebServlet("/disServlet")
public class DisServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求数据
String content = (String) request.getAttribute("content");
//保存到request
request.setAttribute("content","Content: "+content);
//转发
request.getRequestDispatcher("/dis.jsp").forward(request,response);
}
}
Servlet过滤器的更多相关文章
- Servlet过滤器Filter用法
1 Servlet 过滤器方法 过滤器是一个实现了 javax.servlet.Filter 接口的 Java 类.javax.servlet.Filter 接口定义了三个方法:public void ...
- Servlet过滤器和监听器
1,Servlet过滤器 <filter> <filter-name>charset</filter-name> <filter-class>org.g ...
- Servlet 过滤器
一.过滤器介绍 在Servlet 2.3中定义了过滤器,它能够对Servlet容器的请求和响应进行检查和修改. Servlet过滤器能够在Servlet被调用之前检查Request对象,并修改Requ ...
- Servlet基础知识(四)——Servlet过滤器Filter
一.什么是过滤器: 政府大楼的安检保安,它既能对进入政府大楼的人员进行检查,只允许检查符合要求的进入:同时他也负责对出大楼的人进行检查,看他带出的东西是否符合要求. 同样的,Servlet中的过滤器既 ...
- Servlet过滤器——过滤器分析流量
1.概述 Servlet过滤器可以对用户提交的数据或服务器返回的数据进行更改.任何到达服务器的请求都会首先经过过滤器的处理.本实例应用过滤器的这个特点,编写了一个在过滤器中统计网站流量的实例. 本实例 ...
- Servlet过滤器——使用过滤器禁止浏览器缓存页面
1.概述 IE缓存虽然能提高已储存网站的访问速度,但是过度的IE缓存会影响浏览器的响应速度.同时还可能为网站的运行带来一些不必要的麻烦.例如:可能会因为浏览器缓存的应用,而导致Web服务器不能准确的计 ...
- Servlet过滤器和监听器知识总结(转)
Servlet过滤器和监听器知识总结(转) Servlet过滤器是 Servlet 程序的一种特殊用法,主要用来完成一些通用的操作,如编码的过滤.判断用户的登录状态.过滤器使得Servlet开发者能 ...
- servlet(2)servlet过滤器
1.servlet过滤器 用于动态的拦截servlet请求或响应,以变更或使用其中的信息. (1)过滤器和servlet是多对多的关系,即一个过滤器可以用于一个或多个servlet,多个过滤器也可以用 ...
- TODO java-web相关 servlet过滤器+监听器
servlet过滤器 定义: 过滤器是小型的web组件,它负责拦截请求和响应,以便查看.提供或以某种方式操作正在客户机和服务器之间交换的数据. 与过滤器相关的servlet共包含3个简单接口:Filt ...
随机推荐
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(60)-系统总结
系列目录 前言: 起初写这个框架的时候,可以说在当时来说并不是很流行的设计模式,那是在2012年,面向对象的编程大家都很熟悉, 但是“注入.控制反转(DI,IOC,依赖注入).AOP切面编程”新兴名词 ...
- Beginners Guide To Web Development
Web Development Front End Development Back End Development
- Android 中关于static的使用问题
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/5251564.html 项目中,在不停地接收串口数据很长一段时间(几小时)后,会偶然性的报错.初步排除了oom ...
- PHPStorm配置自己喜欢的主题
PHPstorm默认的主题和可选的主题有时候不能满足有些人的需求,怎么配置自己喜欢的主题呢? 1.首先先去下载自己喜欢的主题:http://www.phpstorm-themes.com/ 但是在下载 ...
- Python黑帽编程 3.4 跨越VLAN
Python黑帽编程 3.4 跨域VLAN VLAN(Virtual Local Area Network),是基于以太网交互技术构建的虚拟网络,既可以将同一物理网络划分成多个VALN,也可以跨越物理 ...
- PyQt4入门学习笔记(三)
# PyQt4入门学习笔记(三) PyQt4内的布局 布局方式是我们控制我们的GUI页面内各个控件的排放位置的.我们可以通过两种基本方式来控制: 1.绝对位置 2.layout类 绝对位置 这种方式要 ...
- Keil> 编译器特有的功能 > 关键字和运算符 > __weak
__weak 此关键字指示编译器弱导出符号. 可以将 __weak 关键字应用于函数和变量声明以及函数定义. 用法 函数和变量声明 对于声明,此存储类指定一个 extern 对象声明,即使不存在,也不 ...
- 静态代理和利用反射形成的动态代理(JDK动态代理)
代理模式 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 静态代理 1.新建 ...
- Python 历遍目录
Automate the Boring Stuff 学习笔记 01 使用 os 模块的 walk() 函数可以实现历遍目录的操作,该函数接收一个绝对路径字符串作为必选参数,返回三个参数: 当前目录—— ...
- php实现设计模式之 状态模式
<?php /*状态模式:允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它的类.(行为模式) * * 在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做 ...