javaweb——過濾器

過濾器

作用

​ 實現對web資源請求的攔截,完成特殊的操作,尤其是對請求的預處理。

應用場景

  • Web資源權限訪問控制
  • 字符集編碼處理
  • 內容敏感字符詞彙過濾
  • 響應信息壓縮

工作流程
在這裏插入圖片描述

過濾器的生命週期

  • 過濾器的創建和銷燬由web服務器負責
  1. web應用程序啓動時,web服務器創建Filter的實例對象 ,以及對象的初始化。(調用init()方法,這個方法只在tomcat服務器啓動的時候調用一次)
  2. 當請求訪問與過濾器關聯的web資源時(某個URL),過濾器攔截請求,完成指定功能(完成後交給下一個過濾器或者servlet進行處理)。(調用doFilter()方法,web程序運行期間可多次調用)
  3. Filter對象創建後會一直駐留在內存中,在web應用移除或服務器停止時才銷燬。(調用destory()方法)

過濾器鏈

  • 在一個web應用中,多個過濾器組合起來稱之爲一個過濾器鏈。(比如說有的請求不止需要被一個過濾器攔截進行處理[先是字符集編碼的處理的過濾器,再是判斷是否登錄的過濾器],這時就需要編寫多個過濾器類來分別處理)

  • 過濾器請求預處理的調用順序取決於過濾器在web.xml文件中的註冊順序,而過濾器響應後處理的調用順序取決於過濾器註冊順序的逆序。

    (web.xml的順序決定的是執行doFilter()的順序 並不決定init()的順序)

過濾器的實現步驟

編寫java類實現Filter接口

package 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;

//要實現javax.servlet.Filter接口,重寫下面三個方法
public class CharacterEncodingFilter implements Filter {

	@Override
	public void destroy() {
		//在過濾器銷燬的時候做一些清理工作
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		//完成過濾器的功能
        //request是請求預處理
        //reponse是響應後處理
        
        //不要忘記調用這個方法,意思是交給下一個過濾器或者servlet(請求本來要到達的地方)進行後續的操作處理
        chain.doFilter(request,response);
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		this.config = config;
		//在過濾器對象創建的時候做一些初始化操作
        
        //參數中FilterConfig是過濾器配置類,在配置Filter的時候會設置一些初始化參數(設置初始化參數都是在web.xml文件中或者註解中完成),把這些配置封裝成配置類對象傳入進來
      
        /*在web.xml中
        <filter>
        	.....註冊filter
        	<init-param>
        		<param-name>version</param-name>
        		<param-value>2.0</param-value>
        	</init-param>
        </filter>
        */
       
        /*
        	在init()函數中
        	通過 config.getInitParameter("version");能獲取version的值
        */
	}
}

在web.xml文件中對filter類進行註冊,並設置所攔截的資源

