Servlet和Spring MVC的区别及使用说明

 更新时间:2025年01月21日 14:55:17   作者:qq_44199605  
这篇文章详细介绍了Servlet和SpringMVC的基本概念、工作原理、功能对比和应用场景,Servlet是JavaWeb开发的基础,而SpringMVC是一个基于Servlet的高级框架,提供了更强大的功能和易用性,文章通过定义、原理和示例代码,帮助读者理解这两个技术的区别与联系

前言

在 Java Web 开发中,Servlet 和 Spring MVC 是两个重要的技术。Servlet 是 Java Web 的基础组件,而 Spring MVC 是一个高级 Web 框架,建立在 Servlet 的基础之上,提供了强大的功能和易用性。

这篇文章将从定义、原理、功能对比、应用场景等多个方面,详细介绍 Servlet 和 Spring MVC,并解析它们的区别与联系。

一、什么是 Servlet

1. 定义

Servlet 是 Java Web 应用的核心组件,是一种运行在服务器上的小程序,专门用于处理客户端的 HTTP 请求并生成动态响应。

Servlet 是 Java EE 规范的一部分,定义了如何通过 Java 编写服务器端的 Web 应用。

2. 工作原理

Servlet 的核心思想是基于 请求-响应模型

  1. 客户端(通常是浏览器)发送 HTTP 请求。
  2. Web 容器(如 Tomcat)将请求路由到 Servlet。
  3. Servlet 处理请求,执行逻辑,生成并返回 HTTP 响应。

3. 核心组件

  • HttpServletRequest:表示客户端的请求对象,包含请求的所有信息(如请求参数、请求头等)。
  • HttpServletResponse:表示服务器的响应对象,包含响应的所有信息(如响应头、响应状态码、响应体等)。

4. Servlet 的生命周期

Servlet 的生命周期由 Web 容器管理,包含以下几个阶段:

  1. 初始化
    • Servlet 第一次被访问时,容器会加载 Servlet 类并调用 init() 方法完成初始化。
  2. 服务
    • 每次请求都会调用 service() 方法,根据请求的 HTTP 方法(GET、POST 等),调用对应的 doGet()doPost() 方法。
  3. 销毁
    • 在服务器关闭或卸载 Servlet 时,调用 destroy() 方法释放资源。

5. 示例代码

以下是一个简单的 Servlet 示例:

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 设置响应内容类型
        resp.setContentType("text/html");
        // 返回简单的 HTML 响应
        resp.getWriter().write("<h1>Hello, Servlet!</h1>");
    }
}

二、什么是 Spring MVC

1. 定义

Spring MVC 是基于 Spring 框架的一个 Web 开发模块,提供了 MVC(Model-View-Controller) 设计模式的完整实现。

它简化了 Web 应用开发,提供了对请求映射、参数绑定、视图解析等功能的强大支持。

2. 核心思想

Spring MVC 通过 DispatcherServlet(前端控制器)将所有请求统一拦截并分发给具体的处理器(Controller),然后结合视图(View)生成响应。

3. Spring MVC 的架构

Spring MVC 的核心组件:

  1. DispatcherServlet
    • 前端控制器,负责接收和分发所有 HTTP 请求。
  2. HandlerMapping
    • 请求映射器,将 URL 映射到具体的控制器方法。
  3. Controller
    • 业务处理器,负责执行具体的逻辑。
  4. ModelAndView
    • 数据模型和视图对象,用于封装业务数据和返回的视图信息。
  5. ViewResolver
    • 视图解析器,将逻辑视图名解析为物理视图(如 JSP、Thymeleaf 页面)。
  6. View
    • 负责生成最终的响应内容(HTML、JSON 等)。

4. 工作流程

Spring MVC的工作流程

  1. 客户端发送请求。
  2. DispatcherServlet 接收请求并委托给 HandlerMapping 找到对应的 Controller 方法。
  3. Controller 方法处理请求,返回数据(Model)和视图(View)。
  4. ViewResolver 将逻辑视图名解析为物理视图。
  5. 将数据渲染到视图,生成响应并返回给客户端。

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 的区别

对比维度ServletSpring MVC
定位Java Web 开发的基础技术。基于 Servlet 构建的高级 Web 框架。
设计思想直接基于 HTTP 请求-响应模型。基于 MVC(Model-View-Controller)设计模式。
开发复杂度较高,需要手动解析请求和生成响应。较低,提供自动化功能(如参数绑定、视图解析)。
功能丰富度功能较少,需要自行实现扩展(如请求映射、数据绑定)。功能丰富,内置请求映射、表单验证、异常处理等功能。
请求映射静态 URL 映射,直接通过 Web 容器配置路由。灵活的动态映射,支持正则表达式、RESTful URL 等。
视图支持需要手动拼接 HTML 或 JSP 页面。支持多种视图技术(JSP、Thymeleaf、JSON 等)。
表单验证需要手动校验参数。提供注解式校验(如 @Valid 和 @NotNull)。
异常处理需要在代码中显式捕获异常并处理。提供全局异常处理机制(如 @ControllerAdvice)。
扩展性扩展性有限,需通过 Filter 或 Listener 实现一些通用功能。提供拦截器机制,支持 AOP 和依赖注入,扩展性极强。
学习曲线入门简单,但复杂项目开发难度大。需要学习 Spring 框架基础,初学者学习曲线稍陡。
适用场景小型项目或需要直接操作 HTTP 请求的场景。中大型项目,特别是需要高扩展性和快速开发的场景。

