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