<!-- 註冊過濾器,讓web服務器識別到這個過濾器要對一些web請求做攔截處理-->
	<filter>
		<filter-name>TestFilter</filter-name>
		<filter-class>com.lxc.TestFilter</filter-class>
		
		<!--設置過濾器配置類的初始化參數  -->
		<init-param>
			<param-name>charset</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	
	<!--攔截映射的配置,指定過濾器對哪些請求做攔截處理  -->
	<!-- /*代表所有的請求都會被這個過濾器攔截  -->
	<filter-mapping>
		<filter-name>TestFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

配置要攔截的資源

  1. 以指定資源匹配。例如"/index.jsp"

  2. 以目錄匹配。例如"/servlet/*"

  3. 以後綴名匹配,例如"*.jsp"

  4. 通配符,攔截所有web資源。"/*"

  5. 攔截多個頁面

    <filter>  
        <filter-name>authority</filter-name>  
        <filter-class>com.util.AuthorityFilter</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>authority</filter-name>  
        <url-pattern>/pages/genbill/*</url-pattern>  
    </filter-mapping>  
    <filter-mapping>  
        <filter-name>authority</filter-name>  
        <url-pattern>/pages/cmm/*</url-pattern>  
    </filter-mapping>  
    

filter-mapping的子元素dispather

必須寫在filter-mapping的最後。dispatcher的前提條件當然是要先滿足url-pattern,然後是dispatcher屬性。

<filter-mapping>
	<filter-name>testFilter</filter-name>
	<url-pattern>/test2.jsp</url-pattern>
	<dispatcher>REQUEST</dispatcher>
</filter-mapping>

如果不寫dispatcher這個子屬性,那麼默認是REQUEST

dispatcher有四種可能的屬性:
1、REQUEST
只要發起的操作是一次HTTP請求,比如請求某個URL、發起了一個GET請求、表單提交方式爲POST的POST請求、表單提交方式爲GET的GET請求。一次重定向則前後相當於發起了兩次請求,這些情況下有幾次請求就會走幾次指定過濾器。
2、FOWARD
只有噹噹前頁面是通過請求轉發轉發過來的情形時,纔會走指定的過濾器 (但該過濾器必須指定了<dispatcher>FORWARD</dispatcher>
3、INCLUDE
只要是通過<jsp:include page="xxx.jsp" />,嵌入進來的頁面,每嵌入的一個頁面,都會走一次指定的過濾器。
4、ERROR
假如web.xml裏面配置了<error-page></error-page>

<error-page>
 <error-code>400</error-code>
 <location>/filter/error.jsp</location>
</error-page>

<error-page>
 <error-code>404</error-code>
 <location>/filter/error.jsp</location>
</error-page>

不管這個請求是從哪裏發過來的(jsp還是過濾器),發送方是什麼方式就按什麼方式匹配。

也可以把四種可能都寫上,四種情況都會攔截

	<filter-mapping>
		<filter-name>testFilter</filter-name>
		<url-pattern>/test2.jsp</url-pattern>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>INCLUDE</dispatcher>
		<dispatcher>ERROR</dispatcher>
	</filter-mapping>

使用註解配置Filter

在這裏插入圖片描述

@WebFilter(filterName = "CharsetFilter",
        urlPatterns = { "/AddServlet","/qiantai/order.jsp","/RemoveServlet", "/UserOrderingServlet" },
        dispatcherTypes = {DispatcherType.ASYNC,DispatcherType.ERROR},/*枚舉類型*/
        initParams = {
                @WebInitParam(name = "charset", value = "utf-8"),/*這裏可以放一些初始化的參數*/				@WebInitParam(name = "contenttype", value = "text/html;charset=utf-8")
        })

使用註解配置的話,filter的執行順序(過濾器類doFilter()方法的執行順序)跟過濾器類的類名的字母順序有關,例如AFilter.java會比BFilter.java先執行

請求和響應字符集編碼處理

package 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 CharacterEncodingFilter implements Filter {

	//接收過濾配置類對象
	private FilterConfig config;

	@Override
	public void destroy() {

	}

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

		//不直接設置爲UTF-8,而是把編碼的信息放在web.xml文件中,以後直接修改web.xml中的初始化參數就行,避免了java代碼的重新編譯等操作
		// 根據過濾器配置字符集,設置請求字符集編碼
		request.setCharacterEncoding(config.getInitParameter("charset"));
		response.setContentType(config.getInitParameter("responsecharset"));
		chain.doFilter(request, response);
	}

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

web.xml文件

	<!-- 字符集編碼過濾器配置 -->
	<filter>
		<filter-name>characterEncodingFilter</filter-name>
		<filter-class>filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>charset</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
        <init-param>
          <param-name>responsecharset</param-name>
          <param-value>text/html;charset=utf-8</param-value>
    	</init-param>
	</filter>

	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

登錄驗證

使用註解配置過濾器,攔截的時候不能攔截全部頁面,不然會出現很多後續的麻煩


@WebFilter(filterName = "LoginFilter", urlPatterns = "*.jsp", dispatcherTypes = {})
public class SessionFilter implements Filter {

	@Override
	public void destroy() {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest hrequest = (HttpServletRequest)request;
		HttpServletResponse hresponse = (HttpServletResponse)response;
		
		String loginUser = (String)hrequest.getSession().getAttribute("loginUser");//從session對象中獲取登錄用戶名
		
		if(loginUser==null){//登錄用戶名不存在,用戶未登錄,強制重定向至登陸頁面
			hresponse.sendRedirect(hrequest.getContextPath()+"/index.jsp?flag=1");
			return;
			
		}else{
			chain.doFilter(request, response);//已登錄,轉入相應的請求處理
			return;
		}

	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {

	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章