servlet總結

Servlet
C/S--->
Client/Server(客戶機/服務器)

優點:
1)運行效率較高
2)交互性強適合局域網,
缺點:升級維護困難
B/S-->
Browser/Server(瀏覽器/服務器)

 

優點:無需關心客戶端,升級維護,只需操作服務器即可.比較方便.
缺點:
1)交互性是請求/響應式,需要通過網絡進行交互,效率相對c/s架構的軟件來說較低.
2)要開發交互性較強的界面比較困難.

 

CGI:最早開發b/s架構的一門技術
從CGI分出 1)微軟的ASP--->ASP.NET
2)JAVA的Servlet--->jsp

 

開發技術:
靜態網頁技術:
HTML,JS,CSS
動態網頁技術:(動態說的是數據動態)
CGI,ASP,ASP.net,servlet,php,jsp等
url:
http://192.168.1.250:8888/poll/login.jsp
協議://地址(ip-->域名):端口(如果是80,可以省略)/web應用名/資源名
web服務器: (微軟的)IIS:
(apache的)tomcat(開源的):等..

servlet:
1)屬於j2ee的其中一個技術,是一個規範
2)servlet是一個web組件(包含servlet類和他的描述信息) 組件如java bean 可複用的
3)servlet運行的時候就是一個java對象(創建.調用.管理由web服務器(web容器)完成).web容器是web服務器的線程 tomcat的web容器是CATALINA

 

web 容器調用servlet對象的方法
首先由web容器創建兩個對象:
1.HttpServletRequest:
包含了客戶端提交的所以信息,在servlet中 ,可以通過這個對象獲得客戶端傳遞過來的數據.
2.HttpServletResponse:
通過這個對象可以向客戶端返回數據
public void service(ServletRequest req,ServletResponse res){

}

 

web應用的目錄結構:
應用名:(web應用的根目錄的名字)
WEB-INF(必須):瀏覽器不能直接訪問
classes(存放.class文件)
lib(存放第三方的.jar文件)
web.xml(描述servlet,包括類名和訪問標識)
html/first.html
js/my.js
css/my.css
jsp/first.jsp
META-INF
tomcat服務器的目錄結構:
bin:存放一些可執行文件:比如startup.sh,shutdown.sh
common:存放tomcat服務器和所以web應用都可以使用的類和jar包
conf:存放tomcat服務器使用的一些配置文件.比如 service.xml中可改端口號
logs:存放tomcat服務器和web應用輸出的日誌信息的文件
server:存放一些只能由tomcat服務器使用的類和jar包,以及tomcat自帶的web應用
shared:存放一些只能由web應用使用的類和jar包
temp:存放一些臨時文件
*webapps:用來部署web應用
work:存放jsp文件被翻譯和編譯以後的.java和.class文件.

2)初始化階段
調用者:web容器

public void init(ServletConfig config){}

在GenericServlet中已經對有參的init方法作了實現
public abstract class GenericServlet implement Servlet{
private ServletConfig config;
public void init(ServletConfig config){
this.config=config;
this.init();
}  
public void init(){

}
} 

 

3)服務階段
調用者:web容器
public void service(ServletRequest req,ServletResponse res){

}
在HttpServlet中已經對service方法作了實現

public abstract class HttpServlet extends GenericServlet{
public void service(ServletRequest req,ServletResponse res){
HttpServletRequest hReq=(HttpServletRequest)req;
HttpServletResponse hRes=(HttpServletResponse)res;  
service(hReq,hRes);
}
public void service(HttpServletRequest hReq, HttpServletResponse hRes){
String method=hReq.getMethod();

if(method.equals("GET")){
doGet(hReq,hRes);
}else if(method.equals("POST")){
doPost(hReq,hRes);
}
} 

4)銷燬階段
調用者:web容器
public void destory{

}

注:init(),service(),destroy()稱爲servlet對象的生命週期回掉方法.

web應用的邏輯分層:
model(模型):
javabean,ejb..
view(顯示):
servlet,jsp等
control(控制):
servlet,jsp....

請求的轉發:
1)服務器內部跳轉
請求轉發器:RequestDispather
創建:
1.調用request對象的方法
指定的轉發路徑可以相對也可以是絕對的
相對路徑:根據當前servlet的路徑和轉發的路徑進行計算
絕對路徑:就是轉發的servlet的url-pattern
2.調用servletContext對象的方法
指定的路徑必須是絕對路徑

forward:
在轉發請求之前首先調用response對象的resetBuffer方法,清空緩存.
include(包含):
將請求轉發到其他servlet之前不會清空緩存

