Servlet

介紹

Servlet是sun公司提供的一門用於開發動態web資源的技術。
Servlet是JavaWeb的三大組件之一,它屬於動態資源。Servlet的做用是處理請求,服務器會把接收到的請求交給Servlet來處理,在Servlet中一般須要:
接收請求數據;html

【1.獲取信息】
處理請求;java

【2.調用方法】Dao中的方法mysql

完成響應
【3.頁面跳轉】
  例如客戶端發出登陸請求,或者輸出註冊請求,這些請求都應該由Servlet來完成處理!Servlet須要咱們本身來編寫,每一個Servlet必須實現javax.servlet.Servlet接口。程序員

使用

Sun公司在其API中提供了一個servlet接口,用戶若想要開發一個動態web資源(即開發一個Java程序向瀏覽器輸出數據),須要完成如下2個步驟:web

1. 編寫一個Java類,實現servlet接口。而後把開發好的Java類部署到web服務器中。

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.
PrintWriter out = response.getWriter();//獲取打印流對象
out.println("hello_Servlet");//向瀏覽器打印數據
out.flush();//刷新
out.close();//關流
}

 2.servlet須要進行註冊(在web.xml中)(手動部署)

<servlet>
        <servlet-name>Servlet1</servlet-name>
        <servlet-class>com.zym.servlet.Servlet1</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name> Servlet1</servlet-name>
        <url-pattern>/Servlet1</url-pattern>
    </servlet-mapping>

還能夠直接在生成的servlet文件中配置sql

