JavaWeb三大組件


1.javaweb三大組件:servlet,listener,filter;都需要在web.xml中配置(除了兩個感知監聽器)。

2.服務器端小程序每個Servlet都是唯一的,能處理的請求是不同的(比如登錄,查詢);前面的調度由tomcat完成;要完成獲取請求數據,處理請求,完成響應的任務。

3.實現servlet的三種方法:javax.servlet.Servlet接口,GenericServlet抽象類(service方法待實現),HttpServlet類(常用)。

4.Servlet接口5大方法:其中3個生命周期方法不由我們來調用,由Tomcat調用;對象也不用我們來創建,Tomcat創建。
4.1:init(ServletConfig):生命周期方法,在對象創建之后只執行一次;當第一次被請求才被創建;
4.2:destroy():生命周期方法,在servlet對象被銷毀之前調用,只調用一次;比如IO流等釋放(很少);服務器被關閉時調用;
4.3:service(ServletRequest,ServletResponse):生命周期方法,被調用多次用來處理請求;
4.4:getServletConfig()(有用),getServletInfo()(無用)。

5.瀏覽器如何訪問Servlet:必須把Servlet綁定到一個路徑(web.xml配置):<servlet>name,class</servlet>,<servlet-mapping>name,url-pattern</servlet-mapping>,其中pattern必須/開頭。

6.Servlet單例,線程不安全,效率高。

7.ServletConfig接口:對應的就是web.xml里的本Servlet的配置信息被xml解析器解析后,加載到里面;返回的實例的實現類是Tomcat提供的;
7.1:getServletName()(幾乎沒用);
7.2:getServletContext()(有用);
7.3:getInitParameter[Names()]:初始化參數相關

8.ServletRequest(Tomcat封裝的請求信息),ServletResponse(設置狀態碼,設置響應頭,發送html代碼)。

9.GenericServlet抽象類:集成了很多ServletConfig的方法(實質也是調用ServletConfig的方法);注意init()的妙用(非生命周期方法與生命周期的方法鏈在一起);這個類的源代碼可在Tomcat源碼里看到。

10.HttpServlet類:是抽象類但沒有抽象方法;在http包里,重載了兩個service()方法,一個是生命周期方法,一個參數是HttpServletRequest;生命周期的service()會強制轉換兩個參數類型再調用非生命周期service()方法;非生命周期service()方法會根據request得到請求方式,分別調用doGet()或doPost()方法。如果沒覆蓋着兩個方法且被調用,出現405。

11.Myeclipse可直接右鍵新建Servlet,可自動生成web.xml配置以及自動列出要覆蓋的方法。

12.Servlet細節:
12.1:servlet的線程安全問題:不要創建成員變量,創建局部變量即可;或者創建無狀態成員變量;或者有狀態成員變量但只讀的;
12.2:服務器啟動時即創建servlet,web.xml中配置<load-on-startup>即可(但很少有這種需求);
12.3:servlet-mapping的<url-pattern>可以寫多個或者匹配多個(用*)(以前沒有三大組件,一般Sevlet需要充當過濾器,所以需要多個路徑)。

13.web.xml文件(了解):每個項目都繼承自Tomcat里conf下的web.xml文件:
13.1:DefaultServlet,匹配/,優先級別最低,負責給出404;
13.2:JspServlet,匹配*.jsp,*jspx;
13.3:session-timeout配置,30分鍾;
13.4:mime類型和其真實類型。

14.請求與實現:反射,通過url找名字,找到類名ClassForName,創建對象newInstace,調用方法getMethod;反射總是與配置相出現。

15.域對象:傳遞數據;javaweb四大域對象(作用域從小到大):PageContext,ServletRequest,HttpSession,ServletContext;JSP含有全部,Servlet只含其中3個。
15.1:ServletContext域,即application域,整個web應用都存在,可以在web.xml中配置初始值,接口可以訪問服務器靜態內容文件,線程不安全;
15.2:Httpsession域,即session域,在會話期間都存在,服務器為每個瀏覽器開辟專用內存,把會話號返回瀏覽器的cookie;
15.3:ServletRequest域,在請求存在,數據只使用一次的放在這里,比如servlet產生給jsp顯示的數據;
15.4:PageContext域,即page域,作用在jsp頁面。

16.ServletContext(重要):又名application;一個項目一個,可以在多個servlet之間傳遞數據;與Tomcat共存亡;
16.1:獲得:通過ServletConfig或者GenericServlet類;HttpSession類,ServletContextEvent類;
16.2:內部是一個Map,存屬性,取屬性,移除屬性等;演示在一個Servlet存,另一個Servlet讀;
16.3:可以獲取公共參數<context-param>,之前Servlet獲取的只是為自己所用的局部參數;getInitParameter(String);
16.4:獲取資源的真實路徑(重要):得到有盤符的路徑,getRealPath("/index.jsp");然后可以創建File類對象進行后續操作;
16.5:獲取資源流:把資源以輸入流的方式獲取,getResourceAsStream("/a.txt");
16.6:獲取指定目錄下所有資源路徑:getResourcePaths("/WEB-INF")。不會進入子目錄。

