目錄
Servlet
Servlet簡介
- Servlet(Service+Applet)伺服器小程式,主要用於生成動態的Web內容。
- Servlet通常通過HTTP協議接收和響應來自Web客戶端的請求。
- Servlet實際上是一個介面
Servlet簡單實現
- 建立一個類:Myservlet 該檔案目錄為:D:\IdeaProjects\FirstServlet\src\servlet\MyServlet.java
package 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.io.PrintWriter;
//繼承HttpServlet類
public class MyServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println("<h1 style='color:red'>"+"Hello Servlet"+"</h1>");
}
}
- 在WEB-INF資料夾下對web.xml中配置Servlet對映
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>myservlet</servlet-name>//類的別名
<servlet-class>servlet.MyServlet</servlet-class>//該類的路徑
</servlet>
<servlet-mapping>
<servlet-name>myservlet</servlet-name>//類的別名
<url-pattern>/myservlet</url-pattern>//請求該類對應的URL
</servlet-mapping>
</web-app>
實現原理:①當伺服器接受到客戶端瀏覽器的請求後,會解析請求URL路徑,獲取訪問的Servlet的資源路徑
②查詢web.xml檔案,是否有對應的<url-pattern>標籤體內容。
③如果有,則在找到對應的<servlet-class>全類名
④tomcat會將位元組碼檔案載入進記憶體,並且建立其物件
⑤呼叫其方法
建立Servlet的三種方法:
實現Servlet介面
*必須得實現介面中的抽象方法*
繼承GenericServlet類
繼承HttpServlet類
Servlet註解
每次建立Servlet類之後都要在WEB-INF資料夾下對web.xml中配置Servlet對映,但凡類較多的時候web.xml檔案會因為配置Servlet顯得檔案過長可讀性較差。而使用註解則不需要部署web.xml檔案。
PS:tomcat7之前的版本是不支援註解的。這是Servlet3的特性,所以在建立專案時指定版本3.0以上。
格式: @WebServlet("資源路徑")
在配置對映時,路徑要加斜槓,不然會報錯
package 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.io.PrintWriter;
@WebServlet("/myservlet") //此處為Servlet註解
//繼承HttpServlet類
public class MyServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println("<h1 style='color:red'>"+"Hello Servlet"+"</h1>");
}
}
Servlet生命週期
**①載入Servlet類。**
類載入器負責載入servlet類。 當Web容器接收到servlet的第一個請求時,將載入servlet類。
**②建立Servlet例項。**
載入servlet類之後在第一次訪問Servlet對應的URL時,tomcat會對該Servlet類建立物件,並執行建構函式。servlet例項在servlet生命週期中只建立一次。
**③呼叫Servlet類的`init`方法。初始化**
在第一次建立Servlet時被呼叫,只呼叫一次,後續請求不再呼叫。用於一次性初始化。
**④呼叫Servlet類的`service`方法。提供服務**
當對Servlet進行訪問時,就會提供訪問服務方法(如:`service()` `doGet()` `doPost()`)處理來自客戶端(瀏覽器)的請求,並把格式化的響應寫回給客戶端。
**⑤呼叫Servlet類的`destroy`方法。銷燬**
從服務中刪除servlet例項之前(關閉或重啟tomcat),Web容器呼叫`destroy`方法。在呼叫 destroy() 方法之後,servlet 物件被標記為垃圾回收,釋放資源。
啟動時載入Servlet
啟動時載入常用於系統的預處理
在web.xml使用<load-on-startup>設定啟動時載入,所傳遞的值表示載入時的優先順序,**若傳遞的為負值則系統第一個載入**
Servlet客戶端 HTTP請求的結構
HTTP請求包含三部分:請求行、請求頭、請求體
請求行(請求方法、請求URL、HTTP協議及版本)
如:POST /loginServlet HTTP/1.1
關於請求方式:POST請求的請求引數在請求體中
**GET請求的請求引數在請求行中,在URL之後**
請求頭
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
Connection: keep-alive
Referer: http://localhost:8080/FirstServlet/login.html
Cookie: JSESSIONID=131FD70E4649021B826F5654951687CF
Upgrade-Insecure-Requests: 1User-Agent(使用者環境,包括客戶使用的作業系統及版本 CPU型別 瀏覽器版本等一些資訊)
請求體(封裝POST請求訊息的請求引數)
username=admin&password=123456
Servlet伺服器 HTTP響應的結構
HTTP響應包含三部分:響應行、響應頭、響應體
響應行(報文協議及版本、狀態碼及狀態描述)
Http/1.1 200 OK
響應頭(一些輔助資訊)
Content-Type:text/html .......
響應體(描述了瀏覽器要響應的資訊)
HTTP常見狀態碼
狀態碼 | 錯誤描述 |
---|---|
200 | 伺服器處理成功 |
404 | 無法找到檔案 |
500 | 內部伺服器錯誤 |
403 | 伺服器拒絕訪問 |
301、302 | 請求重定向 |
400 | 無效的請求 |
401 | 未經過授權 |
503 | 伺服器超負荷或停機維護,無法處理請求 |
ConteneType的作用
- ConteneType決定瀏覽器以何種方式來處理響應體
型別 | 描述 |
---|---|
text/plain | 純文字 |
text/html | HTML文件 |
text/xml | xml文件 |
application/x-msdownload | 需要下載的資源 |
Servlet請求轉發與響應重定向
Servlet請求轉發
原理:輸入一個正確的URL之後,會產生一個請求傳送到Tomcat上,在Servlet_A處理完之後呼叫request.getRequestDispatcher().forward()
方法之後,將HttpServletRequest物件原封不動的傳送給Servlet_B,在Servlet_B處理完之後產生響應返回給客戶端。
checkLogin.java
package servlet_direct;
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("/direct/check")
public class checkLogin extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("使用者登入成功!");
req.getRequestDispatcher("/direct/index").forward(req,resp);//請求轉發語句
}
}
indexServlet.java
package servlet_direct;
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("/direct/index")
public class indexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("<h1>This is index page</h1>" );
}
}
②轉發只能訪問當前伺服器下的資源
③轉發是一次請求,可以使用request物件來共享資料
Servlet響應重定向
原理:輸入一個正確的URL之後,會產生一個請求傳送到Tomcat上,在Servlet_A處理完產生響應返回給客戶端,客戶端再產生新的請求跳轉到新地址上,由Tomcat傳送給Servlet_B處理完之後產生新的響應返回給客戶端。
checkLogin.java
package servlet_direct;
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("/direct/check")
public class checkLogin extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("使用者登入成功!");
resp.sendRedirect("/FirstServlet/direct/index");//響應重定向語句
}
}
indexServlet.java
package servlet_direct;
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("/direct/index")
public class indexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("<h1>This is index page</h1>" );
}
}
請求轉發和響應重定向比較
請求轉發 | 響應重定向 |
---|---|
轉發位址列路徑不變 | 位址列發生變化 |
只能訪問當前伺服器下的資源 | 可以訪問其他站點(伺服器)的資源 |
一次請求,可以使用request物件來共享資料 | 兩次請求。不能使用request物件來共享資料 |
會話技術(Cookie和Session)
會話:客戶端和伺服器之間發生一系列的請求與響應的過程。(一方斷開即會話結束)
作用:在一次會話的範圍內的多次請求間,共享資料
方式: 客戶端會話技術:Cookie
伺服器端會話技術:Session
Servlet Cookie
概念:客戶端會話技術,將資料儲存到客戶端。當使用者通過瀏覽器訪問Web伺服器時,伺服器會給客戶端傳送一些資訊(伺服器向客戶端傳送Cookie時,會在HTTP響應頭中增加Set-Cookie響應頭資訊),這些資訊會儲存在Cookie中。這樣,當瀏覽器再次訪問伺服器時,會在請求頭中將Cookie傳送給伺服器,方便伺服器對瀏覽器做出正確的響應。
Cookie工作原理
當瀏覽器向伺服器傳送請求之後,伺服器會建立一個Cookie物件,將資料儲存在其中,然後把Cookie物件放在響應頭(response.addCookie(cookie物件)
)傳送給瀏覽器,瀏覽器接收響應後將Cookie儲存在客戶端;當瀏覽器再次訪問伺服器時,會把儲存的Cookie放在請求頭中一起傳送給伺服器,伺服器從中獲取Cookie(request.getCookie()
),然後作出響應。
cookie_first.java
package servlet_cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/cookie_first")
public class cookie_first extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//建立Cookie物件,儲存相應資料
Cookie cookie = new Cookie("name", "Jack");
//將生成的cookie傳送給瀏覽器
response.addCookie(cookie);
//設定持久化時間
cookie.setMaxAge(60*2);//有效時間2分鐘
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
cookie_second.java
package servlet_cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/cookie_second")
public class cookie_second extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//伺服器從中獲取cookie
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
response.getWriter().println(cookie.getName()+"="+cookie.getValue());
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
Servlet Session
概念:伺服器端會話技術,在一次會話的多次請求間共享資料,將資料儲存在伺服器端的物件中。瀏覽器訪問Web伺服器時,Servlet容器就會建立一個Session物件和ID屬性,當客戶端後續訪問伺服器時,只要將標識號傳遞給伺服器,伺服器就能判斷該請求是哪個客戶端傳送的,從而選擇與之對應的Session物件為其服務。預設情況下session的有效時間為30分鐘。
Session工作原理
客戶端傳送一個全新的請求給伺服器,伺服器就會建立一個Session物件,並且設定SessionId:178HA。然後Servlet會執行session.setAttribute("name","王小二");
設定自定義屬性,把資料封裝在這個Session物件中,將Session物件儲存在伺服器中。之後會將SessionID連同響應回瀏覽器,瀏覽器就會把SessionId值儲存在Cookie中。在下一次傳送請求時,會攜帶SessionID:178HA給伺服器。伺服器會根據所獲取的Session編號找到對應的Session物件,然後利用該Session物件把儲存的資料取出來!
loginServlet.java
package servlet_session;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session/login")
public class loginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//建立Session物件
HttpSession session = req.getSession();
//設定自定義屬性
session.setAttribute("name","王小二");
//獲取SessionId
System.out.println(session.getId());
req.getRequestDispatcher("/session/index").forward(req,resp);
}
}
indexServlet.java
package servlet_session;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session/index")
public class indexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
System.out.println(session.getId());
//獲取自定義屬性
String name =(String)session.getAttribute("name");
//設定響應編碼格式
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().println("當前登入使用者為:"+name);
}
}
Post請求中文亂碼
對於Tomcat8.X版本,預設Get請求傳送中文就是UTF-8格式,無須轉換。
而對於Post請求,通過呼叫setCharacterEncoding("UTF-8")
來解決中文亂碼問題。