一: 過濾器: 可以把”不和諧”的東西給過濾掉
01.過濾器概述
生活中的過濾器:帶有過濾功能的淨水器,濾紙,香菸的過濾嘴,測試,丈母孃.
程序中的過濾器:在JAVA中最小的程序單元是類,程序中的過濾器就是一個特殊的類
Servelt/Filter是Web的一個組件.
Web中過濾器的作用(簡單理解爲:過濾器處在客戶端和服務端資源之間):
過濾器可以對所有的請求或者響應做攔截操作.
1:以常規的方式調用資源(Servelt/JSP);
2:利用修改過的請求信息調用資源;
3:調用資源之後,但在響應到客戶端之前,對響應做出修改;
4:阻止當前資源調用,代之轉帶其他資源.
02.過濾器的應用
過濾器在開發中的應用:
1):可以對請求中的字符做編碼.
2):登錄驗證過濾器.
3):敏感字(非法文字)過濾.
4):做MVC框架中的前端控制器(處理所有請求共同操作,再分發)
在開發中兩個常用的思想:
1):DRY原則: Don't Repeat Yourself.
開發中拒絕代碼重複,(重複會帶來巨大的維護成本)
2):責任分離原則:各自做各自最擅長的事情.
03:開發和使用Filter
Servlet開發:
1:自定義一個類(XxxServlet),實現於javax.servlet.Servlet接口.
2:實現Servelt接口中的方法(init(初始化方法),service(處理請求))
3:告訴Tomcat來幫我們管理該Servlet程序(1:使用web.xml做配置,2:WebServlet("/資源名")).
<servlet>
<servlet-name>Servlet的別名</servlet-name>
<servlet-class>自定義Servelt的全限定名</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet的別名</servlet-name>
<url-pattern>/資源名</url-pattern>
</servlet-mapping>
注意:此時的url-pattern的文本內容是外界訪問Servelt的資源名稱.
Filter開發:
1:自定義一個類(XxxFilter),實現於javax.servlet.Filter接口.
2:實現Filter接口中的方法(init(初始化方法),doFilter(處理請求))
3:告訴Tomcat來幫我們管理該Filter程序(1:使用web.xml做配置,2:WebFilter("/資源名")).
<filter>
<filter-name>Filter的別名</filter-name>
<filter-class>自定義Filter的全限定名</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter的別名</filter-name>
<url-pattern>/資源名</url-pattern>
</filter-mapping>
注意:此時的url-pattern的文本內容是Filter對哪一些資源做過濾操作.
如: /hello.jsp :說明當前Filter只會對/hello.jsp做攔截/過濾.
/employee :說明當前Filter只會對/enployee資源做過濾.
/system/* :說明當前Filter只會對以/system/作爲前綴的資源路徑做攔截.
filterChain(過濾器鏈):多個過濾器按照一定的順序,排列起來.
攔截器棧:
--------------------------------------------------------
程序中存在多個過濾器的時候,過濾器的先後執行順序由誰來決定.
在WEB.xml中:配置的<fiter-mapping>的先後順序來決定.
![過濾器的的先後執行順序示意圖](https://img-blog.csdn.net/20180310104230663?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzQwMTYxNzA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
04.Filter的細節
過濾器的映射細節:
1):filter中的url-pattern的文本內容是Filter對哪一些資源做過濾操作.
如: /hello.jsp :說明當前Filter只會對/hello.jsp做攔截/過濾.
/employee :說明當前Filter只會對/enployee資源做過濾.
/system/* :說明當前Filter只會對以/system/作爲前綴的資源路徑做攔截.
/* :說明對所有的資源做過濾.
/*.do :對所有以 .do 結尾的資源做攔截
2):Filter的dispatcher(表示對哪些動作作過濾).
<filter-mapping>
<filter-name>FilterDemo1</filter-name>
<url-pattern>/*</url-pattern>
<url-pattern>/x1</url-pattern>
<!-- 只對請求做攔截(默認) -->
<dispatcher>REQUEST</dispatcher>
<!-- 增加對請求轉發做攔截 -->
<dispatcher>FORWARD</dispatcher>
<!-- 增加請求包含做攔截 -->
<dispatcher>INCLUDE</dispatcher>
<!-- 增加跳轉到錯誤頁面做攔截 -->
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
05.請求編碼過濾器CharacterEncodingFilter
Servelt只管 1:獲取 2:調用 3:跳轉 就行,設置編碼交給Filter就行, DRY原則 跟 責任分離原則!
//字符編碼過濾器
public class CharacterEncodingFilter implements Filter{
private String encoding;
private Boolean forceEncoding = false;
public void init(FilterConfig config) throws ServletException {
this.encoding = config.getInitParameter("encoding");
forceEncoding = Boolean.valueOf(config.getInitParameter("force"));
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//類型
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
//設置編碼
//1:應用中沒有編碼,並且我自己設置了編碼.
//2:應用中已經存在編碼了但是依然要使用我自己設置的編碼:強制使用
if(haslength(encoding) && (req.getCharacterEncoding() == null || forceEncoding)){
req.setCharacterEncoding(encoding);
}
chain.doFilter(req, resp);
}
public void destroy() {
}
private boolean haslength(String str){
return str!=null && !"".equals(str.trim());
}
}
XML配置文件
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com._520it._02_characterencoding.CharacterEncodingFilter</filter-class>
<!-- 設置編碼 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 是否強制使用該編碼 -->
<init-param>
<param-name>force</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
06.登陸檢查過濾器
![登錄檢查的流程圖](http://img.blog.csdn.net/20180310170822918?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzQwMTYxNzA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
檢查登錄過濾器
//登錄檢查過濾器
public class CheckLoginFilter implements Filter{
private String[] unCheckUris = {"/login.jsp","/login"};
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
Object user = req.getSession().getAttribute("USER_IN_SESSION");
//當前正在過濾的資源
String requestURI = req.getRequestURI();
if(!Arrays.asList(unCheckUris).contains(requestURI)){
if(user == null){//沒有登錄
resp.sendRedirect("login.jsp");
return ;
}
}
chain.doFilter(req, resp);
}
public void destroy() {
}
}
從登錄界面跳轉到的Servlet中
@WebServlet("/login")
public class LoginServelt extends HttpServlet{
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
//把登錄信息存儲到session中
req.getSession().setAttribute("USER_IN_SESSION",username);
resp.sendRedirect("/welcome.jsp");
}
}
login.jsp登錄界面
<form action="/login" method="post">
賬號:<input type="text" name="username" required/><br/>
密碼:<input type="text" name="password"/><br/>
<input type="submit" value="登錄"/>
</form>
welcom.jsp
${sessionScope.USER_IN_SESSION}
<hr/>
<a href="function1.jsp">功能1</a><br/>
<a href="function2.jsp">功能2</a><br/>
<a href="function3.jsp">功能3</a><br/>
Filter的配置文件
<filter>
<filter-name>CheckLoginFilter</filter-name>
<filter-class>com._520it.checklogin.CheckLoginFilter</filter-class>
<init-param>
<param-name>unCheckUris</param-name>
<!-- 以後這樣做 對需要檢查的放到/system/中來 -->
<param-value>/system/*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CheckLoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
07.敏感字過濾
利用裝飾設計模式,給Request.getParameter賦予敏感字過濾功能
![流程示意圖](http://img.blog.csdn.net/20180310212548133?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzQwMTYxNzA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
給Filter中的request賦予過濾字符的功能
public class MessageRequestWapper extends HttpServletRequestWrapper{
public MessageRequestWapper(HttpServletRequest request) {
super(request);
}
//覆蓋getParameter方法,使之支持敏感字過濾
public String getParameter(String name){
//如果參數名爲title或content
if("title".equals(name) || "content".equals(name)){
//返回過濾之後的title和content
FilterUtil.filter(super.getParameter(name)); //FilterUtils就是過濾的代碼,現在先知道就行
}
return super.getParameter(name);
}
}
過濾器(filter)使用
@WebFilter("/*")
public class MessageFilter implements Filter{
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//把不具有處理敏感字的請求對象換成可以處理敏感字的請求對象.
HttpServletRequest req = (HttpServletRequest) request;
HttpServletRequest requestWapper = new MessageRequestWapper(req);
//放行
chain.doFilter(requestWapper, response);
}
public void destroy() {
}
}
二: Listener(監聽器)
Web的另一大組件:Listener(監聽器).
Web中的監聽器,主要用於監聽作用域對象的創建,監聽作用域對象屬性的添加/刪除/替換:
1):監聽作用域對象的創建和銷燬.
ServletRequestListener:監聽請求對象的創建和銷燬.
HttpSessionListener:監聽會話對象(session) 的創建和銷燬
ServletContextListener:監聽應用的創建和銷燬.
2):監聽作用域對象的屬性的添加/刪除/替換.
ServletRequestAttributeListener: 監聽request作用域中屬性的添加/刪除/替換.
HttpSessionAttributeListener: 監聽session作用域中屬性的添加/刪除/替換.
ServletContextAttributeListener: 監聽application作用域中屬性的添加/刪除/替換.
Web中的監聽器組件,沒有初始化參數配置如果要解決監聽器中的硬編碼,只能使用全局的初始化參數.
//監聽系統(應用)的啓動和銷燬
public class ContextLoaderListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent sce) {
System.out.println("Web系統啓動了.....");
}
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("Web系統銷燬了.....");
}
}
@WebListener
public class HttpSessionListenerDemo implements HttpSessionListener{
public void sessionCreated(HttpSessionEvent se) {
System.out.println("會話開始了");
}
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("會話結束了");
}
}
@WebListener
public class HttpSessionAttributeListenerDemo implements HttpSessionAttributeListener{
public void attributeAdded(HttpSessionBindingEvent se) {
System.out.println("屬性添加"+se.getName()+","+se.getValue());
}
public void attributeRemoved(HttpSessionBindingEvent se) {
System.out.println("屬性刪除"+se.getName()+","+se.getValue());
}
public void attributeReplaced(HttpSessionBindingEvent se) {
System.out.println("屬性替換"+se.getName()+","+se.getValue()+","+se.getSession().getAttribute(se.getName()));
}
}
預習,精通Struts2的hello開發: