在上一篇blog里,將todo列表實現(xiàn)了不同用戶列表的隔離功能,但是想一想会油,代碼中是否存在著很多不和諧的地方?
不和諧的地方其實很多古毛,但這一章先解決一個最簡單的地方翻翩,注意一下TodoServlet的post方法的第一行:
request.setCharacterEncoding("utf-8");
他的作用在第二章的時候就已經(jīng)介紹過來,是為了解決中文亂碼的問題稻薇,但是嫂冻,難道我們每個頁面,每個servlet的各種方法中都要寫么塞椎?假如有個企業(yè)應(yīng)用桨仿,有100個jsp頁面怎么辦呢?
方法當(dāng)然有案狠,這里可以使用servlet api的過濾器類來實現(xiàn)
Filter
具體實現(xiàn)方式服傍,首先還是先創(chuàng)建包:
com.niufennan.jtodos.filter
然后創(chuàng)建類EncodingFilter
使其集成Filter
接口.
public class EncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
public void destroy() {
}
}
此接口必須實現(xiàn)三個方法,分別為初始化操作骂铁,執(zhí)行期操作吹零,銷毀期操作,因為我們在這個過濾器創(chuàng)建即銷毀時均沒有特殊操作从铲,所以只要完成doFilter方法即可:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}
最后瘪校,為了減少(不使用)xml配置,使用注解來配置過濾器名和過濾路徑:
@WebFilter( filterName = "encodingFilter",urlPatterns="/*")
filterName代表過濾器的唯一性名字,urlPatterns代碼過濾的路徑阱扬,可以使用*作為通配符泣懊,其中/*表示過濾所有路徑。
刪除TodoServlet類的代碼request.setCharacterEncoding("utf-8");
后麻惶,運(yùn)行輸入中文測試無亂碼效果馍刮。
過濾器執(zhí)行生命周期
修改filter類,在三個生命周期方法中輸出字符:
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("filter-init");
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
System.out.println("filter-doFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
public void destroy() {
System.out.println("filter-destroy");
}
啟動測試服務(wù)器窃蹋,并仔細(xì)觀察控制臺卡啰,發(fā)現(xiàn)init的輸出實在Artifact is deployed successfully
的時候,即容器加載這個過濾器完成之后立即進(jìn)行初始化警没。在之后匈辱,根據(jù)你訪問的頁面不同,調(diào)用了若干次的doFilter杀迹,但這時候發(fā)現(xiàn)亡脸,并沒有調(diào)用destory方法。
這時候树酪,停止測試服務(wù)器浅碾,你很快就發(fā)現(xiàn),對destory進(jìn)行了調(diào)用续语,即對過濾器進(jìn)行了銷毀垂谢。
Servlet類的生命周期與過濾器一致。
過濾鏈
這時候疮茄,你也許會問了滥朱,如果多個過濾器怎么辦?這個娃豹,來做個測試吧焚虱,修改這個測試的輸出字符:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
System.out.println("Bef_EncodingFilter");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Aft_EncodingFilter");
}
并新增一個測試,同樣輸出字符懂版,這樣就可以很清晰了:
@WebFilter(filterName = "TestFilter",urlPatterns = "/*")
public class TestFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Bef_TestFilter");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Aft_TestFilter");
}
public void destroy() {
}
}
同時,在Servlet中也增加輸出語句:
System.out.println("TodoServlet");
運(yùn)行后躏率,輸出順序為:
Bef_EncodingFilter
Bef_TestFilter
TodoServlet
Aft_TestFilter
Aft_EncodingFilter
執(zhí)行順序一目了然:
請原諒我的靈魂畫風(fēng)
執(zhí)行順序
那么躯畴,最后一個問題,為什么先執(zhí)行EncodingFilter這個過濾器呢薇芝,難道是因為它比較早創(chuàng)建么蓬抄?
答案當(dāng)然是否定的,修改一下TestFilter這個類的名字:
@WebFilter(filterName = "AestFilter",urlPatterns = "/*")
public class AestFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Bef_TestFilter");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Aft_TestFilter");
}
public void destroy() {
}
}
再次執(zhí)行夯到,查看輸出:
Bef_TestFilter
Bef_EncodingFilter
TodoServlet
Aft_EncodingFilter
Aft_TestFilter
順序就發(fā)生了變化嚷缭,很奇怪Tomcat這個servelt容器使用類名,或者說文件名來決定加載順序,這一點不如通過xml配置的方式阅爽,可以顯式的決定過濾器的加載順序路幸。
最后,別忘了把測試的Filter類刪掉呦付翁。
謝謝觀看