2)服務器外部重定向
RedirectServlet
通過服務器外部重頂向進行請求的轉發 裏面的路徑可以相對可以絕對
絕對路徑寫法: 應用根路徑+servlet的url-pattern
例:response.sendRedirect(request.getContextPath()+"/resource/view");
相對路徑寫法:例:response.sendRedirect("view");

服務器內部跳轉和服務器外部重定向的比較
1)服務器內部跳轉所有的servlet共享同一個請求,而服務器外部重定向,每個Servlet接受的請求都不相同
2)服務器內部跳轉是在服務器實現的,而服務器外部重定向是由瀏覽器實現的
3)服務器內部跳轉是通過request對象來完成的,而服務器外部重定向是通過response對象來完成的.

作業:

1.findUser.html
2.FindUserServlet:
1.負責接收客戶端查找用戶的請求
2.調用UserMange的findUser(String name)
3.將找到的User對象交給ViewUserServlet顯示
ViewUserServlet
1.首先判段有沒有需要顯示的user,如果沒有 提示
2.如果有,則將用戶的詳細信息進行顯示

3.在UserManager中提供查詢用戶的方法.


Context ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup(jndiName);

通過jndi從目錄服務器上查找DataSource對象
DataSource( 連接池);
06 02 2008 JNDI:java name directory interface
創建DataSource對象
1.通過new 的方式創建.

2.通過web服務器提供的配置的方式,來創建DataSource(這種方式創建的DataSource已經存放在目錄服務器上).
1)將oracle的驅動包放入到tomcat的common/lib目錄下
2)JNDI Name:jdbc/ds
數據庫的URL Data Source
URL:jdbc:oracle:thin:@192.168.1.220:1521:briupdb
數據庫驅動名:JDBC Driver Class:oracle.jdbc.driver.OracleDriver
數據庫用戶名:User Name:jd0804
數據庫用戶密碼:Password:jd0804
最大活動的連接數:Max. Active Connections:
Max. Idle Connections:(當連接池沒有連接的時候,再創建的連接數)

 

