----------------------------------------------------------------------------------------------
[版權申明:本文系做者原創,轉載請註明出處]
文章出處:http://blog.csdn.net/sdksdk0/article/details/52077359
做者:朱培 ID:sdksdk0 郵箱: zhupei@tianfang1314.cn css
--------------------------------------------------------------------------------------------html
本文主要分享的內容是經過使用過濾器解決全站亂碼、Html過濾、髒話過濾、Gzip壓縮過濾等主要內容,是一個切實解決網站實際問題的一套方案。java
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>
咱們之前對於網站亂碼的問題大多數是直接在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>
對於一個網站來講,進行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>
處理前效果:
處理後:
對於髒話過濾在一些論壇網站等都是很是常見的功能,實現這個功能的方法很是多,你能夠直接用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; } }
處理前效果:
處理後效果:
在網站數據傳輸的時候,咱們一般爲了節省流量,加快傳輸速度等緣由,一般須要把文件進行壓縮,不可是用戶請求的頁面,例如當用戶訪問你的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過濾器的使用,都是一些很是簡單易用的知識。對於一名合格的開發者來講,這些知識都是必需要掌握的。共勉!歡迎關注!