過濾器
為什么需用到過濾器?
項目開發中,經常會涉及到重復代碼的實現!
注冊 ---- Servlet 【1. 設置編碼】 ---- JSP
修改 ---- Servlet 【1. 設置編碼】 --- JSP
其他,
如判斷用戶是否登陸,只有登陸才能有操作權限!
涉及到重復判斷: 獲取session
,取出session
數據,判斷是否為空,為空說明沒有登陸,不能操作; 只有登陸后,才能操作!
過濾器是一個特殊的servlet.
過濾器和Servlet是只會創建一次的,要么是啟動時候創建,要么是訪問的時候創建,以后是直接從緩存中取出。
servlet是在訪問的時候,才創建實例。filter是在啟動的時候,就創建實例。
如何解決:
1.抽取重復代碼,封裝
2.每個用到重復代碼的地方,手動的調用!
過濾器,設計執行流程:
1.用戶訪問服務器
2.過濾器: 對Servlet
請求進行攔截
3.先進入過濾器, 過濾器處理
4.過濾器處理完后, 在放行, 此時,請求到達Servlet/JSP
5.Servlet
處理
6.Servlet
處理完后,再回到過濾器, 最后在由tomcat
服務器相應用戶;
(過濾器就像回家的門!)
過濾器案例
Javax.servlet.*;
|-- interface Filter 及過濾器
開發步驟:
1.寫一個普通java類,實現Filter接口
2.配置過濾器
過濾器執行流程
OOAD
面向對象的分析與設計
使用RationRose
時序圖
過濾器相關Api
|-- interface Filter 過濾器核心接口
Void init(filterConfig);
初始化方法,在服務器啟動時候執行
Void doFilter(request,response,filterChain);
過濾器攔截的業務處理方法
Void destroy();
銷毀過濾器實例時候調用
|-- interface FilterConfig 獲取初始化參數信息
|-- interface FilterChain 過濾器鏈參數;一個個過濾器形成一個執行鏈;
void doFilter(ServletRequest request, ServletResponse response) ; 執行下一個過濾器或放行
/**
* 過濾器,測試
* @author Jie.Yuan
*
*/
public class HelloFilter implements Filter{
// 創建實例
public HelloFilter(){
System.out.println("1. 創建過濾器實例");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("2. 執行過濾器初始化方法");
// 獲取過濾器在web.xml中配置的初始化參數
String encoding = filterConfig.getInitParameter("encoding");
System.out.println(encoding);
// 獲取過濾器在web.xml中配置的初始化參數 的名稱
Enumeration<String> enums = filterConfig.getInitParameterNames();
while (enums.hasMoreElements()){
// 獲取所有參數名稱:encoding、path
String name = enums.nextElement();
// 獲取名稱對應的值
String value = filterConfig.getInitParameter(name);
System.out.println(name + "\t" + value);
}
}
// 過濾器業務處理方法: 在請求到達servlet之前先進入此方法處理公用的業務邏輯操作
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("3. 執行過濾器業務處理方法");
// 放行 (去到Servlet)
// 如果有下一個過濾器,進入下一個過濾器,否則就執行訪問servlet
chain.doFilter(request, response);
System.out.println("5. Servlet處理完成,又回到過濾器");
}
@Override
public void destroy() {
System.out.println("6. 銷毀過濾器實例");
}
}
過濾器配置:
<!-- 過濾器配置 -->
<filter>
<!-- 配置初始化參數 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>path</param-name>
<param-value>c:/...</param-value>
</init-param>
<!-- 內部名稱 -->
<filter-name>hello_filter</filter-name>
<!-- 過濾器類的全名 -->
<filter-class>cn.itcast.a_filter_hello.HelloFilter</filter-class>
</filter>
<filter-mapping>
<!-- filter內部名稱 -->
<filter-name>hello_filter</filter-name>
<!-- 攔截所有資源 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
對指定的請求攔截
/* 表示攔截所有的請求
<filter-mapping>
<filter-name>hello_filter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
默認攔截的類型:(直接訪問或者重定向)
<dispatcher>REQUEST</dispatcher>
攔截轉發:
<dispatcher>FORWARD</dispatcher>
攔截包含的頁面(RequestDispatcher.include(/page.jsp); 對page.jsp也執行攔截)
<dispatcher>INCLUDE</dispatcher>
攔截聲明式異常信息:
<dispatcher>ERROR</dispatcher>
<!-- 配置第二個過濾器 -->
<!-- 演示: 攔截指定的請求 -->
<filter>
<filter-name>hello_filter2</filter-name>
<filter-class>cn.itcast.a_filter_hello.HelloFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>hello_filter2</filter-name>
<!-- 1. 攔截所有
<url-pattern>/*</url-pattern>
-->
<!-- 2. 攔截指定的jsp
<url-pattern>/index.jsp</url-pattern>
<url-pattern>/list.jsp</url-pattern>
-->
<!-- 攔截所有的jsp
<url-pattern>*.jsp</url-pattern>
-->
<!-- 3. 根據servlet的內部名稱攔截
<servlet-name>IndexServlet</servlet-name>
-->
<!-- 攔截指定的servlet
<url-pattern>/index</url-pattern>
-->
<!-- 4. 指定攔截指定的類型 -->
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
共性問題:
1.過濾器:方法參數沒有自動命名,說明沒有關聯源碼
-- 關聯tomcat或servlet源代碼
- 連接池: 多刷新幾次,報錯!
- 連接沒關
QueryRunner qr = new QueryRunner();
qr.update(con,sql);
// 這里con一定要關閉
- 注意:dataSource 確定一個項目創建一次
QueryRunner qr = new QueryRunner(dataSource);
修改連接池參數配置
3 . 編碼
// 設置POST提交的請求的編碼
request.setCharacterEncoding("UTF-8");
// 設置相應體的編碼
response.setCharacterEncoding("UTF-8");
// 設置頁面打開時候時候的編碼格式、 設置相應體的編碼
response.setContentType("text/html;charset=UTF-8");
開發中:
工作區間編碼、項目編碼、request/response、數據庫編碼一致!