四、Servlet 和 Spring MVC 的联系

尽管 Servlet 和 Spring MVC 在定位和功能上有所不同,但它们之间有着密切的联系:

1. 基于 Servlet 构建

  • Spring MVC 是构建在 Servlet 基础之上的高级框架。
  • Spring MVC 的核心组件 DispatcherServlet 本质上是一个 Servlet,它负责接收和分发请求。

2. Servlet 是 Spring MVC 的基础

  • Spring MVC 使用 Servlet 来处理 HTTP 请求,但屏蔽了复杂的细节,例如参数解析、请求分发等。

3. Spring MVC 依赖 Servlet 容器

  • Spring MVC 必须运行在支持 Servlet 的 Web 容器(如 Tomcat、Jetty)中。
  • Servlet 容器负责加载和管理 DispatcherServlet

五、什么时候选择 Servlet 或 Spring MVC

1. 使用 Servlet

  • 适合小型项目,功能简单。
  • 希望深入理解 Java Web 的底层原理。
  • 不需要复杂的框架支持,能够手动实现请求处理和响应。

2. 使用 Spring MVC

  • 适合中大型项目,功能复杂。
  • 需要高效开发、灵活配置和良好的扩展能力。
  • 希望享受 Spring 框架的生态系统(如 Spring Data、Spring Security 等)。

示例代码

假设我们需要构建一个简单的 Web 服务:

  • 请求路径:http://localhost:8080/hello?name=Tom
  • 返回内容:Hello, Tom!

完整 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;

// 使用 @WebServlet 注解映射路径 "/hello"
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

    // 初始化 Servlet(只执行一次)
    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("Servlet 初始化完成!");
    }

    // 处理 GET 请求
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 设置响应内容类型
        resp.setContentType("text/html;charset=UTF-8");

        // 获取请求参数
        String name = req.getParameter("name");
        if (name == null || name.isEmpty()) {
            name = "World"; // 默认值
        }

        // 返回动态响应
        resp.getWriter().write("<h1>Hello, " + name + "!</h1>");
    }

    // 销毁 Servlet(只执行一次,用于释放资源)
    @Override
    public void destroy() {
        super.destroy();
        System.out.println("Servlet 已被销毁!");
    }
}

代码优化点

  1. 注解简化配置:
    • 使用 @WebServlet 注解代替传统的 web.xml 配置。
  2. 默认参数处理:
    • 如果用户未传递参数,返回默认的 "World"。
  3. 字符编码:
    • 通过 resp.setContentType("text/html;charset=UTF-8") 设置字符编码,防止中文乱码。
  4. 日志输出:
    • init()destroy() 方法中添加日志信息,便于调试。

如何运行

  1. 将代码打包为 .war 文件,并部署到 Tomcat。
  2. 访问 URL:http://localhost:8080/hello?name=Tom
  3. 返回结果:Hello, Tom!

Spring MVC 实现

Spring MVC 的实现更加简洁且功能强大。

以下代码实现相同的功能。

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) {
        // 返回动态内容
        return "<h1>Hello, " + name + "!</h1>";
    }
}

Spring Boot 主类

如果使用 Spring Boot 构建项目,可以通过以下代码快速启动:

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);
    }
}

代码优化点

  1. 注解驱动开发:
    • 使用 @Controller@GetMapping 注解处理请求,简化了配置。
  2. 自动参数绑定:
    • 使用 @RequestParam 自动从请求中提取参数,同时设置默认值。
  3. 自动响应:
    • 通过 @ResponseBody 将返回的字符串直接作为响应体,省去了手动处理 HttpServletResponse
  4. Spring Boot 快速启动:
    • 使用 Spring Boot 自动化配置,无需单独部署到 Tomcat。

如何运行

  1. 将代码保存为一个 Spring Boot 应用。
  2. 运行主类 SpringMvcApplication
  3. 访问 URL:http://localhost:8080/hello?name=Tom
  4. 返回结果:Hello, Tom!

示例场景扩展

为了更好地理解 Servlet 和 Spring MVC 的应用场景,我们再扩展一个功能:根据用户输入返回 JSON 数据。

