Servlet 过滤器原理

来源:互联网 发布:python前端书单 编辑:程序博客网 时间:2024/05/22 00:14

Servlet 过滤器原理

Servlet 过滤器是小型的 Web 组件,它们拦截请求和响应,
以便查看、提取或以某种方式操作正在客户机和服务器之间交换的数据。
过滤器是通常封装了一些功能的 Web 组件,这些功能虽然很重要,
但是对于处理客户机请求或发送响应来说不是决定性的。
典型的例子包括记录关于请求和响应的数据、处理安全协议、

1.1声明式的:过滤器通过 Web 部署描述符(web.xml)中的 XML 标签来声明。
这样允许添加和删除过滤器,而无需改动任何应用程序代码或 JSP 页面。 

1.2动态的:过滤器在运行时由 Servlet 容器调用来拦截和处理请求和响应。 

1.3灵活的:过滤器在 Web 处理环境中的应用很广泛,涵盖诸如日志记录和安全等许多最公共的辅助任务。
过滤器还是灵活的,因为它们可用于对来自客户机的直接调用执行预处理和后期处理,
以及处理在防火墙之后的 Web 组件之间调度的请求。最后,可以将过滤器链接起来以提供必需的功能。 

1.4模块化的:通过把应用程序处理逻辑封装到单个类文件中,过滤器从而定义了可容易地从请求/响应链中添加或删除的模块化单元。 

1.5可移植的:与 Java 平台的其他许多方面一样,Servlet 过滤器是跨平台和跨容器可移植的,
从而进一步支持了 Servler 过滤器的模块化和可重用本质。 

1.6可重用的:归功于过滤器实现类的模块化设计,以及声明式的过滤器配置方式,过滤器可以容易地跨越

1.7透明的:在请求/响应链中包括过滤器,这种设计是为了补充servlet 或 JSP 页面提供的核心处理。
因而,过滤器可以根据需要添加或删除,而不会破坏 servlet 或 JSP 页面。 


Servlet过滤器是Servlet的一种特殊用法,主要用来完成一些通用的操作。
比如编码的过滤,判断用户的登陆状态等等。
Servlet过滤器的适用场合:

  A.认证过滤

  B.登录和审核过滤 
C.图像转换过滤 
D.数据压缩过滤 
E.加密过滤 
F.令牌过滤 
G.资源访问触发事件过滤 


Servlet过滤器接口的构成: 
所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。
这个接口含有3个过滤器类必须实现的方法: 
init(FilterConfig cfg) 这是Servlet过滤器的初始化方法,性质等同与servlet的init方法。 
doFilter(ServletRequest,ServletResponse,FilterChain) 完成实际的过滤操作,当请求访问过滤器关联的URL时,Servlet容器将先调用过滤器的doFilter方法。
FilterChain参数用于访问后续过滤器 
destroy() Servlet容器在销毁过滤器实例前调用该方法,这个方法中可以释放Servlet过滤器占用的资源。性质等同与servlet的destory()方法。 

Servlet过滤器的创建步骤: 
A.实现javax.servlet.Filter接口的servlet类 
B.实现init方法,读取过滤器的初始化函数 
C.实现doFilter方法,完成对请求或过滤的响应 
D.调用FilterChain接口对象的doFilter方法,向后续的过滤器传递请求或响应 
E.在web.xml中配置Filter 
2.使用过滤器处理中文问题 
当用用户登陆页面输入帐号时,如果输入是中文,后台servlet再次输出这个内容时,
可能就会是乱码,这是因为serlvet中默认是以ISO-8859-1格式编码的,
如果后台有多个Servlet,多个参数,这样就不合适,这个问题,
我们可以通过一个过滤器统一解决,使后台的输出输出都支持中文!
将ISO-8859-1转码为GBK的那段代码!

3.使用过滤器认证用户: 
每个过滤器也可以配置初始化参数,可以将不需要过滤的地址配置到这个Filter的配置参数中,
过滤时,如果请求地址在配置参数中,则放行,这样就避免了在程序中硬编码。

  每个Filter中初始化时,都可以得到配置对象,在Filter中配置二个不需要过滤的地址,

  一个是登陆页面,一个是执行登陆认证的servlet; 
4.Servlet监听器 
类似与Swing界面应用开发,Servlet也可以创建监听器,以对Servlet容器,或Servlet中以象的事件做出反应。
Servlet监听器主要有以下几种: 
ServletRequestListener ,
ServletRequestAttributeListener, 
HttpSessionActivationListener ,
HttpSessionBindingListener , 
HttpSessionAttributeListener,
HttpSessionListener, 
ServletContextListener
... 
这些监听器主要用来监听session,request,application这三个对象里存取数据的变化。 
----------------------------------------------------------------------------------------------------
2.Servlet 过滤器体系结构

