過濾器應用案例分析

----------------------------------------------------------------------------------------------
[版權申明:本文系做者原創,轉載請註明出處
文章出處:http://blog.csdn.net/sdksdk0/article/details/52077359
做者:朱培      ID:sdksdk0      郵箱: zhupei@tianfang1314.cn   css

--------------------------------------------------------------------------------------------html

 

本文主要分享的內容是經過使用過濾器解決全站亂碼、Html過濾、髒話過濾、Gzip壓縮過濾等主要內容,是一個切實解決網站實際問題的一套方案。java

1、過濾器簡介

 

Filter,對web服務器管理的全部web資源對請求和響應對象進行攔截。例如實現URL級別的權限訪問控制、過濾敏感信息。git

 

下面來看一下過濾器的執行過程和生命週期github

生命週期

 

初始化:當應用被加載時,由服務器調用默認的構造方法,並接着調用初始化方法。
doFilter:一直伴隨着應用程序而存在,用戶每次訪問被過濾的資源,都會調用doFilter方法。
銷燬:應用被卸載的時候。


web

執行過程

 

一、在javaweb服務器:服務器啓動時加載應用,加載應用的配置文件web.xml,實例化過濾器並初始化。
二、瀏覽器請求index.jsp。
三、建立request和response,通過過濾器,調用request,response,FilterChain。
四、經過FilterChain()處理。瀏覽器

 

開發步驟

一、寫一個類,繼承Filter接口
二、配置web.xml。指定須要過濾的資源

緩存

    <!-- 定義過濾器 -->
	<filter>
		<filter-name>Demo1</filter-name>
		<filter-class>cn.tf.filter.Demo1</filter-class>
	</filter>
	
	<!-- 映射要過濾的資源 -->
	<filter-mapping>
		<filter-name>Demo1</filter-name>
		<url-pattern>/index.jsp</url-pattern>
	</filter-mapping>



2、全站亂碼

 

咱們之前對於網站亂碼的問題大多數是直接在servlet中rerquest.setCharacterEncoder("UTF-8")這樣來解決,可是對於多個servlet重複也的話就很是很差了,及其不方便,因此咱們可使用一個過濾器來對整站的編碼進行設置。服務器

新建一個類SetCharacterEncodingFilter,使其繼承Filter接口。而後實現其3個生命週期方法init()、doFilter()、destroy(),固然,咱們須要對其doFilter方法進行操做了。在這裏面設置編碼就能夠了app

public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		String encoding = filterConfig.getInitParameter("encoding");
		if(encoding==null)
			encoding = "UTF-8";
		
		request.setCharacterEncoding(encoding);//解決POST請求參數編碼
		response.setCharacterEncoding(encoding);//更改響應字符流使用的編碼
		response.setContentType("text/html;charset="+encoding);//更改響應字符流使用的編碼,還能告知瀏覽器用什麼編碼進行顯示
		chain.doFilter(request, response);
	}

使用chain.doFilter釋放攔截。

