java servlet過濾器使用示例
Servlet過濾器簡(jiǎn)介
Servlet過濾器實(shí)際上就是一個(gè)標(biāo)準(zhǔn)的java類,這個(gè)類通過實(shí)現(xiàn)Filter接口獲得過濾器的功能。它在jsp容器啟動(dòng)的時(shí)候通過web.xml配置文件被系統(tǒng)加載。
Servlet過濾器在接收到用戶請(qǐng)求的時(shí)候被調(diào)用,當(dāng)服務(wù)器接收到用戶的請(qǐng)求的時(shí)候,依次調(diào)用配置好的過濾器,完成后將執(zhí)行請(qǐng)求所要求的servlet,而servlet執(zhí)行后的響應(yīng),則先通過配置好的過濾器后再發(fā)送給用戶。
過濾器的用途:
1、用戶認(rèn)證和授權(quán)管理。
2、統(tǒng)計(jì)web應(yīng)用的訪問量和訪問命中率,生成訪問報(bào)告。
3、實(shí)現(xiàn)web應(yīng)用的日志處理功能。
4、實(shí)現(xiàn)數(shù)據(jù)壓縮功能。
5、對(duì)傳輸?shù)臄?shù)據(jù)進(jìn)行加密。
6、實(shí)現(xiàn)xml文件的XSLT的轉(zhuǎn)換。
一個(gè)servlet過濾器其實(shí)是一個(gè)java類,它的實(shí)現(xiàn)需要分為兩個(gè)部分,java類自身以及在web.xml文件中的XML描述。對(duì)于filter接口,該接口由一對(duì)描述的生命周期的方法init(),destroy(),init方法在服務(wù)器初始化過濾器的時(shí)候會(huì)調(diào)用,而destory方法在服務(wù)器關(guān)閉的時(shí)候會(huì)調(diào)用,還有一個(gè)行為方法doFilter方法會(huì)在執(zhí)行過濾操作的時(shí)候調(diào)用.
Servlet過濾器的配置
Servet過濾器需要通過web應(yīng)用程序部署描述符文件web.xml來(lái)部署到應(yīng)用中。配置如下
< filter>
<filter-name>Filtername</filter-name>
<filter-class>com.filter.Filter/class</filter-class>
<init-param>
<param-name>file</param-name>
<param-value>filename</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Filtername</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
下面是示例:
使用過濾器解決中文編碼問題:
由于java的默認(rèn)編碼方式是ISO-8859-1,而通常編寫中文應(yīng)用程序的時(shí)候都是使用GB2312或gbk編碼方式。在這種情況下,應(yīng)在頁(yè)面的首部通過<%@ page contentType="text/html;charset=gbk"%>命令來(lái)指定頁(yè)面的編碼方式。這樣中文頁(yè)面就可以正常地顯示了。但是如果頁(yè)面中村中表單。如一個(gè)input輸入框,如果訪問者在其中輸入中文,又提交到某個(gè)servlet進(jìn)行處理的話,java會(huì)首先按ISO-5589-1的默認(rèn)方式對(duì)這段文本進(jìn)行編碼,然后交給servet處理,處理后的文本將還是以ISO-5589-1編碼方式村中,如果這個(gè)時(shí)候這個(gè)文本返回一個(gè)按GBK編碼來(lái)顯示的頁(yè)面,由于編碼格式的不同,很顯然得不到正確的顯示結(jié)果。
對(duì)于編碼方式的解決方法有很多種,這里主要介紹用過濾器來(lái)解決中文編碼問題:
public class CharacterEncodingFilter implements Filter {
private FilterConfig config;
private String encoding = "ISO8859_1";
public void destroy() {
config = null;
}
public void doFilter(ServletRequest request, ServletResponse response ,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding(encoding);
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
this.config = config;
String s = config.getInitParameter("encoding");
if(s!=null){
encoding = s;
}
}
}
然后在是XML的配置:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
最后是encoding.jsp的編寫?
用戶名:<c:out value="${param.username}" default="none"></c:out><br>
密碼:<c:out value="${param.userpassword}" default="none"></c:out><br>
<form action="MyJsp.jsp" method="post">
用戶名:<input type="test" name="username"> <br>
密碼:<input type="password" name="userpassword"><br>
<input type="submit" value="提交">
</form>
啟動(dòng)tomcat,訪問encoding.jsp,輸入“張山”就可以看到,經(jīng)過過濾器后,頁(yè)面可以正常顯示服務(wù)器傳出的信息。。。
使用過濾器記錄用戶訪問日志
對(duì)于有些項(xiàng)目,它對(duì)于用戶的每次訪問都要有詳細(xì)的記錄。那么這是使用記錄日志是一個(gè)非常好的解決方法,使用過濾器就可以很輕松地對(duì)每次用戶的訪問進(jìn)行記錄。但是由于同一個(gè)訪問者在同一個(gè)時(shí)段訪問站點(diǎn)不同的頁(yè)面時(shí),不能重復(fù)記錄日志,否則日志將會(huì)在很短的時(shí)間內(nèi)塞滿服務(wù)器的硬盤空間。于是這里可以利用session對(duì)象來(lái)判斷用戶的每次會(huì)話,在一次會(huì)話中,過濾器只會(huì)記錄一次。
下面編寫LogFilter類,這個(gè)過濾器主要負(fù)責(zé)記錄用戶的訪問記錄:
package com.filter;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.SimpleDateFormat;
import java.util.Date;
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.HttpSession;
import com.sun.org.apache.bcel.internal.generic.NEW;
public class LoginFilter implements Filter{
private FilterConfig config =null;
private String filename = null;
private String filtername = null;
public void destroy() {
this.config = null;
this.filename = null;
this.filtername = null;
}
public void doFilter(ServletRequest request , ServletResponse response,
FilterChain chain ) throws IOException, ServletException {
HttpServletRequest hRequest = (HttpServletRequest) request;
// 獲取session對(duì)象
HttpSession session = hRequest.getSession();
// 先判斷session中的LOGGED是否有值,如沒有則說(shuō)明是新的請(qǐng)求
if(null==session.getAttribute("LOGGED")){
session.setAttribute("LOGGED", "yes"); // 設(shè)置LOGGED的值為yes,防止同一會(huì)話重復(fù)記錄
File file = new File(this.filename);
if(!file.exists())
file.createNewFile(); // 判斷文件是否存在,如果不存在,就建立一個(gè)新的
/*
* 創(chuàng)建日志記錄內(nèi)容logContent包括訪問者的IP, 訪問的頁(yè)面URL和訪問的時(shí)間以及日志過濾器的名字
*/
String logContent = hRequest.getRemoteHost()+"->"+hRequest.getRequestURI()+" Logged "+getTime()+" By s"+this.filtername+"\r\n";
RandomAccessFile rf = new RandomAccessFile(this.filename,"rw"); // 建立一個(gè)隨機(jī)文件操作對(duì)象
rf.seek(rf.length()); // 將寫入指針指向文件的尾部,rf.length()獲得文件的長(zhǎng)度,seek文件長(zhǎng)度這么長(zhǎng)得距離正好是文件的尾部
rf.writeBytes(logContent); // 將日志寫入到文件中去
rf.close(); // 關(guān)閉文件
}
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
this.config = config;
this.filename = this.config.getInitParameter("file");
this.filtername = this.config.getFilterName();
}
// 獲取時(shí)間
private String getTime(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
return sdf.format(new Date());
}
}
這里利用session來(lái)限制同一個(gè)會(huì)話只會(huì)記錄一次日志,而不管這個(gè)會(huì)話中的訪問者訪問了多少個(gè)頁(yè)面,在第一次訪問的時(shí)候,由于session的LOGGED是空的,所以這個(gè)時(shí)候記錄日志并把LOGGED設(shè)置為yes,這樣第二次判斷的時(shí)候?qū)⒉粫?huì)執(zhí)行記錄日志。
然后在來(lái)配置XML:
<filter>
<filter-name>LogFilter</filter-name>
<filter-class>com.filter.LoginFilter</filter-class>
<init-param>
<param-name>file</param-name>
<param-value>D:/log.txt</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
配置好XML后,訪問跟目錄下地任何文件,都會(huì)可以在D:/log.txt文件中得到訪問者的記錄。
相關(guān)文章
java操作mysql入門代碼實(shí)例(含插入、更新和查詢)
這篇文章主要介紹了java操作mysql代碼實(shí)例,通過執(zhí)行SQL語(yǔ)句實(shí)現(xiàn),需要的朋友可以參考下2014-04-04jsp+servlet實(shí)現(xiàn)文件上傳與下載功能
這篇文章主要為大家詳細(xì)介紹了jsp+servlet實(shí)現(xiàn)文件上傳與下載功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12JSP開發(fā)入門(五)--JSP其他相關(guān)資源
JSP開發(fā)入門(五)--JSP其他相關(guān)資源...2006-10-10java 中Spring task定時(shí)任務(wù)的深入理解
這篇文章主要介紹了java 中Spring task定時(shí)任務(wù)的深入理解的相關(guān)資料,這里提供實(shí)例來(lái)幫助大家理解task定時(shí)任務(wù),希望大家通過本文掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09jsp利用application統(tǒng)計(jì)在線人數(shù)的方法
這篇文章主要介紹了jsp利用application統(tǒng)計(jì)在線人數(shù)的方法,代碼中備有較為詳盡的注釋便于理解,是比較實(shí)用的技巧,需要的朋友可以參考下2015-01-01教你怎么用JSP統(tǒng)計(jì)網(wǎng)站訪問人數(shù)
這篇文章主要介紹了教你怎么用JSP統(tǒng)計(jì)網(wǎng)站訪問人數(shù),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)JSP的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04Jsp+Servlet實(shí)現(xiàn)簡(jiǎn)單登錄注冊(cè)查詢
這篇文章主要介紹了Jsp+Servlet實(shí)現(xiàn)簡(jiǎn)單登錄注冊(cè)查詢,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09