<filter-mapping>                
         <filter-name>Logger</filter-name>
         <url-pattern>/*</url-pattern> //將過濾器應用於Web應用中的每個Web資源;可以只指定某個資源
     </filter-mapping>

使用DataSource
1.如果是通過new的方式創建的DataSource,可以直接調用他的getConnection方法來獲得連接
2.通過jndi訪問目錄服務器,查找DataSource,調用方法獲得連接.

ch05 狀態持久。
爲什麼需要狀態持久?
因爲http協議是無狀態的,客戶端發起一個請求的時候,會跟服務器建立socket連接,一旦響應,就會關閉socket連接,所以爲了讓服務器端知道某個客戶端的狀態信息,我們需要將狀態進行持久化

cookie
創建:       name        value

Cookie cookie = new Cookie("isLogin", "true");
cookie.setMaxAge(time);
response.addCookie(cookie);
當time<0,表示cookie保存在瀏覽器進程中,一旦瀏覽器進程結束,cookie就消失
當time=0,表示刪除客戶端同名的cookie
當time>0,表示cookie將在瀏覽器端保存起來,超過time後纔會消失

獲取:
Cookie[] cookies=request.getCookies();

session(結合cookie使用):創建和保存都在服務器端

由web服務器維護
HttpSession session = request.getSession();
或者
HttpSession session = request.getSession(boolean create);
當create==true時,這個方法的作用跟無參的getSession()方法作用一樣
當create==false時,這個方法的作用是:根據客戶端傳遞過來的session的id,尋找服務器端的session,如果找到返回,如果沒有找到,返回null;

String ID=session.getId();
session.setAttribute("isLogin", true);
當對客戶端作出響應的時候,會將session的ID包裝成一個cookie對象(名字爲JSESSIONID,值爲session的id),返回給客戶端

HttpSession消失的情況:
1)web應用停止
2)超時(上一次訪問開始的時間到當前時間,如果這個時間超過了指定的超時時間,那麼就認爲是超時了)
可在web.xml中可配置session的超時時間:

3)調用session對象的invalidate方法

通過URL重寫解決cookie禁用sesion不能訪問的問題:
當客戶端禁用cookie之後,無法通過cookie保存session的id我們可以通過URL重寫來保存session的id
url;jsessionid=HJGKJWBDRUWRGW
String oldUrl = "sessionCheck";
String newUrl = response.encodeURL(oldUrl);// encodeUrl已不建議使用

三個範圍(scope)
requestScope(ServletRequest):在多個servlet之間進行服務器內部跳轉的時候,我們可以通過將數據放在request對象中進行數據的傳遞。
request.setAttribute(key,value);
Object value=request.getAttribute(key);
request.removeAttribute(key);

sessionScope(HttpSession):session中一般存放一些狀態信息,或者在整個會話中經常要使用的數據(不建議存放過多數據(影響服務器效率))
session.setAttribute(key,value);
Object value=session.getAttribute(key);
session.removeAttribute(key);

applicationScope(ServletContext):ServletContext一般存放整個系統運行過程中,經常要使用的數據
ctx.setAttribute(key,value);
Object value=ctx.getAttribute(key);
ctx.removeAttribute(key);

web應用的事件的處理機制
1.事件源
web容器

2.事件對象:由web容器創建
在web應用啓動和停止的時候產生:ServletContextEvent 在javax.servlet 包中
會話開始和結束的時候產生:HttpSessionEvent 在javax.servlet.http 包中
請求開始和結束的時候:ServletRequestEvent
對application範圍中的數據操作的時候產生:ServletContextAttributeEvent
對session範圍內的數據進行操作的時候產生: HttpSessionBindingEvent
對requset範圍中的數據操作進行操作的時候產生: ServletRequestAttributeEvent

3.監聽器

處理ServletContextEvent事件對應ServletContextListener 接口(執行時間:web應用啓動和停止)
處理HttpSessionEvent事件 HttpSessionListener 執行時間:session(會話)開始和結束
處理ServletRequestEvent 事件 ServletRequestListener 執行時間:請求的開始和結束
處理ServletContextAttributeEvent 事件 ServletContextAttributeListener
執行時間:加入數據,刪除數據,替換數據
HttpSessionBindingEvent HttpSessionAttributeListener 執行時間:加入數據,刪除數據,替換數據

ServletRequestAttributeEvent ServletRequestAttributeListener
執行時間:加入數據,刪除數據,替換數據

註冊監聽器:在web.xml中描述就可以完成監聽器的工作.

過濾器:Filter

一、 過濾器 Filter
1. why Filter?
   針對通用WEB服務、功能,透明的處理

2. 什麼是 Servlet Filter?
     過濾是 Servlet 2.3 版才引入的新特性。過濾器可以認爲是實現 Http 請求、響應以及頭信息等內容的傳送的代碼片斷。
     過濾器並不能創建響應,但它可以“過濾”傳給 servlet 的請求,還可以“過濾”從 servlet發送到客戶端的響應;

它不僅能處理靜態內容,還可以處理動態內容。換而言之,filter 其實是一個“servlet chaining”(servlet 鏈)。
   一個 filter 包括:
    1) 在 servlet 被調用之前截獲;
    2) 在 servlet 被調用之前檢查 servlet request;
    3) 根據需要修改 request 頭和 request 數據;
    4) 根據需要修改 response 頭和 response 數據;
    5) 在 servlet 被調用之後截獲

3. 過濾器的生命週期
   Filter 組件的生命週期與 Servlet 的類似。
   過濾器有四個階段(與servlet類似):
    1) 實例化;
    2) 初始化(調用init()方法);
    3) 過濾(調用doFilter()方法);
    4) 銷燬(調用destroy()方法);

4. Filter編程
   1)定義Filter(implements Filter)
   2)配置Filter
     配置對哪些資源進行過濾(url)

<filter>
        <filter-name>Logger</filter-name>                   //過濾器名
        <filter-class>com.LoggerFilter</filter-class>       //具體過濾器類
        <init-param>                                        //初始化參數
           <param-name>xsltfile</param-name>
           <param-value>/xsl/stockquotes.xsl</param-value>
        </init-param>
     </filter>

 

5. FilterChain
   1) chain是如何配置,順序
      當同一個應用中配置了多個 filter 時,其執行順序是如何的呢?
      答:按 web.xml 中<filter-mapping>的順序來執行的
   2) chain.doFilter(req, resp)
      調用下一個Filter,到最後一個Filter則正式調用 TargetServlet
   3) 調用過程(類似於遞歸調用)

6. Filter的類型
   Filter 有4種類型,主要體現在<filter-mapping>中的<dispatcher>屬性:
   <dispatcher>REQUEST</dispatcher>       默認,客戶端的直接的請求,才觸發該過濾器
   <dispatcher>FORWARD</dispatcher>       servlet 調用 rd.forward(req,resp)時觸發
   <dispatcher>INCLUDE</dispatcher>       servlet 調用 rd.include(req,resp)時觸發
   <dispatcher>ERROR</dispatcher>         發生錯誤,跳轉到錯誤頁面時觸發

 

 c.監聽 servlet request
      1)生命週期
        接口: javax.servlet.ServletRequestListener
        內容: 一個 servlet 請求開始由 web 組件處理
      2)屬性改變
        接口: javax.servlet.ServletRequestAttributeListener
        內容: 在 ServletRequest 中,增加、刪除或者替換屬性

二、監聽器 Listener
    Listener 是 Servlet 的監聽器,它可以監聽客戶端的請求、服務端的操作等。通過監聽器,可以自動激發一些操作。
    如:監聽在線的用戶數量。當增加一個session時,就激發sessionCreated(HttpSessionEvent se),給在線人數加1

1. 監聽器的種類
   一共分三大類型,有 8 種 listener:
    a.監聽 servlet context
      1)生命週期事件
        接口: javax.servlet.ServletContextListener
        內容: servlet 上下文已經被創建,並且可以用來向其第一個請求提供服務,或者 servlet 上下文即將關閉
      2)屬性的改變
        接口: javax.servlet.ServletContextAttributeListener
        內容: 在 servlet 上下文中,增加、刪除或者替換屬性

 b.監聽 servlet session
      1)生命週期事件
        接口: javax.servlet.http.HttpSessionListener
        內容: 對一個 HttpSession 對象進行創建、失效處理或者超時處理
      2)屬性改變
        接口: javax.servlet.http.HttpSessionAttributeListener
        內容: 在 servlet 會話中,增加、刪除或者替換屬性
      3)會話遷移
        接口: javax.servlet.http.HttpSessionActivationListener
        內容: HttpSession 被激活或者鈍化
      4)對象綁定
        接口: javax.servlet.http.HttpSessionBindingListener
        內容: 對 HttpSession 中的對象進行綁定或者解除綁定

 

Servlet環境配置
JAVA_HOME=/XXX/XXX/(JDK路徑,bin的上一層目錄)
CATALINA_HOME=/XXXX/XXX(tomcat的絕對路徑 windows中 X:\xxx\xxx)

Tomcat使用
在啓動Tomcat時,是運行Tomcat的bin目錄下的startup.sh(windows中使用startup.bat)
Linux中要顯示後臺的具體信息,則用catalina.sh run 代替startup.sh命令。
判斷Tomcat是否啓動成功,可以在瀏覽器的地址欄中使用
http://localhost:8080/http://127.0.0.1:8080/ 可以訪問到tomcat的主頁就表示啓動成功。
要想停止tomcat服務器,可使用shutdown.sh(windows中使用shutdown.bat),如果直接關閉啓動窗口,就會造成8080端口占用錯誤,這時可以再使用shutdown.sh關閉一下服務器。

 

 Servlet開發步驟
編寫servlet源代碼,注意servlet的結構。
編譯servlet,需要servlet-api.jar文件(位於$Tomcat\common\lib\目錄下;加入classpath環境變量中)
部署servlet
   編寫配置文件web.xml:其中包括servlet burl與 servlet name的映射,
   以及servlet name 與 servlet class name的映射。
構造web應用程序目錄結構如下:
└─MyWebApp           應用程序名
   └─WEB-INF
       └─classes
       └─lib
   └─*.html/*.jsp
配置文件web.xml放在WEB-INF目錄下
servlet類文件放在classes目錄下
將整個應用程序目錄拷貝到 $Tomcat\webapps\ 目錄下


使用此結構的優點
一個Web容器中可以共存多個Web應用程序。
Web容器知道該到何處尋找裝入Web應用程序所需的類。

web.xml文件的寫法
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="
http://java.sun.com/xml/ns/j2ee"
   xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation=http://java.sun.com/xml/ns/j2ee
  
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd version="2.4">
<servlet>
<servlet-name>IpLogServlet</servlet-name>
<servlet-class>tarena.servlet.lc.IpLogServlet</servlet-class>
   <init-param>
<param-name>filename</param-name>        //getServletConfig().getInitParameter();
<param-value>c:/iplog.txt</param-value>
   </init-param>
   <load-on-startup>2</ load-on-startup > //啓動服務器時就創建該servlet實例,必須是正數,小的數先加載
</servlet>
<servlet-mapping>
<servlet-name>IpLogServlet</servlet-name> //要和servlet標籤中的相同
<url-pattern>/lc/iplog</url-pattern> //指定servlet相對於應用目錄的虛擬路徑
</servlet-mapping>                       /xxx/xxx(絕對路徑),xxx(相對路徑)
</web-app>

絕對路徑開頭的“/”代表 http://localhost:8080/

             測試應用
在tomcat服務器中,訪問應用下的資源可以在端口號後加上web應用文件夾的名字,就可以看到資源
http://localhost:8080/應用文件夾名/url-pattern
靜態頁面只能放在web應用的文件夾下,不能夠放在WEB-INF文件夾下,WEB-INF文件夾中的資源是受保護的,不能夠通過網絡訪問到。

Servlet的調用過程
用戶通過瀏覽器向web服務器發送請求
http://serverip:port/appname
服務器爲用戶定位資源
   靜態資源:/a.html /a/b.html (這裏的路徑是針對web應用文件夾目錄)讀文件並把內容發送到客戶端。
   動態資源:解析web.xml定位Servlet類的名字。
裝載類(WEB-INF/classes | WEB-INF/lib/*.jar)
創建該對象的實例
Servlet ser=(Servlet)(Class.forName("servle的類名")).newInstance();
//我們寫的Servlet一定要實現Servlet接口或者繼承實現了Servlet接口的類
ser.service(request,response);

用Servlet處理表單數據
FORM元素的屬性
action: 用來指定要處理FORM數據的Servlet的URL
method: 指定數據傳送給HTTP服務器的方法
解析請求
getParameterNames:可以獲得一個迭代器Enumeration,通過這個迭代器,來獲得form表單中參數的名字。
getParameter: 返回表單中參數名(區分大小寫)對應的值(沒有這樣的參數,返回null; 沒有任何值,返回空String);多參數同名時,只取一個。
getParametervalues: 返回表單中參數名(區分大小寫)對應的字符串數組(沒有這樣的參數,返回null;只有一個值,返回值爲單一元素組);

            get & post
在瀏覽器的地址欄操作按回車鍵,或者是熱連接,都是get請求,form的method屬性如果不指定,默認爲get請求(傳的數據不能太大,且表現爲明文)。
get請求,會將參數顯示在瀏覽器的地址欄上,其顯示格式,在地址之後會以?開始,以'&'分隔參數,可以通過HttpServletRequest對象的getQueryString()方法來獲得get請求的參數值。
post請求:ServletRequest對象的getInputStream()方法可以獲得一個由Socket得來的輸入流,可以使用這個流來實現文件的上傳。getReader()方法可以直接獲取post請求的參數。

  Servlet的生命週期
創建Servlet對象,通過服務器反射機制創建Servlet實例,默認第一次請求時纔會創建。
調用Servlet對象的init()方法,初始化Servlet的信息,init()方法只會在創建後被調用一次。
響應請求,調用service()或者是doGet(),doPost()方法來處理請求,這些方法是運行的在多線程狀態下的。
在長時間沒有被調用或者是服務器關閉時,會調用destroy()方法來銷燬Servlet對象。

Servlet對客戶端提供服務的時序圖(插圖見Servlet_Note.pdf,P16)
Servlet生命週期狀態圖(插圖見Servlet_Note.pdf,P17)

      init方法
當首次創建Servlet時就會調用init方法, 而不是每個用戶請求都會調用該方法。
我們可以在init方法中完成類似於構造方法的初始化功能。
init方法一結束,servlet即可接受客戶端請求;

           init方法實例
覆蓋init(ServletConfig conf)方法時,應該總是在首行調用super.init();或者直接覆蓋init();
init方法接受ServletConfig作爲參數, 用以下方法獲得參數值:
getInitParameter: 返回指定參數名稱對應的值,如果參數不存在,返回null;
getInitParameterNames: 返回所有初始化參數的名字 ;

       service方法
每當服務器接收到對Servlet的請求時,服務器就會產生一個新線程, 並調用service。
service方法檢查HTTP請求類型,並相應地調用doGet、doPost、doPut、doDelete。
被container調用去響應(ServletResponse)來自客戶端的請求(ServletRequest);

   Servlets的多線程安全
多線程佔用資源少,處理速度快,提高了效率。
一些編碼建議:
對變量和方法定義適當的訪問方式, 例如單純取值操作不會有多線程安全問題;
同步化所有訪問重要數據的實例變量; 多線程下,如果操作的是一個變量,且兼有讀寫操作,
就要考慮加上同步,但同步不能亂加,否則會造成死鎖問題。

併發需要注意的
併發的環境:資源處於一個併發的環境
共享資源:多個線程共享一個臨界資源
全面同步:如有n個變量訪問同一個資源,這n個變量都得同步。即多個鎖一把鑰匙,鑰匙放在一個共享區域內
sychronized(this):粗粒度的鎖。是將所有的路都加鎖;
sychronized(object o1):細粒度的鎖。只對對象中的變量加鎖。效率較前面的高,但是較難控制。
讀寫需要互斥。
sychronized(this):this不能是基本數據類型,必須是Object.不鎖對象的引用,而是對象的內存空間。
servlet中需要同步的:成員變量、文件、靜態變量、數據庫連接

 destroy方法
服務器決定刪除已經加載的Servlet實例之前將調用Servlet的destroy方法;
該方法允許Servlet:
關閉數據庫連接;
中止後臺線程;
將Cookie程序清單或訪問計數寫到磁盤以及執行其他類似的收尾工作。
在Servlet終止時處理Service線程
在destroy()方法中:如有服務(通過一個同步化的實例方法取得當前線程數大於0),則置關閉狀態爲false(通過一個同步化的實例方法實現)。然後循環等待服務線程數爲0,則置關閉狀態爲true.
在Service()方法中: 如見關閉狀態爲true,便不執行具體邏輯方法,直接退出。

HTTP servlet類的基本結構
繼承HttpServlet
實現至少一個service方法,如:doGet(...)和doPost(...)
service方法有兩個參數,HttpServletRequest 和HttpServletResponse:
HttpServletRequest代表經過容器加工的用戶的請求
HttpServletResponse代表需要容器進一步加工的對用戶的響應
我們寫的servlet需要引入javax.servlet.* 和javax.servlet.http.* 兩個命名空間

servlet繼承關係
servlet主要數據結構:
Servlet 接口:主要定義了servlet的生命週期方法
ServletConfig接口:爲servlet提供了使用容器服務的若干重要對象和方法。
ServletContext接口:是Servlet的上下文對象,這個對象是在服務器啓動時創建的,爲servlet提供了使用容器服務的若干重要方法。
GenericServlet抽象類:爲servlet提供了一般的實現(包括實現了servlet和ServletConfig兩個接口),保存了容器通過init方法傳遞給servlet的一個ServletConfig類型的重要對象。
HttpServlet抽象類:爲處理http請求的servlet提供了一般實現,主要是定義和實現了若干service方法。
繼承關係:GenericServlet繼承了Servlet和ServletConfig接口;HttpServlet繼承了GenericServlet;


MVC框架 (組件的各司其職)
Model,模型層(封裝數據 ),這一層一般是進行數據庫訪問,並且封裝對象,這一層中也存放在訪問數據庫取出信息封裝成對象的類,也就是實體類的信息,可以使用JDBC或者Hibernate實現這一層的功能。
Ctrl,控制層(改變數據,改變模型的狀態 ),用來相應請求和調用寫好的相應的訪問數據庫的方法,這一層是用來控制請求的響應的,現在我們是使用Servlet來實現這一層,不過一般是會用開源的MVC框架來實現這層,例如struts,或者是Spring的MVC框架。
View,表現層(顯示數據和收集數據),收集數據的一般是form表單,不過要保證數據的正確性要是用JavaScript驗證信息,以後我們會學到的JSP(java server page)就是用來表現、顯示數據的。

Servlet之間的怎麼互相調用在上述基礎上需要解決servlet之間的調用:可以利用servletContext解決每一個servlet都可能和上下文交互,則每個servlet中都應該保存一個servletContext對象,去訪問整個應用的上下文, 步驟如下:
getServletContext()::application
application.getRequestDispatcher(“/res/students/list”)::dis
patcher dispatcher.forward(request,response)
每個JVM中的每一個應用程序裏都存在一個上下文
servletContext在servletConfig的對象中;
ServletContext.getRequestDispatcher(String path):返回一個RequestDispatcher
通過RequestDispatcher的forward()或include()方法傳送請求。
如何在一個servlet中調用另外一個
              servlet:
ServletContext類的getRequestDispatcher(Stringpath)方法獲得一個RequestDispatcher對象,並且跳轉到指定的Servlet,getRequestDispatcher(String path)方法中的參數就是path,就是指定跳轉的Servlet的url-pattern。
RequestDispatcher類的forward(ServletRequestrequest, ServletResponse response) 方法,可以把請求對象轉發給其他的Servlet。


在多個servlet中傳遞信息:
HttpServletRequest對象中的方法
setAttribute(String name,Object o),可以使用HttpServletRequest對象來攜帶信息,並且可以通過getAttribute(String name)方法來獲得攜帶的信息,這兩個方法類似於map中的存取方法,setAttribute方法給數據加上標識,getAttribute方法則是通過這個標識來獲取數據,可以使用這一對方法的前提就是要保證是同一個請求對象(HttpServletRequest)

 

 轉發請求至新的資源
request dispatcher的二種傳送請求方式
   Forward: 將請求從一個servlet傳到服務器上的其他資源
   (servlet、JSP、HTML);
   Include: 將靜態或動態內容包含在當前servlet中;
獲得request dispatcher的二種方式:
   ServletRequest.getRequestDispatcher()     // 相對路徑
   ServletContext.getRequestDispatcher()     // 絕對路徑
Response.sendRedirect(/servapp/state/login); //要寫絕對路徑,產生新的請求,
Forward(req,resp);//在當前路徑基礎上跳轉
   兩個頁面之間跳轉的時侯如果需要數據傳遞,則只能用
   forward();因爲sendRedirect()會產生一個新的請求。

 

servlet中使用數據源訪問數據庫
在服務器中配置數據源(使用admin管理界面)
再servlet中使用JNDI語法獲取數據源
Context context = new InitalContext();
DataSource ds =(DataSource)
context.lookup("java:comp/env/"+dsName);
Connection con = ds.getConnection();
新建一個配置文件myapp.xml(假設web應用程序名稱爲:myapp),將xml文件的頭部和一對<Context>標籤寫入該文件,將server.xml中有關數據源配置的<Resource>標籤內容拷貝到myapp.xml中的<context>標籤之間。server.xml位於$tomcat\conf\文件夾下,myapp.xml放在$tomcat\conf\catalina\localhost\文件夾下。

數據源配置Server.xml
<Resource
   name="jdbc/oracle" 配置JDNI的名字
   type="javax.sql.DataSource" 綁定資源的類型
   password=“openlab"
   driverClassName="oracle.jdbc.driver.OracleDriver" 驅動名
   maxIdle=“1”最大空閒連接數
   maxWait="-1"等待時間,配置爲-1就是無限等待,直到有空閒連接爲止
   username=“open123"
   url="jdbc:oracle:thin:@192.168.0.39:1521:TARENADB"
   maxActive="3" 最大活動連接數/>
     會話管理
爲什麼要使用session?


爲什麼要使用session?
一般來講,從同一客戶打開瀏覽器連接到服務再到客戶關閉瀏覽器可稱爲一次會話(中間瀏覽器可以打開多個窗口)
通信協議分爲有狀態和無狀態兩種。Http協議是一種無狀態協議。一個客戶向服務器發出請求然後服務器返回響應,連接就被關閉了。在服務器端不保留連接的有關信息.因此當下一次連接建立時,服務器已沒有以前連接的信息了,無法判斷這一次連接和以前的連接是不是屬於同一客戶發出的。在實際應用中,客戶進行一個事務性的操作可能需要對服務器進行好幾次連接,這時維護前幾次連接的狀態就非常重要。
服務器必須能夠區分不同的客戶,而且還要有爲每一個客戶存儲數據的方法。

 

session實現的三種方法
Cookie
URL Rewriting
隱藏表單域
使用java servlet API進行會話管理
          (session)
java servlet API 主要提供了兩個與會話相關
的類和接口:Cookie和HttpSession
                 Cookie
控制機制:
⊕Browser---------request----- Web server
⊕Web server---------request+info--------- Browser
⊕Browser---------request+info-------- Web server(客戶端
帶信息來再次訪問其標誌的資源)
詳細解釋
Cookie是一小塊可以嵌入到Http請求和相應中的數據。
它在服務器端產生,並作爲響應頭域的一部分返回用戶。瀏覽器收到包含Cookie的響應後,會把Cookie的內容用key-value對的形式寫入到一個客戶端專門存放Cookie的文本文件中(c:/documents and setting/$user/Cookies)。瀏覽器會把Cookie及隨後產生的請求發給相同的服務器,服務器可以再次讀取 Cookie中存放的數據。
Cookie可以進行有效期的設置,過期的Cookie不會發送給服務器。
Cookie的用法:
獲取Cookies:Cookie[] all = request.getCookies();
獲取Cookies名字:Cookie[i].getName();
獲取Cookies的值:Cookie[i].getValue();
爲Cookies設置新值:Cookie[i].setValue();
設置Cookie保存的最大期限:
Cookie[i].setMaxAge (int expiry);毫秒
以cookie實現的session的流程:
Browser訪問 Web server---- Web server
分給用戶一個jsessionId並返回給用戶保存在本地,同時將jsessionId保存在session中--- 用戶再次訪問本Web server時帶着 jsessionId來訪問------ Web server根據用戶傳過來的jsessionId跟session中的 jsessionId比較,如果有相同的,就將這個jsessionId對應的session返回給用戶,這樣用戶可以看到上一次的訪問信息。


HttpSession
javax.servlet.http.HttpSession接口封裝了HTTP會話的細節,該會話與一段時間內特定的web客戶對web服務器的多個請求相關。它由Servlet容器環境實現。對Servlet的開發者隱藏實現的細節。
在Servlet中進行會話管理時,首先要獲得會話對象。HttpServletRequest.getSession()對象返回與請求相關的當前HttpSession對象,並且該對象不存在時就創建一個新的對象。
HttpServletRequest.getSession(true)具有相同的功能。如果參數是false,當不存在會話對象的時候就不創建新的,而是返回一個Null值。

URL Rewriting
Cookies可以用來跟蹤某一用戶向站點發出的每一個請求,有人認爲web站點管理員能都收集到用戶所瀏覽網頁的足夠信息。這侵犯
了用戶的個人隱私權,所以某些用戶會關閉瀏覽器的Cookie功能。這樣的話就要求程序員事先在實現Cookie的同時也實現重寫URL,那當Cookie失效的時候重寫URL就會替代Cookie發揮作用。
Servlet中的數據可見範圍和生命週期:
一個應用只有一個上下文對象。

 Filter
鏈式結構的問題.
f.doFilter(r,r)
過濾器是沒有url的servlet
容器知道filter的轉發順序,通過配置文件
web.xml中的位置決定執行先後
所以filter就解放了.

web.xml 中的listener、 filter、servlet 加載順序及其詳解


一、
1、啓動一個WEB項目的時候,WEB容器會去讀取它的配置文件web.xml,讀取<listener> 和<context-param>兩個結點。
2、緊急着,容創建一個ServletContext(servlet上下文),這個 web項目的所有部分都將共享這個上下文。
3、容器將<context-param>轉換爲鍵值對,並交給 servletContext。
4、容器創建<listener>中的類實例,創建監聽器。
二、
load- on-startup 元素在web應用啓動的時候指定了servlet被加載的順序,它的值必須是一個整數。如果它的值是一個負整數或是這個元素不存 在,那麼容器會在該servlet被調用的時候,加載這個servlet 。如果值是正整數或零,容器在配置的時候就加載並初始化這個servlet,容 器必須保證值小的先被加載。如果值相等,容器可以自動選擇先加載誰。 
在servlet的配置當中,<load-on- startup>5</load-on-startup>的含義是:
標記容器是否在啓動的時候就加載這個servlet。
當 值爲0或者大於0時,表示容器在應用啓動時就加載這個servlet;
當是一個負數時或者沒有指定時,則指示容器在該servlet被選擇時才 加載。
正數的值越小,啓動該servlet的優先級越高。
三、
首 先可以肯定的是,加載順序與它們在 web.xml 文件中的先後順序無關。即不會因爲 filter 寫在 listener 的前面而會先加 載 filter。最終得出的結論是:listener -> filter -> servlet 
同時還存 在着這樣一種配置節:context-param,它用於向 ServletContext 提供鍵值對,即應用程序上下文信息。我們 的 listener, filter 等在初始化時會用到這些上下文中的信息,那麼 context-param 配置節是不是應該寫 在 listener 配置節前呢?實際上 context-param 配置節可寫在任意位置,因此真正的加載順序爲:context- param -> listener -> filter -> servlet 
對於某類配置節而言, 與它們出現的順序是有關的。以 filter 爲例,web.xml 中當然可以定義多個 filter,與 filter 相關的一個配置節 是 filter-mapping,這裏一定要注意,對於擁有相同 filter-name 的 filter 和 filter-mapping 配置 節而言,filter-mapping 必須出現在 filter 之後,否則當解析到 filter-mapping 時,它所對應的 filter- name 還未定義。web 容器啓動時初始化每個 filter 時,是按照 filter 配置節出現的順序來初始化的,當請求資源匹配多 個 filter-mapping 時,filter 攔截資源是按照 filter-mapping 配置節出現的順序來依次調 用 doFilter() 方法的。 
servlet 同 filter 類似 ,此處不再贅述。 
由 此,可以看出,web.xml 的加載順序是:context- param -> listener -> filter -> servlet ,而同個類型之間的實際程序調用的時候的順序是根據 對應的 mapping 的順序進行調用的。

 

 容器做的事情
產生不重複的jsessionId;
將jsessionId和session對象映射成表;
將jsessionId返回給用戶
(cookie/urlRewriting);
再次訪問時,先在表中查jsessionId對應的session;
將查到的session對象的引用放入request給用戶。

用戶做的事情
request.getSession();
request.setAttribute();
request.getAttribute();
   servlet的會話機制(servlet將
cookie/urlRewriting封裝而成)
底層的cookie和url之間的過程被封裝;
urlRewriting的細節被屏蔽,即jsessionId由容器生成,jsessionId列表由容器維護;
狀態對象由容器維護;
容器提供了在狀態對象中存取數據的方法;會話狀態會被自動持久化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章