Servlet和Spring?MVC的區(qū)別及使用說明
前言
在 Java Web 開發(fā)中,Servlet 和 Spring MVC 是兩個重要的技術(shù)。Servlet 是 Java Web 的基礎(chǔ)組件,而 Spring MVC 是一個高級 Web 框架,建立在 Servlet 的基礎(chǔ)之上,提供了強大的功能和易用性。
這篇文章將從定義、原理、功能對比、應(yīng)用場景等多個方面,詳細介紹 Servlet 和 Spring MVC,并解析它們的區(qū)別與聯(lián)系。
一、什么是 Servlet
1. 定義
Servlet 是 Java Web 應(yīng)用的核心組件,是一種運行在服務(wù)器上的小程序,專門用于處理客戶端的 HTTP 請求并生成動態(tài)響應(yīng)。
Servlet 是 Java EE 規(guī)范的一部分,定義了如何通過 Java 編寫服務(wù)器端的 Web 應(yīng)用。
2. 工作原理
Servlet 的核心思想是基于 請求-響應(yīng)模型:
- 客戶端(通常是瀏覽器)發(fā)送 HTTP 請求。
- Web 容器(如 Tomcat)將請求路由到 Servlet。
- Servlet 處理請求,執(zhí)行邏輯,生成并返回 HTTP 響應(yīng)。
3. 核心組件
HttpServletRequest:表示客戶端的請求對象,包含請求的所有信息(如請求參數(shù)、請求頭等)。HttpServletResponse:表示服務(wù)器的響應(yīng)對象,包含響應(yīng)的所有信息(如響應(yīng)頭、響應(yīng)狀態(tài)碼、響應(yīng)體等)。
4. Servlet 的生命周期
Servlet 的生命周期由 Web 容器管理,包含以下幾個階段:
- 初始化:
- Servlet 第一次被訪問時,容器會加載 Servlet 類并調(diào)用
init()方法完成初始化。
- Servlet 第一次被訪問時,容器會加載 Servlet 類并調(diào)用
- 服務(wù):
- 每次請求都會調(diào)用
service()方法,根據(jù)請求的 HTTP 方法(GET、POST 等),調(diào)用對應(yīng)的doGet()或doPost()方法。
- 每次請求都會調(diào)用
- 銷毀:
- 在服務(wù)器關(guān)閉或卸載 Servlet 時,調(diào)用
destroy()方法釋放資源。
- 在服務(wù)器關(guān)閉或卸載 Servlet 時,調(diào)用
5. 示例代碼
以下是一個簡單的 Servlet 示例:
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 設(shè)置響應(yīng)內(nèi)容類型
resp.setContentType("text/html");
// 返回簡單的 HTML 響應(yīng)
resp.getWriter().write("<h1>Hello, Servlet!</h1>");
}
}二、什么是 Spring MVC
1. 定義
Spring MVC 是基于 Spring 框架的一個 Web 開發(fā)模塊,提供了 MVC(Model-View-Controller) 設(shè)計模式的完整實現(xiàn)。
它簡化了 Web 應(yīng)用開發(fā),提供了對請求映射、參數(shù)綁定、視圖解析等功能的強大支持。
2. 核心思想
Spring MVC 通過 DispatcherServlet(前端控制器)將所有請求統(tǒng)一攔截并分發(fā)給具體的處理器(Controller),然后結(jié)合視圖(View)生成響應(yīng)。
3. Spring MVC 的架構(gòu)
Spring MVC 的核心組件:
- DispatcherServlet:
- 前端控制器,負責(zé)接收和分發(fā)所有 HTTP 請求。
- HandlerMapping:
- 請求映射器,將 URL 映射到具體的控制器方法。
- Controller:
- 業(yè)務(wù)處理器,負責(zé)執(zhí)行具體的邏輯。
- ModelAndView:
- 數(shù)據(jù)模型和視圖對象,用于封裝業(yè)務(wù)數(shù)據(jù)和返回的視圖信息。
- ViewResolver:
- 視圖解析器,將邏輯視圖名解析為物理視圖(如 JSP、Thymeleaf 頁面)。
- View:
- 負責(zé)生成最終的響應(yīng)內(nèi)容(HTML、JSON 等)。
4. 工作流程
- 客戶端發(fā)送請求。
- DispatcherServlet 接收請求并委托給 HandlerMapping 找到對應(yīng)的 Controller 方法。
- Controller 方法處理請求,返回數(shù)據(jù)(Model)和視圖(View)。
- ViewResolver 將邏輯視圖名解析為物理視圖。
- 將數(shù)據(jù)渲染到視圖,生成響應(yīng)并返回給客戶端。
5. 示例代碼
以下是一個簡單的 Spring MVC 示例:
Controller 類:
@Controller
public class HelloController {
@GetMapping("/hello")
@ResponseBody
public String sayHello(@RequestParam String name) {
return "<h1>Hello, " + name + "!</h1>";
}
}三、Servlet 和 Spring MVC 的區(qū)別
| 對比維度 | Servlet | Spring MVC |
|---|---|---|
| 定位 | Java Web 開發(fā)的基礎(chǔ)技術(shù)。 | 基于 Servlet 構(gòu)建的高級 Web 框架。 |
| 設(shè)計思想 | 直接基于 HTTP 請求-響應(yīng)模型。 | 基于 MVC(Model-View-Controller)設(shè)計模式。 |
| 開發(fā)復(fù)雜度 | 較高,需要手動解析請求和生成響應(yīng)。 | 較低,提供自動化功能(如參數(shù)綁定、視圖解析)。 |
| 功能豐富度 | 功能較少,需要自行實現(xiàn)擴展(如請求映射、數(shù)據(jù)綁定)。 | 功能豐富,內(nèi)置請求映射、表單驗證、異常處理等功能。 |
| 請求映射 | 靜態(tài) URL 映射,直接通過 Web 容器配置路由。 | 靈活的動態(tài)映射,支持正則表達式、RESTful URL 等。 |
| 視圖支持 | 需要手動拼接 HTML 或 JSP 頁面。 | 支持多種視圖技術(shù)(JSP、Thymeleaf、JSON 等)。 |
| 表單驗證 | 需要手動校驗參數(shù)。 | 提供注解式校驗(如 @Valid 和 @NotNull)。 |
| 異常處理 | 需要在代碼中顯式捕獲異常并處理。 | 提供全局異常處理機制(如 @ControllerAdvice)。 |
| 擴展性 | 擴展性有限,需通過 Filter 或 Listener 實現(xiàn)一些通用功能。 | 提供攔截器機制,支持 AOP 和依賴注入,擴展性極強。 |
| 學(xué)習(xí)曲線 | 入門簡單,但復(fù)雜項目開發(fā)難度大。 | 需要學(xué)習(xí) Spring 框架基礎(chǔ),初學(xué)者學(xué)習(xí)曲線稍陡。 |
| 適用場景 | 小型項目或需要直接操作 HTTP 請求的場景。 | 中大型項目,特別是需要高擴展性和快速開發(fā)的場景。 |
四、Servlet 和 Spring MVC 的聯(lián)系
盡管 Servlet 和 Spring MVC 在定位和功能上有所不同,但它們之間有著密切的聯(lián)系:
1. 基于 Servlet 構(gòu)建
- Spring MVC 是構(gòu)建在 Servlet 基礎(chǔ)之上的高級框架。
- Spring MVC 的核心組件 DispatcherServlet 本質(zhì)上是一個 Servlet,它負責(zé)接收和分發(fā)請求。
2. Servlet 是 Spring MVC 的基礎(chǔ)
- Spring MVC 使用 Servlet 來處理 HTTP 請求,但屏蔽了復(fù)雜的細節(jié),例如參數(shù)解析、請求分發(fā)等。
3. Spring MVC 依賴 Servlet 容器
- Spring MVC 必須運行在支持 Servlet 的 Web 容器(如 Tomcat、Jetty)中。
- Servlet 容器負責(zé)加載和管理 DispatcherServlet。
五、什么時候選擇 Servlet 或 Spring MVC
1. 使用 Servlet
- 適合小型項目,功能簡單。
- 希望深入理解 Java Web 的底層原理。
- 不需要復(fù)雜的框架支持,能夠手動實現(xiàn)請求處理和響應(yīng)。
2. 使用 Spring MVC
- 適合中大型項目,功能復(fù)雜。
- 需要高效開發(fā)、靈活配置和良好的擴展能力。
- 希望享受 Spring 框架的生態(tài)系統(tǒng)(如 Spring Data、Spring Security 等)。
示例代碼
假設(shè)我們需要構(gòu)建一個簡單的 Web 服務(wù):
- 請求路徑:
http://localhost:8080/hello?name=Tom - 返回內(nèi)容:
Hello, Tom!
完整 Servlet 實現(xiàn)
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 注解映射路徑 "/hello"
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
// 初始化 Servlet(只執(zhí)行一次)
@Override
public void init() throws ServletException {
super.init();
System.out.println("Servlet 初始化完成!");
}
// 處理 GET 請求
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 設(shè)置響應(yīng)內(nèi)容類型
resp.setContentType("text/html;charset=UTF-8");
// 獲取請求參數(shù)
String name = req.getParameter("name");
if (name == null || name.isEmpty()) {
name = "World"; // 默認值
}
// 返回動態(tài)響應(yīng)
resp.getWriter().write("<h1>Hello, " + name + "!</h1>");
}
// 銷毀 Servlet(只執(zhí)行一次,用于釋放資源)
@Override
public void destroy() {
super.destroy();
System.out.println("Servlet 已被銷毀!");
}
}代碼優(yōu)化點
- 注解簡化配置:
- 使用
@WebServlet注解代替?zhèn)鹘y(tǒng)的web.xml配置。
- 使用
- 默認參數(shù)處理:
- 如果用戶未傳遞參數(shù),返回默認的 "World"。
- 字符編碼:
- 通過
resp.setContentType("text/html;charset=UTF-8")設(shè)置字符編碼,防止中文亂碼。
- 通過
- 日志輸出:
- 在
init()和destroy()方法中添加日志信息,便于調(diào)試。
- 在
如何運行
- 將代碼打包為
.war文件,并部署到 Tomcat。 - 訪問 URL:
http://localhost:8080/hello?name=Tom。 - 返回結(jié)果:
Hello, Tom!
Spring MVC 實現(xiàn)
Spring MVC 的實現(xiàn)更加簡潔且功能強大。
以下代碼實現(xiàn)相同的功能。
Controller 類
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
// 處理 GET 請求,映射路徑 "/hello"
@GetMapping("/hello")
@ResponseBody
public String sayHello(@RequestParam(name = "name", required = false, defaultValue = "World") String name) {
// 返回動態(tài)內(nèi)容
return "<h1>Hello, " + name + "!</h1>";
}
}Spring Boot 主類
如果使用 Spring Boot 構(gòu)建項目,可以通過以下代碼快速啟動:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringMvcApplication {
public static void main(String[] args) {
SpringApplication.run(SpringMvcApplication.class, args);
}
}代碼優(yōu)化點
- 注解驅(qū)動開發(fā):
- 使用
@Controller和@GetMapping注解處理請求,簡化了配置。
- 使用
- 自動參數(shù)綁定:
- 使用
@RequestParam自動從請求中提取參數(shù),同時設(shè)置默認值。
- 使用
- 自動響應(yīng):
- 通過
@ResponseBody將返回的字符串直接作為響應(yīng)體,省去了手動處理HttpServletResponse。
- 通過
- Spring Boot 快速啟動:
- 使用 Spring Boot 自動化配置,無需單獨部署到 Tomcat。
如何運行
- 將代碼保存為一個 Spring Boot 應(yīng)用。
- 運行主類
SpringMvcApplication。 - 訪問 URL:
http://localhost:8080/hello?name=Tom。 - 返回結(jié)果:
Hello, Tom!
示例場景擴展
為了更好地理解 Servlet 和 Spring MVC 的應(yīng)用場景,我們再擴展一個功能:根據(jù)用戶輸入返回 JSON 數(shù)據(jù)。
Servlet 示例(返回 JSON 數(shù)據(jù))
import com.google.gson.Gson;
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.util.HashMap;
import java.util.Map;
@WebServlet("/json")
public class JsonServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 設(shè)置響應(yīng)類型為 JSON
resp.setContentType("application/json;charset=UTF-8");
// 獲取請求參數(shù)
String name = req.getParameter("name");
if (name == null || name.isEmpty()) {
name = "World";
}
// 構(gòu)造響應(yīng)數(shù)據(jù)
Map<String, String> responseData = new HashMap<>();
responseData.put("message", "Hello, " + name + "!");
// 將數(shù)據(jù)轉(zhuǎn)換為 JSON
String jsonResponse = new Gson().toJson(responseData);
// 返回 JSON 響應(yīng)
resp.getWriter().write(jsonResponse);
}
}Spring MVC 示例(返回 JSON 數(shù)據(jù))
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class JsonController {
@GetMapping("/json")
public Map<String, String> sayHello(@RequestParam(name = "name", required = false, defaultValue = "World") String name) {
// 構(gòu)造響應(yīng)數(shù)據(jù)
Map<String, String> response = new HashMap<>();
response.put("message", "Hello, " + name + "!");
return response;
}
}doGet()、doPost() 和 service() 的區(qū)別
| 特性 | service() | doGet() | doPost() |
|---|---|---|---|
| 定位 | 通用方法,用于處理所有 HTTP 請求類型。 | 專門用于處理 HTTP GET 請求。 | 專門用于處理 HTTP POST 請求。 |
| 調(diào)用方式 | 由 Web 容器直接調(diào)用。 | 由 service() 方法根據(jù) HTTP 請求方法分發(fā)調(diào)用。 | 由 service() 方法根據(jù) HTTP 請求方法分發(fā)調(diào)用。 |
| 實現(xiàn)目的 | 自動分發(fā)請求到對應(yīng)的 doXxx() 方法。 | 處理只讀請求(如查詢數(shù)據(jù))。 | 處理數(shù)據(jù)提交(如表單、文件上傳)。 |
| 開發(fā)者重寫 | 很少被重寫,通常由 Web 容器托管。 | 常被重寫以處理 GET 請求。 | 常被重寫以處理 POST 請求。 |
| 請求語義 | 無特定語義,作為分發(fā)入口。 | 遵循 HTTP GET 請求的語義(冪等)。 | 遵循 HTTP POST 請求的語義(非冪等)。 |
總結(jié)
區(qū)別
- Servlet 是 Java Web 開發(fā)的基礎(chǔ)技術(shù),提供了直接操作 HTTP 請求和響應(yīng)的能力,適合小型項目或需要深入了解底層原理的場景。
- Spring MVC 是一個基于 Servlet 的高級 Web 框架,提供了大量的自動化功能和開發(fā)便利性,適合中大型項目。
聯(lián)系
- Spring MVC 是建立在 Servlet 技術(shù)之上的框架,它通過 DispatcherServlet 實現(xiàn)請求的接收和分發(fā)。
- Servlet 是 Spring MVC 的基礎(chǔ),但 Spring MVC 封裝了許多底層細節(jié),使開發(fā)更高效。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java Config下的Spring Test幾種方式實例詳解
這篇文章主要介紹了Java Config下的Spring Test方式實例代碼的相關(guān)資料,需要的朋友可以參考下2017-05-05
SpringBoot使用Scheduling實現(xiàn)定時任務(wù)的示例代碼
Spring Boot提供了一種方便的方式來實現(xiàn)定時任務(wù),即使用Spring的@Scheduled注解,通過在方法上添加@Scheduled注解,我們可以指定方法在何時執(zhí)行,本文我們就給大家介紹一下SpringBoot如何使用Scheduling實現(xiàn)定時任務(wù),需要的朋友可以參考下2023-08-08
SpringCloud實現(xiàn)全鏈路灰度發(fā)布的示例詳解
灰度發(fā)布是指在軟件或服務(wù)發(fā)布過程中,將新版本的功能或服務(wù)以較小的比例引入到生產(chǎn)環(huán)境中,僅向部分用戶或節(jié)點提供新功能的一種發(fā)布策略,下面我們就來學(xué)習(xí)一下SpringCloud如何實現(xiàn)全鏈路灰度發(fā)布2023-11-11
springboot調(diào)用webservice-soap接口的實現(xiàn)
接口協(xié)議目前廣泛使用的有http協(xié)議和RPC協(xié)議和webservice,本文主要介紹了springboot調(diào)用webservice-soap接口的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-03-03
Spring Boot學(xué)習(xí)入門之AOP處理請求詳解
AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預(yù)編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術(shù),下面這篇文章主要給大家介紹了關(guān)于Spring Boot學(xué)習(xí)入門之AOP處理請求的相關(guān)資料,需要的朋友可以參考下。2017-09-09