17.ServletContext應用:寫一個Servlet,根據servletContext的特點,統計所有Servlet的訪問量,再利用response對象向瀏覽器輸出response.getWriter().print()。

18.獲取類路徑下的資源:/WEB-INF/classes和/WEB-INF/lib下每個jar包;注意src下的東西會拷貝到classes目錄下;
18.1:相對/classes目錄:this.getClass().getClassLoader();然后getResourceAsStream("a.txt");從流到字符串需要利用commons-io包的工具;
18.2:(復雜,不常用)相對class文件所在目錄:this.getClass().getResourceAsStream("a.txt");/a.txt加了/則是相對於/classes目錄;
18.3:(不會這么用,有ServletContext.getRealPath("/index.jsp"))獲取index.jsp內容:this.getClass().getResourceAsStream("/../../index.jsp")。

19.BaseServlet:希望在一個Servlet寫多個請求處理方法;用戶發出請求給出參數確定調用的方法;自定義處理方法的函數簽名要與service()相同;
19.1:service()中:從req.getParameter()獲取用戶指定的處理方法名;然后if-else判斷執行;
19.2:接上,得到方法名,先獲取當前對象,然后getMethod(方法名,參數類型)得到對象;調用method.invoke(this,req,resp);
19.3:接上,可以將反射的處理放到一個抽象類里然后被不同的Servlet繼承,這樣只需要實現不同的處理方法即可;
19.4:接上,若希望自定義方法處理完后實現轉發或重定向,則在自定義方法返回String,在抽象類service()的invoke后加上判斷邏輯;然后轉發req.getRequestDispatcher(路徑).forward(req,resp);重定向resp.sendRedirect(req.getContextPath()+path)。

-------------------------------------監聽器------------------------------------

1.監聽器:很少用;比如AWT里的ActionListener,XML解析的SAX;都是接口,里面放自定義的代碼;需要注冊;發生特定事件時執行;

2.觀察者:事件源,事件,監聽器(可能有多個方法)。

3.javaWeb中的監聽器:事件源是三大域;每個域都有兩個監聽器:XXXListener(兩個方法,事件是生和死),XXXAttributeListener(三個方法,事件為添加,替換和移除屬性);
3.1:ServletRequest:請求動態資源即創建;
3.2:HttpSession:一個項目可有0或多個session;執行了req.getSession()就會創建;
3.3:ServletContext:服務器啟動創建,服務器關閉銷毀。

4.實現ServletContext生命周期監聽器:
4.1:實現ServletContextListener接口;
4.2:在web.xml注冊<listener>,寫明實現類即可;
4.3:用處:放一些初始化數據庫數據的代碼,關閉的時候刪掉這些臨時數據;IOC這里放完成工廠注入的代碼。

5.上述方法的參數都有事件對象,如:ServletContextEvent對象,只有一個方法getServletContext();HttpSessionEvent對象,getSession()方法;都是匯報事件源用。

6.實現ServletContextAttributeListener屬性監聽器:
6.1:使用eclipse選擇實現該接口,自動在web.xml里注冊;
6.2:添加、修改、移除屬性三個方法都有參數ServletContextAttributeEvent對象,getName(),getValue(),getServletContext()方法。

7.感知監聽器HttpSessionBindingListener:添加到JavaBean上;與HttpSession相關;無需在web.xml中注冊;感知自己是否被session添加或移除;
7.1:比如一個簡單User類,實現了該接口的兩個方法valueBound(HttpSessionBindingEvent)和valueUnbound(HttpSessionBindingEvent);

8.感知監聽器HttpSessionActivationListener:也是添加到JavaBean,還要實現Serializable接口;無需注冊;能感知自己是否隨session被鈍化和活化
8.1:Session的序列化和反序列化:在服務器啟停的時候發生;禁用該功能在Tomcat的conf的context.xml文件添加<Manager pathname=""/>;
8.2:鈍化和活化:太長時間不活躍的session從內存到磁盤;配置參數也是在context.xml(全局生效);活化后文件還存在;
8.3:兩個方法sessionWillPassive(HttpSessionEvent)和sessionDidActivate(HttpSe ssionEvent);監聽8.2的事件;
8.4:這個監聽器基本沒啥用。

----------------------------------過濾器---------------------------------

1.在一組資源(jsp,servlet,css,html等)前面執行;可以讓請求獲得資源,也可以不獲得;攔截一組請求。

2.實現:實現Filter接口,在web.xml配置;單例的;
2.1:方法init(FilterConfig):服務器啟動就創建,創建之后馬上執行,初始化工作;
2.2:方法doFilter(ServletRequest,ServletResponse,FilterChain):
2.3:destroy():服務器關閉,非內存資源的釋放,一般用不上;
2.4:配置:與servlet相同;一般<url-pattern>都含有*,;也可用<servlet-name>指定一個或多個具體的servlet。