Servlet 过滤器用于拦截传入的请求和/或传出的响应,并监视、修改或以某种方式处理正在通过的数据流。
过滤器是自包含、模块化的组件,可以将它们添加到请求/响应链中,
或者在无需影响应用程序中其他 Web 组件的情况下删除它们。
过滤器仅只是改动请求和响应的运行时处理,因而不应该将它们直接嵌入 Web 应用程序框架,
除非是通过 Servlet API 中良好定义的标准接口来实现。 
当过滤器在 Servlet 2.3 规范中首次引入时,它们只能过滤 Web 客户机和客户机所访问的指定 Web 资源之间的内容。
如果该资源然后将请求调度给其他 Web 资源,那就不能向幕后委托的任何请求应用过滤器。
Servlet 过滤器现在可以应用于 J2EE Web 环境中存在请求和响应对象的任何地方。
Servlet 过滤器可以应用在客户机和 servlet 之间、servlet 和 servlet 或 JSP 页面之间,
以及所包括的每个 JSP 页面之间。它非常强大能力和灵活性!
----------------------------------------------------------------------------------------------------
3.1编写实现类的程序
过滤器 API 包含 3 个简单的接口,它们整洁地嵌套在 
为了与我们的三步模式保持一致,过滤器必须运用三个方法,以便完全实现 Filter 接口: 

init() :这个方法在容器实例化过滤器时被调用,它主要设计用于使过滤器为处理做准备。
该方法接受一个 FilterConfig 类型的对象作为输入。 

doFilter() :与 servlet 拥有一个 service() 方法(这个方法又调用 doPost() 或者 doGet() )来处理请求一样,
过滤器拥有单个用于处理请求和响应的方法―― doFilter() 。
这个方法接受三个输入参数:一个 ServletRequest 、 response 和一个 FilterChain 对象。 
destroy() :
正如您想像的那样,这个方法执行任何清理操作,这些操作可能需要在自动垃圾收集之前进行。
sample code list

SessionFilter.java
package net.pms.web.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;
import javax.servlet.http.HttpServletResponseWrapper;

/**
* @author jfish
* @since 2006.1.12
*/
public class SessionFilter implements Filter {

public static boolean isContains(String container, String[] regx) {
boolean result = false;

for (int i = 0; i < regx.length; i++) {
if (container.indexOf(regx) != -1) {
return true;
}
}
return result;
}

public FilterConfig config;

public void setFilterConfig(FilterConfig config) {
this.config = config;
}

public FilterConfig getFilterConfig() {
return config;
}

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {

HttpServletRequest httpreq = (HttpServletRequest) request;
HttpServletResponse httpres = (HttpServletResponse) response;

HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper(
(HttpServletResponse) response);
String logonStrings = config.getInitParameter("logonStrings");
String includeStrings = config.getInitParameter("includeStrings");
String redirectPath = httpreq.getContextPath()
+ config.getInitParameter("redirectPath");
String disabletestfilter = config.getInitParameter("disabletestfilter");

if (disabletestfilter.toUpperCase().equals("Y")) {
chain.doFilter(request, response);
return;
}
String[] logonList = logonStrings.split(";");
String[] includeList = includeStrings.split(";");
Object user = httpreq.getSession().getAttribute("userinfo");
if (user == null) {
if (!this.isContains(httpreq.getRequestURI(), includeList)) {
chain.doFilter(request, response);
return;
}
if (this.isContains(httpreq.getRequestURI(), logonList)) {
chain.doFilter(request, response);
return;
}
wrapper.sendRedirect(redirectPath);

} else {
chain.doFilter(request, response);
}
}

public void destroy() {
this.config = null;
}

public void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
}
}


3.2配置 Servlet 过滤器
在web.xml中:
<filter>
<filter-name>SessionFilter</filter-name>
<filter-class>net.pms.web.filter.SessionFilter</filter-class>
<init-param>
<param-name>logonStrings</param-name>
<param-value>login.jsp</param-value>
</init-param>
<init-param>
<param-name>includeStrings</param-name>
<param-value>.jsp;.html</param-value>
</init-param>
<init-param>
<param-name>redirectPath</param-name>
<param-value>/login.jsp</param-value>
</init-param>
<init-param>
<param-name>disabletestfilter</param-name>
<param-value>N</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
其中参数logonStrings,登陆页面
includeStrings,过滤页面参数
redirectPath,没有登陆转向页面
disabletestfilter,过滤器是否有效。
----------------------------------------------------------------------------------------------------
4.1字符集过滤类:
package net.pms.web.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;
/**

* @author jfish
* @since 2006.1.12
*
*/
public class SetCharacterEncodingFilter implements Filter {


protected String encoding = null;

protected FilterConfig filterConfig = null;

protected boolean ignore = true;

public void destroy() {

this.encoding = null;
this.filterConfig = null;

}

public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {

// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null)) {
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}

// Pass control on to the next filter
chain.doFilter(request, response);

}

public void init(FilterConfig filterConfig) throws ServletException {

this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
String value = filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;

}

protected String selectEncoding(ServletRequest request) {

return (this.encoding);

}

}
4.2
在web.xml中配置如下:
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>net.pms.web.filter.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
不过,在spring中带有此过滤器
在web.xml中配置如下:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>

0 0
原创粉丝点击