Table of Contents
1.2:手動實現 Servlet 程序---HelloServlet
1.6:通過繼承 HttpServlet 實現 Servlet 程序
2.1:ServletConfig 類的三大作用 類的三大作用
3.2:ServletContext 類的四個作用 類的四個作用
5.1:HttpServletRequest 類有什麼作用。
5.4:doGet 請求的中文亂碼解決: 請求的中文亂碼解決:
6.5:請求重定向-resp.sendRedirect("http://localhost:8080");
三:web組件-Servlet
1:Servlet技術
1.1:什麼是 Servlet
1、Servlet 是 JavaEE 規範之一。規範就是接口
2、Servlet 就 JavaWeb 三大組件之一。三大組件分別是:Servlet 程序、Filter 過濾器、Listener 監聽器。
3、Servlet 是運行在服務器上的一個 java 小程序,它可以接收客戶端發送過來的請求,並響應數據給客戶端。
1.2:手動實現 Servlet 程序---HelloServlet
1、編寫一個類去實現 Servlet 接口
2、實現 service 方法,處理請求,並響應數據
3、到 web.xml 中去配置 servlet 程序的訪問地址
Servlet代碼:
package com.wkl.servlet;
import javax.servlet.*;
import java.io.IOException;
/**
* Description:
* Date: 2020/6/14 - 下午 9:10
* author: wangkanglu
* version: V1.0
*/
public class HelloServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello Servlet 被訪問了");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
web.xml代碼:
<?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 標籤給 Tomcat 配置 Servlet 程序 -->
<servlet>
<!--servlet-name 標籤 Servlet 程序起一個別名(一般是類名) -->
<servlet-name>HelloServlet</servlet-name>
<!--servlet-class 是 Servlet 程序的全類名 -->
<servlet-class>com.wkl.servlet.HelloServlet</servlet-class>
</servlet>
<!--servlet-mapping 標籤給 servlet 程序配置訪問地址 -->
<servlet-mapping>
<!--servlet-name 標籤的作用是告訴服務器,我當前配置的地址給哪個 Servlet 程序使用 -->
<servlet-name>HelloServlet</servlet-name>
<!--url-pattern 標籤配置訪問地址 <br/>
/ 斜槓在服務器解析的時候,表示地址爲: http://ip:port/ 工程路徑 <br/>
/hello 表示地址爲: http://ip:port/ 工程路徑 /hello <br/>
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
訪問:
結果:
1.3:url 地址到 Servlet 程序的訪問
1.4:Servlet 的生命週期
1、執行 Servlet 構造器方法
2、執行 init 初始化方法
第一、二步,是在第一次訪問,的時候創建 Servlet 程序會調用。
3、執行 service 方法
第三步,每次訪問都會調用。
4、執行 destroy 銷燬方法
第四步,在 web 工程停止的時候調用。
1.5:GET 和 和 POST 請求的分發處理
package com.wkl.servlet;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* Description:
* Date: 2020/6/14 - 下午 9:10
* author: wangkanglu
* version: V1.0
*/
public class HelloServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init...");
}
@Override
public ServletConfig getServletConfig() {
System.out.println("config...");
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello Servlet 被訪問了");
// 類型轉換(因爲它有 getMethod() 方法)
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
// 獲取請求的方式
String method = httpServletRequest.getMethod();
if ("GET".equals(method)) {
doGet();
} else if ("POST".equals(method)) {
doPost();
}
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("destroy...");
}
}
1.6:通過繼承 HttpServlet 實現 Servlet 程序
一般在實際項目開發中,都是使用繼承 HttpServlet 類的方式去實現 Servlet 程序。
1、編寫一個類去繼承 HttpServlet 類
2、根據業務需要重寫 doGet 或 doPost 方法
3、到 web.xml 中的配置 Servlet 程序的訪問地址
package com.wkl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Description:
* Date: 2020/6/14 - 下午 9:10
* author: wangkanglu
* version: V1.0
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet的get方法被請求了。。。");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet的post方法被請求了。。。");
}
}
web.xml
<?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 標籤給 Tomcat 配置 Servlet 程序 -->
<servlet>
<!--servlet-name 標籤 Servlet 程序起一個別名(一般是類名) -->
<servlet-name>HelloServlet</servlet-name>
<!--servlet-class 是 Servlet 程序的全類名 -->
<servlet-class>com.wkl.servlet.HelloServlet</servlet-class>
</servlet>
<!--servlet-mapping 標籤給 servlet 程序配置訪問地址 -->
<servlet-mapping>
<!--servlet-name 標籤的作用是告訴服務器,我當前配置的地址給哪個 Servlet 程序使用 -->
<servlet-name>HelloServlet</servlet-name>
<!--url-pattern 標籤配置訪問地址 <br/>
/ 斜槓在服務器解析的時候,表示地址爲: http://ip:port/ 工程路徑 <br/>
/hello 表示地址爲: http://ip:port/ 工程路徑 /hello <br/>
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
1.7:可以通過idea快速設成servlet
1.8:Servlet 類的繼承體系 類的繼承體系
2:ServletConfig 類
ServletConfig 類從類名上來看,就知道是 Servlet 程序的配置信息類。
Servlet 程序和 ServletConfig 對象都是由 Tomcat 負責創建,我們負責使用。
Servlet 程序默認是第一次訪問的時候創建,ServletConfig 是每個 Servlet 程序創建時,就創建一個對應的 ServletConfig 對
象。
2.1:ServletConfig 類的三大作用 類的三大作用
1、可以獲取 Servlet 程序的別名 servlet-name 的值
2、獲取初始化參數 init-param
3、獲取 ServletContext 對象
web.xml 中的配置:
<?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 標籤給 Tomcat 配置 Servlet 程序 -->
<servlet>
<!--servlet-name 標籤 Servlet 程序起一個別名(一般是類名) -->
<servlet-name>HelloServlet</servlet-name>
<!--servlet-class 是 Servlet 程序的全類名 -->
<servlet-class>com.wkl.servlet.HelloServlet2</servlet-class>
<init-param>
<!-- 是參數名 -->
<param-name>username</param-name>
<!-- 是參數值 -->
<param-value>root</param-value>
</init-param>
</servlet>
<!--servlet-mapping 標籤給 servlet 程序配置訪問地址 -->
<servlet-mapping>
<!--servlet-name 標籤的作用是告訴服務器,我當前配置的地址給哪個 Servlet 程序使用 -->
<servlet-name>HelloServlet</servlet-name>
<!--url-pattern 標籤配置訪問地址 <br/>
/ 斜槓在服務器解析的時候,表示地址爲: http://ip:port/ 工程路徑 <br/>
/hello 表示地址爲: http://ip:port/ 工程路徑 /hello <br/>
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
public class HelloServlet2 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
// 1 、可以獲取 Servlet 程序的別名 servlet-name 的值
System.out.println("HelloServlet 程序的別名是:" + servletConfig.getServletName());
// 2 、獲取初始化參數 init-param
System.out.println(" 初始化參數 username 的值是;" + servletConfig.getInitParameter("username"));
System.out.println(" 初始化參數 url 的值是;" + servletConfig.getInitParameter("url"));
// 3 、獲取 ServletContext 對象
System.out.println(servletConfig.getServletContext());
}
3.ServletContext 類
3.1:什麼是 ServletContext?
1、ServletContext 是一個接口,它表示 Servlet 上下文對象
2、一個 web 工程,只有一個 ServletContext 對象實例。
3、ServletContext 對象是一個域對象。
4、ServletContext 是在 web 工程部署啓動的時候創建。在 web 工程停止的時候銷燬。
3.2:ServletContext 類的四個作用 類的四個作用
1、獲取 web.xml 中配置的上下文參數 context-param
2、獲取當前的工程路徑,格式: /工程路徑
3、獲取工程部署後在服務器硬盤上的絕對路徑
4、像 Map 一樣存取數據
代碼:
package com.wkl.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Description:
* Date: 2020/6/14 - 下午 9:10
* author: wangkanglu
* version: V1.0
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet的get方法被請求了。。。");
// 1 、獲取 web.xml 中配置的上下文參數 context-param
ServletContext context = getServletConfig().getServletContext();
String username = context.getInitParameter("username");
System.out.println("context-param 參數 username 的值是:" + username);
System.out.println("context-param 參數 password 的值是:" +
context.getInitParameter("password"));
// 2 、獲取當前的工程路徑,格式 : / 工程路徑
System.out.println(" 當前工程路徑:" + context.getContextPath());
// 3 、獲取工程部署後在服務器硬盤上的絕對路徑
/**
* / 斜槓被服務器解析地址爲 :http://ip:port/ 工程名 / 映射到 IDEA 代碼的 web 目錄 <br/>
*/
System.out.println(" 工程部署的路徑是:" + context.getRealPath("/"));
System.out.println(" 工程下 css 目錄的絕對路徑是:" + context.getRealPath("/css"));
System.out.println(" 工程下 imgs 目錄 1.jpg 的絕對路徑是:" + context.getRealPath("/imgs/1.jpg"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet的post方法被請求了。。。");
}
}
web.xml:
<!--context-param 是上下文參數 ( 它屬於整個 web 工程 )-->
<context-param>
<param-name>username</param-name>
<param-value>context</param-value>
</context-param>
<!--context-param 是上下文參數 ( 它屬於整個 web 工程 )-->
<context-param>
<param-name>password</param-name>
<param-value>root</param-value>
</context-param>
ServletContext 像 Map 一樣存取數據:
ContextServlet1 代碼:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
// 獲取 ServletContext 對象
ServletContext context = getServletContext();
System.out.println(context);
System.out.println(" 保存之前: Context1 取 獲取 key1 的值是:"+ context.getAttribute("key1"));
context.setAttribute("key1", "value1");
System.out.println("Context1 中獲取域數據 key1 的值是:"+ context.getAttribute("key1"));
}
4:HTTP 協議
4.1: 什麼是 HTTP 協議 協議
什麼是協議?
協議是指雙方,或多方,相互約定好,大家都需要遵守的規則,叫協議。
所謂 HTTP 協議,就是指,客戶端和服務器之間通信時,發送的數據,需要遵守的規則,叫 HTTP 協議。
HTTP 協議中的數據又叫報文。
4.2:請求的 HTTP 協議格式 協議格式
客戶端給服務器發送數據叫請求。
服務器給客戶端回傳數據叫響應。
請求又分爲 GET 請求,和 POST 請求兩種
1:get
2:post
3:響應
5:HttpServletRequest 類
5.1:HttpServletRequest 類有什麼作用。
每次只要有請求進入 Tomcat 服務器,Tomcat 服務器就會把請求過來的 HTTP 協議信息解析好封裝到 Request 對象中。然後傳遞到 service 方法(doGet 和 doPost)中給我們使用。我們可以通過 HttpServletRequest 對象,獲取到所有請求的信息。
5.2:HttpServletRequest 類的常用方法
- getRequestURI() 獲取請求的資源路徑
- getRequestURL() 獲取請求的統一資源定位符(絕對路徑)
- getRemoteHost() 獲取客戶端的 ip 地址
- getHeader() 獲取請求頭
- getParameter() 獲取請求的參數
- getParameterValues() 獲取請求的參數(多個值的時候使用)
- getMethod() 獲取請求的方式 GET 或 POST
- setAttribute(key, value); 設置域數據
- getAttribute(key); 獲取域數據
- getRequestDispatcher() 獲取請求轉發對象
package com.wkl.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Description:
* Date: 2020/6/14 - 下午 9:10
* author: wangkanglu
* version: V1.0
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet的get方法被請求了。。。");
// i.getRequestURI() 獲取請求的資源路徑
System.out.println("URI => " + req.getRequestURI());
// ii.getRequestURL() 獲取請求的統一資源定位符(絕對路徑)
System.out.println("URL => " + req.getRequestURL());
// iii.getRemoteHost() 獲取客戶端的 ip 地址
/**
* 在 IDEA 中,使用 localhost 訪問時,得到的客戶端 ip 地址是 ===>>> 127.0.0.1<br/>
* 在 IDEA 中,使用 127.0.0.1 訪問時,得到的客戶端 ip 地址是 ===>>> 127.0.0.1<br/>
* 在 IDEA 中,使用 真實 ip 訪問時,得到的客戶端 ip 地址是 ===>>> 真實的客戶端 ip 地址 <br/>
*/
System.out.println("端 客戶端 ip 址 地址 => " + req.getRemoteHost());
// iv.getHeader() 獲取請求頭
System.out.println(" 請求頭 User-Agent ==>> " + req.getHeader("User-Agent"));
// vii.getMethod() 獲取請求的方式 GET 或 POST
System.out.println("式 請求的方式 ==>> " + req.getMethod());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet的post方法被請求了。。。");
}
}
5.3:如何獲取請求參數
package com.wkl.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Description:
* Date: 2020/6/14 - 下午 9:10
* author: wangkanglu
* version: V1.0
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet的get方法被請求了。。。");
// 獲取請求參數
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet的post方法被請求了。。。");
}
}
5.4:doGet 請求的中文亂碼解決: 請求的中文亂碼解決:
// 獲取請求參數
String username = req.getParameter("username");
//1 先以 iso8859-1 進行編碼
//2 再以 utf-8 進行解碼
username = new String(username.getBytes("iso-8859-1"), "UTF-8");
5.5:POST 請求的中文亂碼解決
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 設置請求體的字符集爲 UTF-8 ,從而解決 post 請求的中文亂碼問題
req.setCharacterEncoding("UTF-8");
System.out.println("-------------doPost------------");
// 獲取請求參數
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println(" 用戶名:" + username);
System.out.println(" 密碼:" + password);
System.out.println(" 興趣愛好:" + Arrays.asList(hobby));
}
5.6:請求轉發
什麼是請求的轉發?
請求轉發是指,服務器收到請求後,從一次資源跳轉到另一個資源的操作叫請求轉發。
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 獲取請求的參數(辦事的材料)查看
String username = req.getParameter("username");
System.out.println("在 在 Servlet1 (櫃檯 1 )中查看參數(材料):" + username);
// 給材料 蓋一個章,並傳遞到 Servlet2 (櫃檯 2 )去查看
req.setAttribute("key1", " 櫃檯 1 的章");
// 問路: Servlet2 (櫃檯 2 )怎麼走
/**
* 請求轉發必須要以斜槓打頭, / 斜槓表示地址爲: http://ip:port/ 工程名 / , 映射到 IDEA 代碼的 web 目錄
<br/>
*
*/
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
// 走向 Sevlet2 (櫃檯 2 )
requestDispatcher.forward(req, resp);
}
5.7:Web 中的相對路徑和絕對路徑
在 javaWeb 中,路徑分爲相對路徑和絕對路徑兩種:
相對路徑是:
. 表示當前目錄
.. 表示上一級目錄
資源名 表示當前目錄/資源名
絕對路徑:
http://ip:port/工程路徑/資源路徑
在實際開發中,路徑都使用絕對路徑,而不簡單的使用相對路徑。
1、絕對路徑
2、base+相對
5.8:web 中 / 斜槓的不同意義
在 web 中 / 斜槓 是一種絕對路徑。
/ 斜槓 如果被瀏覽器解析,得到的地址是:http://ip:port/
<a href="/">斜槓</a>
/ 斜槓 如果被服務器解析,得到的地址是:http://ip:port/工程路徑
1、<url-pattern>/servlet1</url-pattern>
2、servletContext.getRealPath(“/”);
3、request.getRequestDispatcher(“/”);
6:HttpServletResponse 類
6.1:HttpServletResponse 類的作用
HttpServletResponse 類和 HttpServletRequest 類一樣。每次請求進來,Tomcat 服務器都會創建一個 Response 對象傳
遞給 Servlet 程序去使用。HttpServletRequest 表示請求過來的信息,HttpServletResponse 表示所有響應的信息,
我們如果需要設置返回給客戶端的信息,都可以通過 HttpServletResponse 對象來進行設置
6.2:兩個輸出流的說明。
- 字節流 getOutputStream(); 常用於下載(傳遞二進制數據)
- 字符流 getWriter(); 常用於回傳字符串(常用)
兩個流同時只能使用一個。
使用了字節流,就不能再使用字符流,反之亦然,否則就會報錯。
6.3:如何往客戶端回傳數據
要求 : 往客戶端回傳 字符串 數據。
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.write("我知道了,回去吧");
}
6.4:響應的亂碼解決
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 設置服務器字符集爲 UTF-8
resp.setCharacterEncoding("UTF-8");
// 通過響應頭,設置瀏覽器也使用 UTF-8 字符集
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("我知道了,回去吧");
}
相比較上邊的,更推薦:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 它會同時設置服務器和客戶端都使用 UTF-8 字符集,還設置了響應頭
// 此方法一定要在獲取流對象之前調用纔有效
resp.setContentType("text/html; charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("我知道了,回去吧");
}
6.5:請求重定向-resp.sendRedirect("http://localhost:8080");
請求重定向,是指客戶端給服務器發請求,然後服務器告訴客戶端說。我給你一些地址。你去新地址訪問。叫請求重定向(因爲之前的地址可能已經被廢棄)。
請求重定向的第一種方案:
// 設置響應狀態碼 302 ,表示重定向,(已搬遷)
resp.setStatus(302);
// 設置響應頭,說明 新的地址在哪裏
resp.setHeader("Location", "http://localhost:8080");
請求重定向的第二種方案(推薦使用):
resp.sendRedirect("http://localhost:8080");
7:HTTP Request Header 請求頭參數說明
8:HTTP Request Header 請求頭參數說明
9:Servlet生命週期
從生成到銷燬都是由容器完成的
1:調用servlet構造器,生成Servlet實例
2:調用init方法初始化
3:調用servlet的servise方法進行業務邏輯處理
4:調用destory方法進行實例的銷燬,該操作一般在服務關閉時自動調用