一、Servlet
1. 什麼是Servlet
- Servlet 是 JavaEE 規範之一,規範就是介面
- Servlet 就 JavaWeb 三大元件之一,三大元件分別是:Servlet 程式、Filter 過濾器、Listener 監聽器
- Servlet 是執行在伺服器上的一個 java 小程式,它可以接收客戶端傳送過來的請求,並響應資料給客戶端
2. 手動實現Servlet程式
首先還是在IDEA中建立一個對應的模組,具體看上一個,結果如下
- 編寫一個類去實現 Servlet 介面
- 實現 service 方法,處理請求,並響應資料
- 到 web.xml 中去配置 servlet 程式的訪問地址
1. 首先在src下建立一個java檔案,實現Servlet介面,重寫方法
現在先看Servlet(),其他的省略
package com.md.servlet;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author MD
* @create 2020-07-24 14:44
*/
public class HelloServlet implements Servlet {
/**
* service方法專門用來處理請求和響應的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Service方法");
}
}
2. 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程式起一個別名,通常是類名-->
<servlet-name>HelloServlet</servlet-name>
<!--servlet程式全類名-->
<servlet-class>com.md.servlet.HelloServlet</servlet-class>
</servlet>
<!--servlet-mapping標籤給servlet程式配置訪問地址-->
<servlet-mapping>
<!--servlet-name 作用是告訴伺服器,當前配置的地址給那個Servlet程式使用-->
<servlet-name>HelloServlet</servlet-name>
<!-- 配置訪問的地址 http://ip:port/hello , 可以自定義-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
當訪問地址http://localhost:8080/hello時,可以看到輸出語句了
3. url地址到Servlet程式
4. Servlet的宣告週期
- 執行 Servlet 構造器方法
- 執行 init 初始化方法
第一、二步,是在第一次訪問的時候建立 Servlet 程式會呼叫
- 執行 service 方法 每次訪問都會呼叫
- 執行 destroy 銷燬方法 在 web 工程停止的時候呼叫
package com.md.servlet;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author MD
* @create 2020-07-24 14:44
*/
public class HelloServlet implements Servlet {
public HelloServlet() {
System.out.println("1 構造器方法");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2 init初始化方法");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* service方法專門用來處理請求和響應的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3. service方法");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("4 destroy銷燬方法");
}
}
// 結果如下:
//1 構造器方法
//2 init初始化方法 只有第一次訪問執行
//3. service方法
//3. service方法 每次重新整理都會執行這個方法
//4 destroy銷燬方法 關閉Tomcat會執行這個方法
4. GET 和 POST 請求的分發處理
此時請求的話無論執行get或者是post請求都會執行service()方法,這樣不方便,所以做了如下的改進,
其他方法省略,主要看service()
public class HelloServlet implements Servlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3. service方法");
// 1. 型別轉換
HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
// 2. 獲取請求的方式
String method = httpServletRequest.getMethod();
// 3. 處理不同的請求
if ("GET".equals(method)){
doGet();
}else if ("POST".equals(method)){
doPost();
}
}
/**
* 做get請求的操作
*/
public void doGet(){
System.out.println("get請求正在操作");
}
/**
* 做post請求的操作
*/
public void doPost(){
System.out.println("post請求正在操作");
}
}
5. 通過繼承 HttpServlet 實現 Servlet 程式
一般在實際專案開發中,都是使用繼承 HttpServlet 類的方式去實現 Servlet 程式
- 編寫一個類去繼承 HttpServlet 類
- 根據業務需要重寫 doGet 或 doPost 方法
- 到 web.xml 中的配置 Servlet 程式的訪問地址
Servle類中的程式碼
package com.md.servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author MD
* @create 2020-07-24 15:25
*/
public class HelloServlet2 extends HttpServlet {
/**
* get請求時呼叫
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet2 --- get");
}
/**
* post請求時呼叫
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet2 --- post");
}
}
在web.xml中的配置
<servlet>
<servlet-name>HelloServlet2</servlet-name>
<servlet-class>com.md.servlet.HelloServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
6. 使用IDEA建立Servlet程式
方便,快捷
配置Servlet資訊
最後在web.xml中新增資訊就可以了
<servlet>
<servlet-name>HelloServlet3</servlet-name>
<servlet-class>com.md.servlet.HelloServlet3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet3</servlet-name>
<url-pattern>/hello3</url-pattern>
</servlet-mapping>
7. Servlet類的繼承體系
二、ServletConfig類
ServletConfig 是 Servlet 程式的配置資訊類
Servlet 程式和 ServletConfig 物件都是由 Tomcat 負責建立,我們負責使用
Servlet 程式預設是第一次訪問的時候建立,ServletConfig 是每個 Servlet 程式建立時,就建立一個對應的 ServletConfig 物件
1. ServletConfig 類的三大作用
- 可以獲取 Servlet 程式的別名 servlet-name 的值
- 獲取初始化引數 init-param
- 獲取 ServletContext 物件
首先還是在web.xml中進行配置
<!--servlet標籤給Tomcat配置Servlet程式-->
<servlet>
<!--給servlet程式起一個別名,通常是類名-->
<servlet-name>HelloServlet</servlet-name>
<!--servlet程式全類名-->
<servlet-class>com.md.servlet.HelloServlet</servlet-class>
<!--初始化引數-->
<init-param>
<!--引數名-->
<param-name>url</param-name>
<!--引數值-->
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</init-param>
<!--可以配置多個-->
<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>
<!-- 配置訪問的地址 http://ip:port/hello , 可以自定義-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
Servlet中的程式碼:
其他方法就省略了,主要看這個就行,啟動Tomcat之後在位址列輸入地址http://localhost:8080/hello時,可以看到輸出語句了,
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2 init初始化方法");
// 1. 可以獲取Servlet程式的別名servlet-name的值
System.out.println("HelloServlet的別名是:"+servletConfig.getServletName());
//HelloServlet的別名是:HelloServlet
// 2. 獲取初始化引數init-param
System.out.println("初始化引數url:"+servletConfig.getInitParameter("url"));
//初始化引數url:jdbc:mysql://localhost:3306/test
System.out.println("初始化引數username:"+servletConfig.getInitParameter("username"));
//初始化引數username:root
// 3. 獲取ServletContext物件
System.out.println(servletConfig.getServletContext());
//org.apache.catalina.core.ApplicationContextFacade@521f9e31
}
注意:
重寫init方法裡面一定要呼叫父類的init(config)操作
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println("重寫的init方法");
}
三、ServletContext 類
1. 什麼是 ServletContext?
- ServletContext 是一個介面,它表示 Servlet 上下文物件
- 一個 web 工程,只有一個 ServletContext 物件例項
- ServletContext 物件是一個域物件
- ServletContext 是在 web 工程部署啟動的時候建立。在 web 工程停止的時候銷燬
什麼是域物件?
域物件,是可以像 Map 一樣存取資料的物件,叫域物件。
這裡的域指的是存取資料的操作範圍,整個 web 工程
存資料 | 取資料 | 刪除資料 | |
---|---|---|---|
Map | put() | get() | remove() |
域物件 | setAttribute() | getAttribute() | removeAttribute() |
2. ServletContext 類的四個作用
- 獲取 web.xml 中配置的上下文引數 context-param
- 獲取當前的工程路徑,格式:/工程路徑
- 獲取工程部署後在伺服器硬碟上的絕對路徑
- 像 Map 一樣存取資料
在ContextServlet類中,
package com.md.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;
/**
* @author MD
* @create 2020-07-24 16:17
*/
public class ContextServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 獲取web.xml中配置的上下文引數
ServletContext context = getServletConfig().getServletContext();
String username = context.getInitParameter("username");
System.out.println("context-param中引數username的值為:"+username);
System.out.println("context-param中引數pwd的值為:"+context.getInitParameter("pwd"));
// 2. 獲取當前工程的路徑
System.out.println("當前工程的路徑:"+context.getContextPath());
// 3. 獲取工程部署後在伺服器磁碟上的絕對路徑,對映到IDEA程式碼的web目錄,
// 相當於直接到了web目錄那,如果使用web目錄下的其他檔案,直接/目錄名就可以
System.out.println("工程部署路徑:"+context.getRealPath("/"));
// 工程的絕對路徑:E:\Java\code\JavaWeb\out\artifacts\03_web_war_exploded\
// 比如web下有css目錄和imgs目錄
System.out.println(context.getRealPath("/css"));
System.out.println(context.getRealPath("/imgs/1.jpg"));
}
}
對應的配置檔案web.xml
這個是直接在<web-app標籤下,而不是某個<servlet標籤下,
<!--context-param 是上下文引數,屬於整個的Web工程-->
<context-param>
<param-name>username</param-name>
<param-value>context</param-value>
</context-param>
<context-param>
<param-name>pwd</param-name>
<param-value>123456</param-value>
</context-param>
<servlet>
<servlet-name>ContextServlet</servlet-name>
<servlet-class>com.md.servlet.ContextServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ContextServlet</servlet-name>
<url-pattern>/context</url-pattern>
</servlet-mapping>
ServletContext 像Map一樣存取資料,直接可以這樣
在ContextServlet1中,這個對應的web.xml就省略了
package com.md.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;
/**
* @author MD
* @create 2020-07-24 16:40
*/
public class ContextServlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 通過getServletContext()直接獲取ServletContext物件
ServletContext context = getServletContext();
System.out.println("儲存前:"+context.getAttribute("key1")); // null
// 2. 設定值
context.setAttribute("key1","value1");
// 3. 獲取值
System.out.println("儲存後:"+context.getAttribute("key1")); //value1
//
}
}
也可以在不同的Service中獲取的到,因為是域物件
這個是整個web都可以獲取到這個值,通過ContextServlet2也是可以獲取到的
public class ContextServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 由於context是域物件,整個web只有一個,所以這個獲取的和ContextServlet1裡的是同一個
ServletContext context = getServletContext();
// 只要ContextServlet1執行過,設定過這個值,那麼這個就可以獲取到值
System.out.println(context.getAttribute("key1")); //value1
}
}