3.相關類:
3.1:FilterConfig:與ServletConfig類似,獲取過濾器名字,獲取初始化參數和名字,獲取ServletContext;
3.2:FilterChain:方法doFilter(ServletRequest,ServletResponse);放行。

4.多過濾器:FilterChain的doFilter()方法,表示執行目標資源或執行下一過濾器(如有)。

5.四種攔截方式:請求REQUEST;轉發FORWARD;包含INCLUDE;錯誤ERROR;
5.1:配置:在<filter-mapping>里寫<dispatcher>,指明上面四種之一,默認是請求;
5.2:錯誤是去往web.xml里配置的<error-page>的時候被攔截。

6.<filter-mapping>的放置順序就是多個過濾器的執行順序。

7.應用場景:考慮把多個Servlet都要執行的代碼,放到Filter中;
7.1:預處理:設置編碼req.setCharacterEncoding(),一般都放行;
7.2:條件判斷:用戶是否登錄,IP是否禁用的判斷;
7.3:后續處理:在目標資源執行后的處理,比如輸出數據的處理,如動態頁面靜態化。

8.案例1:分IP統計網站的訪問次數;
8.1:統計所有資源的訪問,放在fliter;不做攔截;
8.2:統計數據放哪里?Filter要用,頁面顯示要用;整個項目就用同一個;ServletContext;
8.3:ServletContext的初始化在哪里?用監聽器;在里面放一個統計ip的map;
8.4:材料:靜態資源,filter,listener。

9.案例2:粗粒度權限控制;
9.1:細粒度控制,RBAC基於角色的權限控制;用戶表,角色表,權限表,以及用戶與角色對應的表,角色與權限對應的表;
9.2:判斷有沒有登錄,總要使用到session;注意HttpServletRequest才能得到session,filter里只是ServletRequest;
9.3:只區分游客,會員和管理員:公共資源給所有人訪問,會員資源放一個文件夾一個filter控制,管理員資源放一個文件夾被另一個filter控制;
9.4:材料:index.jsp,登錄頁面,會員資源,管理員資源;會員filter,管理員filter,登錄校驗Servlet(判斷,在session放信息,回到index)。

10.案例3:解決全站字符亂碼,所有資源的POST和GET訪問都要解決;
10.1:POST亂碼的處理(setCharacterEncoding()),GET亂碼的處理(getParameter(),new String()),和響應內容亂碼的處理;
10.2:這些公共處理代碼放filter;但難點在於GET的處理:a.不知道Servlet獲取的參數名字;b.設置完了不知道怎么回傳給對應的Servlet;
10.3:解決GET:掉包request,寫裝飾類,增強getParameter(String);
10.3.1:實現HttpServletRequest接口,實現其所有方法;利用構造方法傳入一個HttpServletRequest類型保存,然后利用其實現其他方法;
10.3.2:增強方法的寫法和之前一樣;
10.3.3:chain.doFilter()傳入自己增強的req即可;
10.3.4:實現接口麻煩,繼承HttpServletRequestWrapper類,只需寫getParameter(String)即可。

11.案例4:頁面靜態化;網站有一些內容是不變的不需要查數據庫,比如書籍的類別;首次查詢查數據庫,保存到html,二次查詢直接顯示;
11.1:材料:link.jsp(查詢所有,查詢SE分類,查詢EE分類...的鏈接);顯示頁面;BookService/Servlet;BookDao;Book實體;
11.2:步驟:創建數據庫表;導入jar包;創建jsp;
11.3:BookServlet:繼承BaseServlet,從req獲得參數,調用Dao實現findAll(),findByCategory(),把結果req.setAttribute(),跳轉到show.jsp;
11.4:BookDao:寫sql語句並查詢,返回List<Book>;
11.5:填充jsp,c3p0的xml文件配置數據庫連接信息;
11.6:實現一個filter,把首次訪問servlet的輸出保存到html,再重定向到html;二次訪問直接重定向,filter不再放行訪問Servlet(判斷);
11.7:准備一個文件夾放中間html;servletContext.getRealPath()得到的是帶盤符的路徑;req.getContextPath()得到的是項目名稱;
11.8:輸出頁面是response的out,掉包,換getWriter(傳html路徑)流與html文件綁定而不是瀏覽器,繼承HttpServletResponseWrapper,這樣show.jsp在使用out的時候以為在寫瀏覽器,其實寫到中間文件;最后重定向到自己的中間文件;解決亂碼也在show.jsp設置編碼即可。

12.案例3和案例4都是利用filter的攔截特性,在chain.doFilter(req,resp)做手腳,傳入自己改良的req對象或resp對象(裝飾類)實現自己的功能。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM