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
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. PrintWriter out = response.getWriter();//獲取打印流對象 out.println("hello_Servlet");//向瀏覽器打印數據 out.flush();//刷新 out.close();//關流 }
<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 { } }
一、徹底路徑匹配 以/開始 不能包含統配符* 例如: /hello /init
二、目錄匹配 以/開始, /*結尾 例如: /* /aa/* /aaa/bbb/*
三、擴展名匹配 不能以/開始,以*開始 例如: *.do *.action數據庫
優先級:徹底匹配 > 目錄匹配 > 擴展名匹配 編程
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程序是由WEB服務器調用,web服務器收到客戶端的Servlet訪問請求後:
Web服務器首先檢查是否已經裝載並建立了該Servlet的實例對象。
裝載並建立該Servlet的一個實例對象。
調用Servlet實例對象的init()方法。
建立一個用於封裝HTTP請求消息的HttpServletRequest對象和一個表明HTTP響應消息的HttpServletResponse對象,而後調用Servlet的service()方法並將請求和響應對象做爲參數傳遞進去。
WEB應用程序被中止或從新啓動以前,Servlet引擎將卸載Servlet,並在卸載以前調用Servlet的destroy()方法。 瀏覽器
當多個servlet的線程同時訪問了servlet的共享數據,如成員變量,可能會引起線程安全問題。
1把使用到共享數據的代碼塊進行同步(使用synchronized關鍵字進行同步)
2建議在servlet類中儘可能不要使用成員變量。若是確實要使用成員,必須同步。並且儘可能縮小同步代碼塊的範圍。(哪裏使用到了成員變量,就同步哪裏!!),以免由於同步而致使併發效率下降。
在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 config=this.getServletConfig();
//獲取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);
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域對象。
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("路徑");
1)ServletContext servletContext = config.getServletContext();
2)ServletContext servletContext = this.getServletContext();
getRequestURL方法返回客戶端發出請求完整URL
getRequestURI方法返回請求行中的資源名部分
getQueryString 方法返回請求行中的參數部分
getRemoteAddr方法返回發出請求的客戶機的IP地址
getMethod獲得客戶機請求方式
getContextPath 得到工程虛擬目錄名稱
得到客戶機請求頭 getHeader(name)方法 --- String getHeaders(String name)方法 --- Enumeration<String> getHeaderNames方法 --- Enumeration<String>
得到具體類型客戶機請求頭 getIntHead(name)方法 --- int getDateHead(name)方法 --- long(日期對應毫秒)
getParameter(name) --- String 經過name得到值 getParameterValues --- String[ ] 經過name得到多值 checkbox getParameterNames --- Enumeration<String> 得到全部name getParameterMap --- Map<String,String[ ]> key :name value: 多值
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");
經常使用轉義規則 空格換成加號(+)
+換成%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對象,它們屬於兩個獨立的訪問請求和響應過程。
狀態碼(Status Code)
setStatus(int)
經常使用狀態碼:200、30二、30四、40四、500
頭信息 (Header Info)
addHeader(String,String) 在原有值添加
setHeader(String,String) 替換原有值
//隔1秒以後,刷新到一個新頁面 resp.setHeader("Refresh", "1;/day02/a.html"); //設置當前頁面每隔1秒刷新一次 resp.setHeader("Refresh", "1");
方案1: resp.setStatus(304); resp.setHeader("Location", "/FirstWeb/aa.jsp"); 方案2: resp.sendRedirect(「/FirstWeb/aa.jsp」); //推薦使用
response.getWriter().write(); 發送字符實體內容 response.getOutputStream().write() 發送字節實體內容 字節流輸出中文 亂碼和瀏覽器的編碼有關 設置瀏覽器默認打開的時候的編碼集 得到字節數組的時候,傳入一個編碼集 字符流輸出中文 response的字符流的緩衝區是ISO-8859-1編碼. 設置response緩衝區的編碼. 設置瀏覽器的默認打開的時候字符集編碼.
向客戶端輸出字符中文的簡寫方式 response.setContentType("text/html;charset=UTF-8"); 字節流與字符流是互斥的 同一個頁面只能使用一種流,不能同時向頁面響應。 使用字符流輸入數字,有可能存在問題 想輸入數字時,使用字符串」1」
設置頭信息response.setHeader(「Content-Disposition」,」 attachment;filename=」+文件名稱);
經過response.getOutputStream()向瀏覽器端輸出
發送http頭,控制瀏覽器禁止緩存當前文檔內容 設置如下三個Http頭信息禁用瀏覽器緩存 Cache-Control : no-cache Expires: Thu, 01 Dec 1994 16:00:00 GMT (很是特殊,轉換特定日期格式才能夠)
將jsp中java代碼和html代碼進行分離,將java代碼寫入到servlet中
servlet主要負責業務邏輯,jsp只負責顯示數據
頁面發送請求->web.xml->解析web.xml中url-pattern標籤,獲取值後
和請求進行匹配(equals())->獲取servlet-mapping標籤中的
servlet-name ->獲取servlet標籤中servlet-name,和mapping標籤中
的name進行匹配->獲取servlet-class中的值-->Class.forName("類的完整路徑").newInstance()
這裏的路徑須要注意
http://localhost:8080/B/UserServlet?method=login&name=Colin&pass=123 這裏的login就是方法的名字
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的形式寫給用戶各自的瀏覽器。當用戶使用瀏覽器再去訪問服務器中的web資源時,就會帶着各自的數據去。這樣,web資源處理的就是用戶各自的數據了。
服務器建立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只能標識一種信息,它至少含有一個標識該信息的名稱(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數據
在WEB開發中,服務器能夠爲每一個用戶瀏覽器建立一個會話對象(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對象 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) : 清除數據
三個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有效時間
application Scope servletContext (數據庫鏈接池,配置, 線程池, 站點訪問次數)
每個Web應用對應一個ServletContext
存放全部用戶均可以訪問的數據
session Scope HttpSession (存放與用戶相關數據)
存放每一個用戶本身會話過程當中的數據
request Scope HttpServletRequest
(Servlet處理結果,JSP顯示)
數據存放在request對象中
生成新的請求時,原request存放數據丟失
(1)保存位置:session-服務器,cookie--客戶端(2)保存數據不一樣:session存入後Object,Cookie--String(3)運行週期:session--瀏覽器訪問期間,Cookie能夠永久保存(4)安全性:session高於cookie