javaweb開發之Filter

1、簡介

在Servlet2.3規範中定義了過濾器,它對servlet容器調用servlet的過程進行攔截,從而在servlet進行響應處理的先後實現一些特殊的功能。 java

過濾器實現了一個責任鏈的模式。多個過濾器造成一個過濾器鏈,過濾器鏈中不一樣過濾器的前後順序由部署文件web.xml中過濾器映射<filter-mapping>的順序決定。 web

最早截獲客戶端請求的過濾器將最後截獲Servlet/JSP的響應信息。 瀏覽器

Servlet過濾器能夠過濾的Web組件包括Servlet,JSP和HTML等文件。 緩存

Servlet過濾器能夠應用在客戶端和servlet之間、servlet和servlet或JSP頁面之間,以及所包括的每一個JSP頁面之間。 tomcat

2、原理

在Servlet中使用過濾器時,過濾器能夠對客戶端的請求進行處理。處理完成後,它會交給下一個過濾器處理,這樣,客戶的請求在過濾鏈裏逐個處理,直到請求發送到目標爲止。在目標處理結束後,會沿着最後一個過濾器反向一個個進行處理直至返回到客戶端。

3、Filter相關接口

1. Filter接口

全部的Servlet過濾器都必須實現javax.servlet.Filter接口,並實現該接口中的三個方法: app

init(FilterConfig filterConfig) jsp

Servlet過濾器的初始化方法,Servlet容器建立Servlet過濾器實例後將調用該方法。該方法將讀取web.xml文件中Servlet過濾器的初始化參數。 ide

該方法在tomcat啓動的時候執行。


doFilter(ServletRequest request, ServletResponse response, FilterChain chain) ui

該方法完成實際的過濾操做,當客戶端請求方法與過濾器設置匹配的URL時,Servlet容器將先調用過濾器的doFilter方法。FilterChain用戶訪問後續過濾器。 編碼

這裏的ServletRequest和ServletResponse通常須要轉換成具體的Servlet實現對於的對象,如:HttpServletRequest和HttpServletResponse。

有些過濾器比較消耗資源,因此須要防止重複過濾,能夠在doFilter()方法中判斷。



destroy()

Servlet容器在銷燬過濾器實例前調用該方法,在該方法中釋放Servlet過濾器佔用的資源。

2. FilterConfig接口

Filter的init方法中提供了一個FilterConfig對象,提供相關的操做:

如獲取Filter中配置的初始化參數:
<filter>
      <filter-name>LoginFilter</filter-name>
      <filter-class>cn.heimar.LoginFilter</filter-class>
      <init-param>
          <param-name>username</param-name>
          <param-value>admin</param-value>
      </init-param>
</filter>
在init方法中獲取:
@Override
public void init(FilterConfig filterConfig) throws ServletException {
    //獲取Filter初始化參數
    String username = filterConfig.getInitParameter("username");
}

3. 在Filter中訪問application

ServletContext context = filterConfig.getServletContext();
或者在doFilter方法中根據轉換好的request獲取:
HttpServletRequest req = (HttpServletRequest)request;
ServletContext context = req.getSession().getServletContext();

4、定義過濾器

public class MyFilter implements Filter {

    public void init(FilterConfig fc) {
        //過濾器初始化代碼
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain){
        //在這裏能夠對客戶端請求進行檢查
        //沿過濾器鏈將請求傳遞到下一個過濾器。
        chain.doFilter(request, response);
        //在這裏能夠對響應進行處理
    }

    public void destroy( ) {
        //過濾器被銷燬時執行的代碼
    }

}

5、過濾器映射

在web.xml文件中添加以下代碼來聲明Filter:
<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>
        cn.edu.uibe.webdev.MyFilter
    </filter-class>
    <init-param>
        <param-name>developer</param-name>
        <param-value>TongQiang</param-value>
    </init-param>
</filter>
<!--針對一個Servlet作過濾-->
<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <servlet-name>MyServlet</servlet-name>
</filter-mapping>
<!--針對URL Pattern作過濾-->
<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/book/*</url-pattern>
</filter-mapping>

/* 攔截全部資源及不存在的資源

*.jsp 攔截全部jsp文件

默認狀況下forward方式不會被過濾。通常是須要過濾的,方式是在filter-mapping中添加<dispatcher>FORWARD</dispatcher>,該值默認是request,添加時爲了防止覆蓋request,須要把該值也添加。

6、常見應用

能夠對客戶提交的數據進行從新編碼。
使瀏覽器不緩存頁面。
過濾不和諧的文字。

能夠驗證用戶是否登陸。


對客戶端提交的數據進行從新編碼示例:

EncodingFilter.java

package cn.heimar.filter.encoding;

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;

	/**
	 * 是否須要強制轉碼
	 */
	private boolean forceEncoding = false;

	@Override
	public void init(FilterConfig config) throws ServletException {
		encoding = config.getInitParameter("ENCODING");
		String force = config.getInitParameter("FORCE_ENCODING");
		if (force != null)
			forceEncoding = Boolean.valueOf(force);
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;

		if ((request.getCharacterEncoding() == null || forceEncoding)
				&& encoding != null){
			request.setCharacterEncoding(encoding);
                }
		response.setCharacterEncoding(encoding);
		chain.doFilter(req, resp);
	}

	@Override
	public void destroy() {

	}

}
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">

	<filter>
		<filter-name>EncodingFilter</filter-name>
		<filter-class>cn.heimar.filter.encoding.EncodingFilter</filter-class>
		<!-- 配置編碼格式 -->
		<init-param>
			<param-name>ENCODING</param-name>
			<param-value>utf-8</param-value>
		</init-param>
		<!-- 配置是否強轉 -->
		<init-param>
			<param-name>FORCE_ENCODING</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	
	<servlet>
		<servlet-name>LoginServlet</servlet-name>
		<servlet-class>cn.heimar.filter.encoding.LoginServlet</servlet-class>
	</servlet>
	
	<filter-mapping>
		<filter-name>EncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<servlet-mapping>
		<servlet-name>LoginServlet</servlet-name>
		<url-pattern>/login</url-pattern>
	</servlet-mapping>

</web-app>
相關文章
相關標籤/搜索