Servlet 示例(返回 JSON 数据)

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 {
        // 设置响应类型为 JSON
        resp.setContentType("application/json;charset=UTF-8");

        // 获取请求参数
        String name = req.getParameter("name");
        if (name == null || name.isEmpty()) {
            name = "World";
        }

        // 构造响应数据
        Map<String, String> responseData = new HashMap<>();
        responseData.put("message", "Hello, " + name + "!");

        // 将数据转换为 JSON
        String jsonResponse = new Gson().toJson(responseData);

        // 返回 JSON 响应
        resp.getWriter().write(jsonResponse);
    }
}

Spring MVC 示例(返回 JSON 数据)

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) {
        // 构造响应数据
        Map<String, String> response = new HashMap<>();
        response.put("message", "Hello, " + name + "!");
        return response;
    }
}

doGet()doPost()service() 的区别

特性service()doGet()doPost()
定位通用方法,用于处理所有 HTTP 请求类型。专门用于处理 HTTP GET 请求。专门用于处理 HTTP POST 请求。
调用方式由 Web 容器直接调用。由 service() 方法根据 HTTP 请求方法分发调用。由 service() 方法根据 HTTP 请求方法分发调用。
实现目的自动分发请求到对应的 doXxx() 方法。处理只读请求(如查询数据)。处理数据提交(如表单、文件上传)。
开发者重写很少被重写,通常由 Web 容器托管。常被重写以处理 GET 请求。常被重写以处理 POST 请求。
请求语义无特定语义,作为分发入口。遵循 HTTP GET 请求的语义(幂等)。遵循 HTTP POST 请求的语义(非幂等)。

总结

区别

  • Servlet 是 Java Web 开发的基础技术,提供了直接操作 HTTP 请求和响应的能力,适合小型项目或需要深入了解底层原理的场景。
  • Spring MVC 是一个基于 Servlet 的高级 Web 框架,提供了大量的自动化功能和开发便利性,适合中大型项目。

联系

  • Spring MVC 是建立在 Servlet 技术之上的框架,它通过 DispatcherServlet 实现请求的接收和分发。
  • Servlet 是 Spring MVC 的基础,但 Spring MVC 封装了许多底层细节,使开发更高效。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • IDEA2023 Maven3.9.1+Tomcat10.1.8配置并搭建Servlet5.0的框架实现

    IDEA2023 Maven3.9.1+Tomcat10.1.8配置并搭建Servlet5.0的框架实现

    本文主要介绍了IDEA2023 Maven3.9.1+Tomcat10.1.8配置并搭建Servlet5.0的框架实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • 基于Java判断网络是否正常代码实例

    基于Java判断网络是否正常代码实例

    这篇文章主要介绍了基于Java判断网络是否正常代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • 浅谈Thread.sleep()为什么要抛出中断异常

    浅谈Thread.sleep()为什么要抛出中断异常

    本文主要介绍了浅谈Thread.sleep()为什么要抛出中断异常,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Java基础之JDK1.8新特性lambda表达式详解

    Java基础之JDK1.8新特性lambda表达式详解

    函数式接口有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,函数式接口可以被隐式转换为lambda表达式,这篇文章主要介绍了Java基础之lambda表达式(JDK1.8新特性),需要的朋友可以参考下
    2023-08-08
  • 一文让你彻底明白Java中的值传递和引用传递

    一文让你彻底明白Java中的值传递和引用传递

    这篇文章主要给大家介绍了关于Java中值传递和引用传递的相关资料,值传递是指在调用函数时将实际参数复制一份传递到函数中,引用传递是指在调用函数时将实际参数的引用直接传递到函数中,需要的朋友可以参考下
    2023-10-10
  • Java中indexOf()的用法小结

    Java中indexOf()的用法小结

    这篇文章主要介绍了Java中indexOf()的用法小结,indexOf()有四种方法,用来查找某个字符或字符串的位置,本文通过示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • Spring中@Autowired注解的原理详解

    Spring中@Autowired注解的原理详解

    这篇文章主要介绍了Spring中@Autowired注解的原理详解,对于spring配置一个bean时,如果需要给该bean提供一些初始化参数,则需要通过依赖注入方式,所谓的依赖注入就是通过spring将bean所需要的一些参数传递到bean实例对象的过程,需要的朋友可以参考下
    2023-11-11
  • 盘点几种常见的java排序算法

    盘点几种常见的java排序算法

    所谓排序就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作,下面这篇文章主要给大家介绍了几种常见的java排序算法的相关资料,需要的朋友可以参考下
    2021-11-11
  • 深入Java线程中断的本质与编程原则的概述

    深入Java线程中断的本质与编程原则的概述

    本篇文章对Java线程中断的本质与编程原则进行了详细的概述,需要的朋友参考下
    2013-05-05
  • Java通过exchange协议发送邮件

    Java通过exchange协议发送邮件

    这篇文章主要为大家详细介绍了Java通过exchange协议发送邮件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02

最新评论