而後咱們就到web.xml中去配置一個這個過濾器。這個找到你直接的類路徑就能夠了,/*是通配符,表示全站過濾,若是你只想要過濾某一種類型的文件,只須要修改相應的<url-pattern>就能夠了,例如是想要jsp的格式改變,就改爲*.jsp便可。

 

<filter>
	  	<filter-name>SetCharacterEncodingFilter</filter-name>
	  	<filter-class>cn.tf.filter.SetCharacterEncodingFilter</filter-class>
	  </filter>
	  <filter-mapping>
	  	<filter-name>SetCharacterEncodingFilter</filter-name>
	  	<url-pattern>/*</url-pattern>
	  </filter-mapping>



 

3、Html過濾

對於一個網站來講,進行html過濾是很是有必要的,由於在執行某些操做的時候,頗有看經過html文件對你的網站注入html進行攻擊,一方面防止攻擊,一方面使用戶體驗度更好,因此咱們經常須要進行html標籤過濾。

首先新建一個類HtmlFilter,使其繼承Filter接口,在doFilter中進行操做。

public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request;
		HttpServletResponse response;
		
		try {
			request=(HttpServletRequest) req;
			response=(HttpServletResponse) resp;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		HttpServletRequest hrequest=new HtmlHttpServletRequest(request);
		chain.doFilter(hrequest,response);
		
	}

這裏咱們把HtmlHttpServletRequest寫出來

class HtmlHttpServletRequest extends HttpServletRequestWrapper{

	public HtmlHttpServletRequest(HttpServletRequest request) {
		super(request);
		
	}
	
	@Override
	public String getParameter(String name) {
		
		String value=super.getParameter(name);
		if(value==null)
			return null;
		value=filter(value);
		return value;
	}

	private String filter(String message) {
		 if (message == null)
	            return (null);

	        char content[] = new char[message.length()];
	        message.getChars(0, message.length(), content, 0);
	        StringBuilder result = new StringBuilder(content.length + 50);
	        for (int i = 0; i < content.length; i++) {
	            switch (content[i]) {
	            case '<':
	                result.append("<");
	                break;
	            case '>':
	                result.append(">");
	                break;
	            case '&':
	                result.append("&");
	                break;
	            case '"':
	                result.append(""");
	                break;
	            default:
	                result.append(content[i]);
	            }
	        }
	        return (result.toString());
	}
	}
	




一樣的,咱們須要在web.xml中進行配置

 <!-- 過濾html -->
	 <filter>
	 <filter-name>HtmlFilter</filter-name>
	  	<filter-class>cn.tf.filterHtml.HtmlFilter</filter-class>
	  </filter>
	  <filter-mapping>
	  	<filter-name>HtmlFilter</filter-name>
	  	<url-pattern>/*</url-pattern>
	  </filter-mapping>


處理前效果:


處理後:


 

 

4、髒話過濾

對於髒話過濾在一些論壇網站等都是很是常見的功能,實現這個功能的方法很是多,你能夠直接用js來作判斷也是能夠,這裏我介紹的是另外一種方法,就是經過過濾器來對髒話進行過濾,把髒話都替換爲*號。

一樣的,新建一個類DirtyWordsFilter.java,實現其Filter接口。

public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request;
		HttpServletResponse response;
		
		try {
			request=(HttpServletRequest) req;
			response=(HttpServletResponse) resp;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		DWHttpServletRequest  dwrequest=new DWHttpServletRequest(request) ;
		chain.doFilter(dwrequest, response);
	}

在這裏對髒話進行處理。

class DWHttpServletRequest extends HttpServletRequestWrapper{

		private String[] strs={"傻逼","人妖","他媽的"};
		
		public DWHttpServletRequest(HttpServletRequest request) {
			super(request);
			
		}
		
		@Override
		public String getParameter(String name) {
			String value=super.getParameter(name);
			if(value==null)
				return null;
			
			for(String s:strs){
				value=value.replace(s, "**");
			}
			return value;
		}
		
	}


處理前效果:

 

處理後效果:

 

5、Gzip壓縮

在網站數據傳輸的時候,咱們一般爲了節省流量,加快傳輸速度等緣由,一般須要把文件進行壓縮,不可是用戶請求的頁面,例如當用戶訪問你的index.html頁面的時候,從你的服務器傳輸到用戶的客戶端,若是直接傳輸整我的html頁面是很耗資源的(固然是對於大量用戶訪問),因此咱們須要把頁面壓縮以後再傳輸,這個咱們就能夠經過過濾器來實現了。

新建GzipFilter.java,使其繼承Filter接口。

 

public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request;
		HttpServletResponse response;
		
		try {
			request=(HttpServletRequest) req;
			response=(HttpServletResponse) resp;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		MyHttpServletResponse  mresponse=new MyHttpServletResponse(response);
		chain.doFilter(request, mresponse);
		
		//獲取原始數據
		byte b[] = mresponse.getOldData();
		System.out.println("壓縮前:"+b.length);
		//GZIP壓縮
		ByteArrayOutputStream out = new ByteArrayOutputStream();//內存字節緩存輸出流
		GZIPOutputStream gout = new GZIPOutputStream(out);
		gout.write(b);
		gout.close();//壓縮後的數據寫到了ByteArrayOutputStream中了
		
		b = out.toByteArray();//取出壓縮後的數據
		System.out.println("壓縮後:"+b.length);
		//告知客戶端正文的壓縮方式:gzip
		response.setHeader("Content-Encoding", "gzip");
		response.setContentLength(b.length);//響應消息頭,告知客戶端正文的長度
		response.getOutputStream().write(b);	
	}


對字符流、字節流進行處理。

class MyHttpServletResponse  extends HttpServletResponseWrapper{

		private ByteArrayOutputStream baos=new ByteArrayOutputStream();
		private PrintWriter pw = null;
		public MyHttpServletResponse(HttpServletResponse response) {
			super(response);
			
		}
		
		//截獲數據:字符流
		public PrintWriter getWriter() throws IOException {
			pw = new PrintWriter(new OutputStreamWriter(baos, super.getCharacterEncoding()));
			return pw;
		}
		
		//截獲數據:字節流
		public ServletOutputStream getOutputStream() throws IOException {
			return new MyServletOutputStream(baos);
		}
	
		//返回截取的數據
		public byte[] getOldData(){
			try {
				if(pw!=null){
					pw.close();
				}
				baos.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			return baos.toByteArray();
		}
		
	}
	
		class MyServletOutputStream extends ServletOutputStream{

			private ByteArrayOutputStream  baos;
			
			public MyServletOutputStream(ByteArrayOutputStream baos){
				this.baos=baos;
			}
			
			@Override
			public void write(int b) throws IOException {
				baos.write(b);
				
			}
			
		}


固然,咱們一樣要在web.xml中配置。這裏的話咱們不須要所有過濾,只須要過濾jsp、html、js、css類型的便可。

<!-- GZIP壓縮 -->
 <filter>
	 <filter-name>GzipFilter</filter-name>
	  	<filter-class>cn.tf.filterHtml.GzipFilter</filter-class>
	  </filter>
	  <filter-mapping>
	  	<filter-name>GzipFilter</filter-name>
	  	<url-pattern>*.jsp</url-pattern>
	  </filter-mapping>
	  	  <filter-mapping>
	  	<filter-name>GzipFilter</filter-name>
	  	<url-pattern>*.html</url-pattern>
	  </filter-mapping>
	  	  <filter-mapping>
	  	<filter-name>GzipFilter</filter-name>
	  	<url-pattern>*.js</url-pattern>
	  </filter-mapping>
	  	  <filter-mapping>
	  	<filter-name>GzipFilter</filter-name>
	  	<url-pattern>*.css</url-pattern>
	  </filter-mapping>

在servlet中使用:

public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String data="大家好啊fyufbdljsbcjlksdnckdnjkdhjfbjcnjdjkdsnkklqispkxlndkehlfehihiohfdidsisildnckdnilfiefilefkkdhwgflkfnioufhyoinckdnckllhdefwvvewfefrvb54eqgdfbfdbgsfngfnhggfns";
		PrintWriter out = response.getWriter();
		out.write(data);
	}



使用Gzip壓縮咱們須要注意的是,數據量若是過小了的話,壓縮以後會變動大了,數據量至少應該在150個字節以上的再壓縮,不然會拔苗助長。

 

總結:本文主要是經過四個經常使用的案例來講明瞭Filter過濾器的使用,都是一些很是簡單易用的知識。對於一名合格的開發者來講,這些知識都是必需要掌握的。共勉!歡迎關注!

 

 

源碼下載:https://github.com/sdksdk0/FilterDemo

相關文章
相關標籤/搜索