package com.zym.servlet;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "Servlet2",urlPatterns = "/Servlet2")
public class Servlet2 extends HttpServlet {


    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("start.............");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

Servlet的編寫及配置

URL-Pattern的三種配置方式

一、徹底路徑匹配 以/開始 不能包含統配符* 例如: /hello /init
二、目錄匹配 以/開始, /*結尾 例如: /* /aa/* /aaa/bbb/*
三、擴展名匹配 不能以/開始,以*開始 例如: *.do *.action數據庫

 

優先級

優先級:徹底匹配 > 目錄匹配 > 擴展名匹配 編程

example

Servlet1 映射到 /abc/*
Servlet2 映射到 /*
Servlet3 映射到 /abc
Servlet4 映射到 *.do
當請求URL爲「/abc/a.html」,「/abc/*」和「/*」都匹配,哪一個servlet響應
    Servlet引擎將調用Servlet1。
當請求URL爲「/abc」時,「/abc/*」和「/abc」都匹配,哪一個servlet響應
    Servlet引擎將調用Servlet3。
當請求URL爲「/abc/a.do」時,「/abc/*」和「*.do」都匹配,哪一個servlet響應
    Servlet引擎將調用Servlet1。
當請求URL爲「/a.do」時,「/*」和「*.do」都匹配,哪一個servlet響應
    Servlet引擎將調用Servlet2.
當請求URL爲「/xxx/yyy/a.do」時,「/*」和「*.do」都匹配,哪一個servlet響應
    Servlet引擎將調用Servlet2。

編寫注意事項

Servlet初始化時覆蓋init() ,無需覆蓋init(config)
根據Http請求的方式,覆蓋相應的doGet或者doPost方法,無需覆蓋Service方法
當doGet和doPost代碼邏輯相同時,能夠相互調用,簡化編程數組

Servlet的執行過程

Servlet程序是由WEB服務器調用,web服務器收到客戶端的Servlet訪問請求後:
Web服務器首先檢查是否已經裝載並建立了該Servlet的實例對象。
裝載並建立該Servlet的一個實例對象。
調用Servlet實例對象的init()方法。
建立一個用於封裝HTTP請求消息的HttpServletRequest對象和一個表明HTTP響應消息的HttpServletResponse對象,而後調用Servlet的service()方法並將請求和響應對象做爲參數傳遞進去。
WEB應用程序被中止或從新啓動以前,Servlet引擎將卸載Servlet,並在卸載以前調用Servlet的destroy()方法。 瀏覽器

Servlet線程安全

當多個servlet的線程同時訪問了servlet的共享數據,如成員變量,可能會引起線程安全問題。

解決方法:

1把使用到共享數據的代碼塊進行同步(使用synchronized關鍵字進行同步)

2建議在servlet類中儘可能不要使用成員變量。若是確實要使用成員,必須同步。並且儘可能縮小同步代碼塊的範圍。(哪裏使用到了成員變量,就同步哪裏!!),以免由於同步而致使併發效率下降。

ServletConfig對象和ServletContext對象(瞭解)

ServletConfig

在Servlet的配置文件中,可使用一個或多個<init-param>標籤爲servlet配置一些初始化參數。

當servlet配置了初始化參數後,經過ServletConfig對象獲得初始化信息,web容器在建立servlet實例對象時,會自動將這些初始化參數封裝到ServletConfig對象中,並在調用servlet的init方法時,將ServletConfig對象傳遞給servlet。進而,程序員經過ServletConfig對象就能夠獲得當前servlet的初始化參數信息。

<servlet>
    <servlet-name>ConfigDemo</servlet-name>
    <servlet-class>gz.itcast.f_config.ConfigDemo</servlet-class>
    <!-- 初始參數: 這些參數會在加載web應用的時候,封裝到ServletConfig   對象中 -->
    <init-param>
        <param-name>path</param-name>
        <param-value>e:/b.txt</param-value>
    </init-param>
  </servlet>

在一個web應用能夠存在多個ServletConfig對象(一個Servlet對應一個ServletConfig對象)
 在哪一個servlet裏面配置的初始化參數,只能在該servlet裏面獲取

servletConfig對象獲取

ServletConfig config=this.getServletConfig(); 

Servlet初始化參數

//獲取servletConfig對象
    ServletConfig config = this.getServletConfig();
//獲得初始化值
    String name = config.getInitParameter("name");
    String age = config.getInitParameter("age");
    String address = config.getInitParameter("address");
    System.out.println(name+"   "+age+"   "+address);

ServletContext

WEB容器在啓動時,它會爲每一個WEB應用程序都建立一個對應的ServletContext對象,它表明當前web應用。
ServletContext表明是一個web應用的環境(上下文)對象,ServletContext對象 內部封裝是該web應用的信息,ServletContext對象一個web應用只有一個
一個web項目只會有一個ServletContext對象
ServletConfig對象中維護了ServletContext對象的引用,開發人員在編寫servlet時,能夠經過ServletConfig.getServletContext方法得到ServletContext對象。
對象獲取方法
因爲一個WEB應用中的全部Servlet共享同一個ServletContext對象,所以Servlet對象之間能夠經過ServletContext對象來實現通信。ServletContext對象一般也被稱之爲context域對象。

瞭解ServletContext對象的功能

web.xml中配置初始化參數
    <context - param>
    <param -name>driver</param - name>
    <param -value>com.mysql.jdbc.Driver</param - value>
    </context - param>
經過context對象得到參數
    獲取servletContext對象
    ServletContext context = getServletContext();
    獲取初始化參數
    String initParameter = context.getInitParameter("driver");
    System.out.println(initParameter);

context.getRealPath(「路徑」) //獲得web應用中的資源文件
context.getResourceAsStream("路徑");

 

servletContext對象獲取

1)ServletContext servletContext = config.getServletContext();
2)ServletContext servletContext = this.getServletContext();

HttpServletRequest(重點)

Request獲取客戶端請求信息

getRequestURL方法返回客戶端發出請求完整URL
getRequestURI方法返回請求行中的資源名部分
getQueryString 方法返回請求行中的參數部分
getRemoteAddr方法返回發出請求的客戶機的IP地址
getMethod獲得客戶機請求方式
getContextPath 得到工程虛擬目錄名稱

Request獲取請求頭

得到客戶機請求頭
    getHeader(name)方法 --- String 
    getHeaders(String name)方法 --- Enumeration<String>
    getHeaderNames方法 --- Enumeration<String>
得到具體類型客戶機請求頭
    getIntHead(name)方法  --- int
    getDateHead(name)方法 --- long(日期對應毫秒)

Request獲取請求參數

getParameter(name) --- String 經過name得到值
getParameterValues  --- String[ ] 經過name得到多值 checkbox
getParameterNames  --- Enumeration<String> 得到全部name
getParameterMap  --- Map<String,String[ ]> key :name value: 多值

Request請求參數亂碼

POST請求亂碼 :request.setCharacterEncoding("utf-8"); 
GET請求亂碼 
    解決方案一:
        修改server.xml ,不建議使用此種解決方案
            <Connector port="80" protocol="HTTP/1.1" 
                       connectionTimeout="20000" 
                       redirectPort="8443" URIEncoding="utf-8"/>
    * 必須有修改tomcat服務器配置文件權限 
    解決方案二:逆向編解碼
                  username = URLEncoder.encode(username, "ISO-8859-1");
                  username = URLDecoder.decode(username, "utf-8");
                  簡化
                      username = new String(username.getBytes("ISO8859-1"),"utf-8");

URL特殊字符轉義規則

經常使用轉義規則
空格換成加號(+) 
+換成%2B 正斜槓(
/)分隔目錄和子目錄 換成%2F 問號(?)分隔URL和查詢 換成%3F 百分號(%)制定特殊字符 換成%25 #號指定書籤 換成%23 &號分隔參數 換成%26 java.net.URLEncoder和 java.net.URLDecoder

請求和重定向的區別

RequestDispatcher.forward方法只能將請求轉發給同一個WEB應用中的組件;而HttpServletResponse.sendRedirect 方法還能夠重定向到同一個站點上的其餘應用程序中的資源,甚至是使用絕對URL重定向到其餘站點的資源。 
若是傳遞給HttpServletResponse.sendRedirect 方法的相對URL以「/」開頭,它是相對於服務器的根目錄;若是建立RequestDispatcher對象時指定的相對URL以「/」開頭,它是相對於當前WEB應用程序的根目錄。 
調用HttpServletResponse.sendRedirect方法重定向的訪問過程結束後,瀏覽器地址欄中顯示的URL會發生改變,由初始的URL地址變成重定向的目標URL;調用RequestDispatcher.forward 方法的請求轉發過程結束後,瀏覽器地址欄保持初始的URL地址不變。
HttpServletResponse.sendRedirect方法對瀏覽器的請求直接做出響應,響應的結果就是告訴瀏覽器去從新發出對另一個URL的訪問請求;RequestDispatcher.forward方法在服務器端內部將請求轉發給另一個資源,瀏覽器只知道發出了請求並獲得了響應結果,並不知道在服務器程序內部發生了轉發行爲。 
RequestDispatcher.forward方法的調用者與被調用者之間共享相同的request對象和response對象,它們屬於同一個訪問請求和響應過程;而HttpServletResponse.sendRedirect方法調用者與被調用者使用各自的request對象和response對象,它們屬於兩個獨立的訪問請求和響應過程。 

HttpServletResponse (重點)

Response設置響應頭和狀態碼

狀態碼(Status Code)
setStatus(int)
經常使用狀態碼:200、30二、30四、40四、500

 

頭信息 (Header Info)
addHeader(String,String) 在原有值添加
setHeader(String,String) 替換原有值

Response實現頁面刷新

//隔1秒以後,刷新到一個新頁面
resp.setHeader("Refresh", "1;/day02/a.html");
//設置當前頁面每隔1秒刷新一次
resp.setHeader("Refresh", "1");

Response實現重定向

方案1:
    resp.setStatus(304);
    resp.setHeader("Location", "/FirstWeb/aa.jsp");
方案2:
    resp.sendRedirect(「/FirstWeb/aa.jsp」); //推薦使用

Response向頁面輸出內容

response.getWriter().write();   發送字符實體內容
response.getOutputStream().write()  發送字節實體內容
字節流輸出中文
    亂碼和瀏覽器的編碼有關
    設置瀏覽器默認打開的時候的編碼集
    得到字節數組的時候,傳入一個編碼集
字符流輸出中文
    response的字符流的緩衝區是ISO-8859-1編碼.
    設置response緩衝區的編碼.
    設置瀏覽器的默認打開的時候字符集編碼.

Response開發細節

向客戶端輸出字符中文的簡寫方式
response.setContentType("text/html;charset=UTF-8");
字節流與字符流是互斥的
同一個頁面只能使用一種流,不能同時向頁面響應。
使用字符流輸入數字,有可能存在問題
想輸入數字時,使用字符串」1」

Response實現文件下載

設置頭信息response.setHeader(「Content-Disposition」,」 attachment;filename=」+文件名稱);
經過response.getOutputStream()向瀏覽器端輸出

Response禁用瀏覽器緩存

發送http頭,控制瀏覽器禁止緩存當前文檔內容
設置如下三個Http頭信息禁用瀏覽器緩存
Cache-Control : no-cache
Expires: Thu, 01 Dec 1994 16:00:00 GMT (很是特殊,轉換特定日期格式才能夠)

Javabean【實體類】 & servlet

將jsp中java代碼和html代碼進行分離,將java代碼寫入到servlet中

servlet主要負責業務邏輯,jsp只負責顯示數據

 請求->找到servlet的過程:

頁面發送請求->web.xml->解析web.xml中url-pattern標籤,獲取值後
和請求進行匹配(equals())->獲取servlet-mapping標籤中的
servlet-name ->獲取servlet標籤中servlet-name,和mapping標籤中
的name進行匹配->獲取servlet-class中的值-->Class.forName("類的完整路徑").newInstance()

baseServlet【增強反射】

建立一個BaseServlet繼承HttpServlet【重寫service方法】

這裏的路徑須要注意

http://localhost:8080/B/UserServlet?method=login&name=Colin&pass=123
這裏的login就是方法的名字

在service方法中

package com.zym.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@WebServlet(name = "BaseServlet")
public class BaseServlet extends HttpServlet {

@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String MethodName = req.getParameter("method");
System.out.println(this);
//com.zym.servlet.User_Servlet@163fc255
Class<? extends BaseServlet> clazz = this.getClass();
try {
//獲取方法對象
Method method = clazz.getMethod(MethodName, HttpServletRequest.class, HttpServletResponse.class);

//執行方法
String path = (String ) method.invoke(this,req,resp);

System.out.println("路徑:"+path);

if (path!=null) {
System.out.println("頁面跳轉");
req.getRequestDispatcher(path).forward(req,resp);
}

} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}
}
package com.zym.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "User_Servlet")
public class User_Servlet extends BaseServlet {

    public String  login(HttpServletRequest request,HttpServletResponse response){

     String name = request.getParameter("user");
        String pwd = request.getParameter("pwd");

        System.out.println(name+""+pwd);

        return "test.jsp";
    }

Cookie

Cookie是客戶端技術,程序把每一個用戶的數據以cookie的形式寫給用戶各自的瀏覽器。當用戶使用瀏覽器再去訪問服務器中的web資源時,就會帶着各自的數據去。這樣,web資源處理的就是用戶各自的數據了。

Cookie會話技術的原理

服務器建立cookie對象,把會話數據存儲到cookie對象中。
new Cookie("name","value");
Cookie cookieName = new Cookie("NAME","Colin")
Cookie cookiePass = new Cookie("PASS","123456")

服務器發送cookie信息到瀏覽器
response.addCookie(cookieName);
response.addCookie(cookiePass);

瀏覽器獲得服務器發送的cookie,而後保存在瀏覽器端。

瀏覽器在下次訪問服務器時,會帶着cookie信息

服務器接收到瀏覽器帶來的cookie信息
request.getCookies();  返回Cookie[]

核心技術點

構造Cookie對象
Cookie(java.lang.String name, java.lang.String value)

設置cookie
void setPath(java.lang.String uri)   :設置cookie的有效訪問路徑
void setMaxAge(int expiry) : 設置cookie的有效時間,單位是秒
void setValue(java.lang.String newValue) :設置cookie的值

發送cookie到瀏覽器端保存
void response.addCookie(Cookie cookie)  : 發送cookie

服務器接收cookie
Cookie[]    request.getCookies()  : 接收cookie

Cookie會話技術的使用

顯示用戶上次訪問時間
判斷用戶是不是第一次訪問
若是是第一次訪問,須要輸出歡迎,而且記錄當前的時間,保存到cookie中,再回寫到瀏覽器端。
若是不是第一次訪問,獲取cookie中的時間,輸出時間,而且記錄當前的時間,保存到cookie中,再回寫到瀏覽器端。

Cookie細節

一個Cookie只能標識一種信息,它至少含有一個標識該信息的名稱(NAME)和設置值(VALUE)。


一個WEB站點能夠給一個WEB瀏覽器發送多個Cookie,一個WEB瀏覽器也能夠存儲多個WEB站點提供的Cookie。


void setPath(java.lang.String uri) :設置cookie的有效訪問路徑。有效路徑指的是cookie的有效路徑保存在哪裏,那麼瀏覽器在有效路徑下訪問服務器時就會帶着cookie信息,不然不帶cookie信息。

 

Cookie數據類型只能保存非中文字符串類型的。能夠保存多個cookie,可是瀏覽器通常只容許存放300個Cookie,每一個站點最多存放20個Cookie,每一個Cookie的大小限制爲4KB。

void setMaxAge(int expiry) : 設置cookie的有效時間。
正整數:表示cookie數據保存瀏覽器的緩存目錄(硬盤中),數值表示保存的時間。
負整數:表示cookie數據保存瀏覽器的內存中。瀏覽器關閉cookie就丟失了!!
零:表示刪除同名的cookie數據

Session

在WEB開發中,服務器能夠爲每一個用戶瀏覽器建立一個會話對象(session對象),注意:一個瀏覽器獨佔一個session對象(默認狀況下)。所以,在須要保存用戶數據時,服務器程序能夠把用戶數據寫到用戶瀏覽器獨佔的session中,當用戶使用瀏覽器訪問其它程序時,其它程序能夠從用戶的session中取出該用戶的數據,爲用戶服務。

Session的原理

1)第一次訪問建立session對象,給session對象分配一個惟一的ID,叫JSESSIONID
2)把JSESSIONID做爲Cookie的值發送給瀏覽器保存
3)第二次訪問的時候,瀏覽器帶着JSESSIONID的cookie訪問服務器
4)服務器獲得JSESSIONID,在服務器的內存中搜索是否存放對應編號的session對象。
5)若是找到對應編號的session對象,直接返回該對象
6)若是找不到對應編號的session對象,建立新的session對象,同時分配一個sessionId,而後繼續走1的流程
結論:經過JSESSION的cookie值在服務器找session對象!!!!!

Session的核心技術點

建立或獲得session對象
HttpSession getSession()   至關於 getSession(true)   getSession(false)
HttpSession getSession(boolean create)  

設置session對象
void setMaxInactiveInterval(int interval)  : 設置session的有效時間,設置爲-1的時候表示session永遠不過時;
void invalidate()     : 銷燬session對象
java.lang.String getId()  : 獲得session編號

保存會話數據到session對象
void setAttribute(java.lang.String name, java.lang.Object value)  : 保存數據
java.lang.Object getAttribute(java.lang.String name)  : 獲取數據
void removeAttribute(java.lang.String name) : 清除數據

Session須要注意的細節

三個getSession()方法的區別
getSession(true) / getSession()  : 建立或獲得session對象。沒有匹配的session編號,自動建立新的session對象。
getSession(false):    獲得session對象。沒有匹配的session編號,返回null

Session對象銷燬的時間    
    a. 默認狀況30分鐘服務器自動回收
    b.手動修改session回收時間,設置setMaxInactiveInterval(int interval)  (若是設置-1的話,表示永遠不過時)
    c. 全局修改session有效時間,在web.xml裏面設置全局的session有效時間   

Servlet的數據訪問範圍

application Scope  servletContext (數據庫鏈接池,配置, 線程池, 站點訪問次數) 
    每個Web應用對應一個ServletContext
    存放全部用戶均可以訪問的數據
session Scope HttpSession (存放與用戶相關數據) 存放每一個用戶本身會話過程當中的數據
request Scope HttpServletRequest
(Servlet處理結果,JSP顯示) 數據存放在request對象中 生成新的請求時,原request存放數據丟失

session和Cookie的區別

(1)保存位置:session-服務器,cookie--客戶端(2)保存數據不一樣:session存入後Object,Cookie--String(3)運行週期:session--瀏覽器訪問期間,Cookie能夠永久保存(4)安全性:session高於cookie

相關文章
相關標籤/搜索