Java Web 技术演进:Servlet → Spring → Spring Boot
📋 目录
- 技术演进历程
- [Servlet - Java Web 的核心技术](#Servlet - Java Web 的核心技术)
- [Spring Framework - 基于 Servlet 的框架](#Spring Framework - 基于 Servlet 的框架)
- [Spring Boot - 自动配置的 Spring](#Spring Boot - 自动配置的 Spring)
- 核心区别对比
- 三者的关系
- 实际应用场景
- 总结
技术演进历程
Servlet (1997)
↓
Spring Framework (2003, 基于Servlet)
↓
Spring Boot (2014, 自动配置的Spring)
Servlet - Java Web 的核心技术
什么是 Servlet?
Servlet 是 Java Web 的标准规范,定义了如何处理 HTTP 请求。它是最早的 Java Web 开发方式。
纯 Servlet 开发(原始方式)
java
// ❌ 纯 Servlet 开发(非常繁琐)
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1. 接收请求参数(手动转换类型)
String userId = req.getParameter("id");
String name = req.getParameter("name");
// 2. 调用 Service 层(手动 new 对象)
UserService userService = new UserServiceImpl();
User user = userService.getUserById(userId);
// 3. 设置请求属性
req.setAttribute("user", user);
// 4. 转发到 JSP
req.getRequestDispatcher("/WEB-INF/jsp/user.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 手动获取表单参数
String id = req.getParameter("id");
String name = req.getParameter("name");
// 手动创建对象
User user = new User();
user.setId(id);
user.setName(name);
// 调用 Service
UserService userService = new UserServiceImpl();
userService.saveUser(user);
// 重定向
resp.sendRedirect(req.getContextPath() + "/user/list");
}
}
web.xml 配置(繁琐)
xml
<!-- ❌ 每个 Servlet 都要配置 -->
<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 -->
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.example.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/user</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>OrderServlet</servlet-name>
<servlet-class>com.example.OrderServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>OrderServlet</servlet-name>
<url-pattern>/order</url-pattern>
</servlet-mapping>
<!-- 配置 Filter -->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.example.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置 Listener -->
<listener>
<listener-class>com.example.ContextLoaderListener</listener-class>
</listener>
<!-- 配置 Session 超时 -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<!-- 配置欢迎页面 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Servlet 的特点
| 优点 | 缺点 |
|---|---|
| 标准、稳定 | 开发繁琐 |
| 底层控制力强 | 配置复杂 |
| 性能好 | 不支持依赖注入 |
| 适合理解原理 | 代码重复多 |
| 不支持 AOP |
Servlet 的生命周期
1. 实例化 (Instantiation)
↓
2. 初始化 (Initialization) - 调用 init() 方法
↓
3. 请求处理 (Request Handling) - 调用 service() 方法
↓
4. 销毁 (Destruction) - 调用 destroy() 方法
示例:
java
public class UserServlet extends HttpServlet {
// 1. 初始化
@Override
public void init() throws ServletException {
System.out.println("Servlet 初始化");
}
// 2. 请求处理
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
// 处理 GET 请求
}
// 3. 销毁
@Override
public void destroy() {
System.out.println("Servlet 销毁");
}
}
Spring Framework - 基于 Servlet 的框架
什么是 Spring?
Spring 是在 Servlet 基础上构建的应用框架,提供了依赖注入(DI)和面向切面编程(AOP)。
Spring MVC(基于 Servlet)
java
// ✅ Spring MVC(简化了 Servlet 开发)
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService; // 自动注入,不用手动 new
@GetMapping("/{id}")
public ModelAndView getUser(@PathVariable String id) {
// 1. 自动参数绑定
User user = userService.getUserById(id);
// 2. 返回 ModelAndView
return new ModelAndView("user", "user", user);
}
@PostMapping
@ResponseBody
public User createUser(@RequestBody User user) {
// 自动 JSON 转换
return userService.saveUser(user);
}
@PutMapping("/{id}")
@ResponseBody
public User updateUser(@PathVariable String id, @RequestBody User user) {
user.setId(id);
return userService.updateUser(user);
}
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteUser(@PathVariable String id) {
userService.deleteUser(id);
}
}
Spring XML 配置(仍然繁琐)
xml
<!-- ❌ Spring 早期配置(仍然复杂) -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="...">
<!-- 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
<property name="initialSize" value="5"/>
<property name="maxTotal" value="20"/>
</bean>
<!-- 配置 SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.example.entity"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 配置事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 配置 DAO -->
<bean id="userDao" class="com.example.dao.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 配置 Service -->
<bean id="userService" class="com.example.service.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
<!-- 配置 Controller -->
<bean id="userController" class="com.example.controller.UserController">
<property name="userService" ref="userService"/>
</bean>
<!-- 扫描组件 -->
<context:component-scan base-package="com.example"/>
</beans>
Spring 的特点
| 优点 | 缺点 |
|---|---|
| 依赖注入(DI) | 配置繁琐 |
| AOP 支持 | 需要大量 XML |
| 集成各种技术 | 学习曲线陡峭 |
| 解耦 | 启动慢 |
| 声明式事务 |
Spring 的核心特性
1. 依赖注入(Dependency Injection)
java
// 传统方式:手动创建依赖
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserServiceImpl() {
this.userDao = new UserDaoImpl(); // 硬编码依赖
}
}
// Spring 方式:自动注入
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao; // 自动注入
}
2. 面向切面编程(AOP)
java
// 定义切面
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Before: " + joinPoint.getSignature());
}
@After("execution(* com.example.service.*.*(..))")
public void logAfter(JoinPoint joinPoint) {
System.out.println("After: " + joinPoint.getSignature());
}
@Around("execution(* com.example.service.*.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
System.out.println("Execution time: " + (end - start) + "ms");
return result;
}
}
3. 声明式事务
java
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Autowired
private OrderDao orderDao;
@Transactional // 自动管理事务
public void createUserWithOrder(User user, Order order) {
userDao.save(user);
orderDao.save(order);
// 如果抛出异常,两个操作都会回滚
}
}
Spring Boot - 自动配置的 Spring
什么是 Spring Boot?
Spring Boot 是 Spring 的自动配置版本,简化了配置,提供了快速开发能力。
Spring Boot(零配置)
java
// ✅ Spring Boot(最简单)
@SpringBootApplication // 一个注解搞定所有配置
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User getUser(@PathVariable String id) {
return userService.getUserById(id); // 自动返回 JSON
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.saveUser(user);
}
@PutMapping("/{id}")
public User updateUser(@PathVariable String id, @RequestBody User user) {
return userService.updateUser(id, user);
}
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteUser(@PathVariable String id) {
userService.deleteUser(id);
}
}
application.yml 配置(极简)
yaml
# ✅ Spring Boot 配置(一行搞定)
spring:
# 数据源配置
datasource:
url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
# JPA 配置
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
format_sql: true
# Redis 配置
redis:
host: localhost
port: 6379
password:
database: 0
# 服务器配置
server:
port: 8080
servlet:
context-path: /api
# 日志配置
logging:
level:
root: INFO
com.example: DEBUG
Spring Boot 的特点
| 优点 | 说明 |
|---|---|
| 零配置 | 自动配置,无需 XML |
| 内嵌服务器 | Tomcat/Jetty 内置 |
| 快速开发 | Starters 简化依赖 |
| 生产就绪 | 监控、健康检查开箱即用 |
| 微服务友好 | 天然支持微服务 |
| 自动重启 | 开发时自动重启 |
Spring Boot Starters
Spring Boot 提供了大量的 Starters 来简化依赖管理:
xml
<!-- Web Starter:包含 Spring MVC、Tomcat 等 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Data JPA Starter:包含 Spring Data JPA、Hibernate 等 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Redis Starter:包含 Spring Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Security Starter:包含 Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Test Starter:包含 JUnit、Mockito 等 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Spring Boot 自动配置原理
java
@SpringBootApplication
// 等价于:
// @SpringBootConfiguration
// @EnableAutoConfiguration // 自动配置
// @ComponentScan // 组件扫描
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
自动配置流程:
1. @EnableAutoConfiguration 启用自动配置
↓
2. 读取 classpath 下的 META-INF/spring.factories
↓
3. 加载所有自动配置类
↓
4. 根据 @Conditional 注解判断是否需要配置
↓
5. 自动装配 Bean
示例:自动配置 DataSource:
java
@Configuration
@ConditionalOnClass(DataSource.class) // classpath 中有 DataSource 类
@ConditionalOnMissingBean(DataSource.class) // 容器中没有 DataSource Bean
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
// 自动创建 DataSource
return DataSourceBuilder.create().build();
}
}
核心区别对比
1. 开发方式对比
| 特性 | Servlet | Spring | Spring Boot |
|---|---|---|---|
| 配置方式 | web.xml | XML/注解 | 零配置 |
| 依赖管理 | 手动管理 | 手动管理 | 自动管理(Starters) |
| 服务器 | 外部部署 | 外部部署 | 内嵌服务器 |
| 启动方式 | 部署到 Tomcat | 部署到 Tomcat | java -jar 运行 |
| 开发效率 | 低 | 中 | 高 |
| 学习曲线 | 陡峭 | 陡峭 | 平缓 |
| 依赖注入 | ❌ | ✅ | ✅ |
| AOP | ❌ | ✅ | ✅ |
| 事务管理 | 手动 | 声明式 | 声明式(简化) |
2. 代码对比
查询用户接口
Servlet 版本(30+ 行):
java
// ❌ 纯 Servlet 开发
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1. 接收参数
String id = req.getParameter("id");
// 2. 手动创建 Service
UserService userService = new UserServiceImpl();
// 3. 调用 Service
User user = userService.getUserById(id);
// 4. 手动转换为 JSON
StringBuilder json = new StringBuilder();
json.append("{");
json.append("\"id\":\"").append(user.getId()).append("\",");
json.append("\"name\":\"").append(user.getName()).append("\",");
json.append("\"email\":\"").append(user.getEmail()).append("\"");
json.append("}");
// 5. 设置响应类型
resp.setContentType("application/json;charset=UTF-8");
// 6. 手动写入响应
resp.getWriter().write(json.toString());
}
}
Spring MVC 版本(10 行):
java
// ✅ Spring MVC
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
@ResponseBody
public User getUser(@PathVariable String id) {
return userService.getUserById(id);
}
}
Spring Boot 版本(3 行):
java
// ✅ Spring Boot
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User getUser(@PathVariable String id) {
return userService.getUserById(id);
}
}
3. 配置对比
数据库配置
Servlet + JDBC 版本:
java
// ❌ 手动创建连接池
public class DBUtil {
private static BasicDataSource dataSource;
static {
dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
dataSource.setInitialSize(5);
dataSource.setMaxTotal(20);
dataSource.setMaxIdle(10);
dataSource.setMinIdle(5);
dataSource.setMaxWaitMillis(60000);
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
// 使用
public class UserDaoImpl implements UserDao {
@Override
public User findById(String id) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = DBUtil.getConnection();
String sql = "SELECT * FROM user WHERE id = ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1, id);
rs = stmt.executeQuery();
if (rs.next()) {
User user = new User();
user.setId(rs.getString("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
return user;
}
return null;
} finally {
// 手动关闭资源
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
}
}
}
Spring Boot + JPA 版本:
yaml
# ✅ 只需配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: password
jpa:
hibernate:
ddl-auto: update
java
// ✅ 使用 JPA
@Entity
@Table(name = "user")
public class User {
@Id
private String id;
private String name;
private String email;
// getters and setters
}
@Repository
public interface UserRepository extends JpaRepository<User, String> {
// 自动实现 CRUD,无需写 SQL
}
三者的关系
技术栈关系图
┌─────────────────────────────────────────────────────┐
│ Java Web 规范 │
│ (Servlet, JSP, Filter, Listener, JNDI 等) │
│ - 定义了 Java Web 的标准 │
│ - 由 Tomcat/Jetty 等 Servlet 容器实现 │
└─────────────────────────────────────────────────────┘
↑
│ 基于
│
┌─────────────────────────────────────────────────────┐
│ Spring Framework │
│ (Spring MVC, Spring JDBC, Spring ORM 等) │
│ - 依赖注入 (DI) │
│ - 面向切面编程 (AOP) │
│ - 事务管理 │
│ - 集成各种技术 │
└─────────────────────────────────────────────────────┘
↑
│ 自动配置 + 快速开发
│
┌─────────────────────────────────────────────────────┐
│ Spring Boot │
│ - 零配置 │
│ - 内嵌服务器 │
│ - Starters │
│ - 生产就绪 │
│ - 微服务支持 │
└─────────────────────────────────────────────────────┘
底层架构对比
Servlet 应用架构
┌─────────────────────────────────────────┐
│ HTTP 请求 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Tomcat Servlet 容器 │
│ - 解析 HTTP 请求 │
│ - 创建 HttpServletRequest 对象 │
│ - 创建 HttpServletResponse 对象 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Web.xml 配置 │
│ - Servlet 映射 │
│ - Filter 配置 │
│ - Listener 配置 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Servlet │
│ - doGet() / doPost() 方法 │
│ - 手动处理请求参数 │
│ - 手动创建 Service 对象 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Service │
│ - 业务逻辑处理 │
│ - 手动创建 DAO 对象 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ DAO │
│ - 手动管理数据库连接 │
│ - 手动编写 SQL │
│ - 手动处理 ResultSet │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 数据库 │
└─────────────────────────────────────────┘
Spring MVC 应用架构
┌─────────────────────────────────────────┐
│ HTTP 请求 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Tomcat Servlet 容器 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ DispatcherServlet (前端控制器) │
│ - 统一处理所有请求 │
│ - 路由到对应的 Controller │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Spring Context (容器) │
│ - 依赖注入 │
│ - AOP 切面 │
│ - 事务管理 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Controller │
│ - @RequestMapping 注解 │
│ - 自动参数绑定 │
│ - 自动注入 Service │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Service │
│ - @Service 注解 │
│ - 自动注入 DAO │
│ - @Transactional 注解 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ DAO │
│ - @Repository 注解 │
│ - Spring JDBC / Hibernate │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 数据库 │
└─────────────────────────────────────────┘
Spring Boot 应用架构
┌─────────────────────────────────────────┐
│ HTTP 请求 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 内嵌 Tomcat │
│ - 自动配置 │
│ - 无需外部部署 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Spring Boot 自动配置 │
│ - 自动装配 Bean │
│ - 自动配置 DataSource │
│ - 自动配置 MVC │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Spring Context (容器) │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Controller │
│ - @RestController 注解 │
│ - 自动返回 JSON │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Service │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Repository │
│ - Spring Data JPA │
│ - 无需写 SQL │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 数据库 │
└─────────────────────────────────────────┘
实际应用场景
1. 什么时候用 Servlet?
适用场景
java
// ✅ 场景:学习 Servlet 原理
public class CustomServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 需要完全控制请求处理流程
}
}
推荐场景:
- ✅ 学习 Servlet 原理和底层机制
- ✅ 需要完全控制请求处理流程
- ✅ 性能极致优化的场景
- ✅ 理解 Java Web 基础
不推荐场景:
- ❌ 常规 Web 应用开发
- ❌ 快速原型开发
- ❌ 微服务开发
- ❌ 企业级应用开发
2. 什么时候用 Spring?
适用场景
java
// ✅ 场景:传统企业项目
@Configuration
@EnableTransactionManagement
@ComponentScan("com.example")
public class SpringConfig {
@Bean
public DataSource dataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/mydb")
.username("root")
.password("password")
.build();
}
@Bean
public UserService userService() {
return new UserServiceImpl();
}
}
推荐场景:
- ✅ 传统企业项目
- ✅ 需要精细控制配置
- ✅ 已有 Spring 项目维护
- ✅ 需要复杂的 AOP 配置
不推荐场景:
- ❌ 新项目(推荐 Spring Boot)
- ❌ 快速开发
- ❌ 微服务
- ❌ 云原生应用
3. 什么时候用 Spring Boot?
适用场景
java
// ✅ 场景:新项目、微服务
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users/{id}")
public User getUser(@PathVariable String id) {
return userService.findById(id);
}
}
推荐场景:
- ✅ 新项目开发(强烈推荐)
- ✅ 微服务开发
- ✅ 快速原型开发
- ✅ 云原生应用
- ✅ RESTful API 开发
- ✅ 容器化部署
示例:微服务架构
┌─────────────────────────────────────────┐
│ API Gateway │
│ (Spring Cloud Gateway) │
└─────────────────────────────────────────┘
↓ ↓ ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 用户服务 │ │ 订单服务 │ │ 商品服务 │
│(Boot) │ │(Boot) │ │(Boot) │
└──────────┘ └──────────┘ └──────────┘
↓ ↓ ↓
┌─────────────────────────────────────────┐
│ 注册中心 │
│ (Spring Cloud Netflix/Eureka) │
└─────────────────────────────────────────┘
4. 特殊场景:Spring Boot + WebFlux
你的 Evo-Apigw 项目使用的就是这个组合:
java
@SpringBootApplication
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
@Component
public class TokenValidationFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 响应式编程
return chain.filter(exchange);
}
}
特点:
- Spring Boot:自动配置、快速开发
- WebFlux:响应式编程(非 Servlet)
- 底层:Reactor Netty(非 Tomcat)
架构对比:
| 特性 | Spring MVC | Spring WebFlux |
|---|---|---|
| 编程模型 | 阻塞式 | 响应式(非阻塞) |
| 底层容器 | Tomcat/Jetty | Reactor Netty |
| 并发模型 | 每请求一线程 | 少量线程处理大量请求 |
| 适用场景 | 传统 Web 应用 | 高并发、微服务、网关 |
| Servlet | 基于 Servlet | 不依赖 Servlet |
总结
快速对比表
| 维度 | Servlet | Spring | Spring Boot |
|---|---|---|---|
| 本质 | 规范 | 框架 | 框架 + 自动配置 |
| 底层 | Servlet API | Servlet API | Servlet API / WebFlux |
| 配置方式 | web.xml | XML/注解 | 零配置(自动配置) |
| 依赖注入 | ❌ | ✅ | ✅ |
| AOP | ❌ | ✅ | ✅ |
| 事务管理 | 手动 | 声明式 | 声明式(简化) |
| 服务器 | 外部 Tomcat | 外部 Tomcat | 内嵌 Tomcat/Netty |
| 启动方式 | war 包部署 | war 包部署 | java -jar |
| 开发效率 | ⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 学习曲线 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ |
| 适用场景 | 学习、底层 | 传统项目 | 新项目、微服务 |
技术选型建议
项目启动流程
新项目?
├─ 是 → 使用 Spring Boot ✅
│ ├─ 传统 Web 应用 → Spring Boot + Spring MVC
│ ├─ 微服务 → Spring Boot + Spring Cloud
│ └─ 网关/高并发 → Spring Boot + Spring Cloud Gateway + WebFlux
│
└─ 否 → 已有项目维护?
├─ 是 → 保持现有技术栈
│ ├─ Servlet 项目 → 继续维护
│ └─ Spring 项目 → 继续维护
└─ 否 → 不推荐使用旧技术栈
学习路径建议
第1步:学习 Servlet 原理(1-2天)
├─ Servlet 生命周期
├─ 请求/响应处理
├─ Filter 和 Listener
└─ 理解 Java Web 基础
↓ 理解底层原理
第2步:学习 Spring Framework(3-5天)
├─ 依赖注入(DI)
├─ 面向切面编程(AOP)
├─ Spring MVC
├─ Spring JDBC / JPA
└─ 事务管理
↓ 掌握核心概念
第3步:学习 Spring Boot(2-3天)
├─ 自动配置原理
├─ Starters 使用
├─ application.yml 配置
├─ 内嵌服务器
└─ 生产就绪特性
↓ 快速开发
第4步:学习 Spring Cloud(5-7天)
├─ 服务注册与发现
├─ 配置中心
├─ 网关
├─ 熔断器
└─ 链路追踪
↓ 微服务开发
第5步:学习 WebFlux + 响应式编程(3-5天)
├─ Reactor(Mono、Flux)
├─ 响应式编程模型
├─ Spring WebFlux
└─ 异步非阻塞
↓ 高性能异步编程
你的 Gateway 项目分析
你的 Evo-Apigw 项目使用的技术栈:
Spring Boot + Spring Cloud Gateway + WebFlux
↓
├─ Spring Boot:自动配置、快速开发
├─ Spring Cloud Gateway:基于 WebFlux 的 API 网关
└─ WebFlux:响应式编程(非 Servlet)
技术特点:
- ✅ 零配置:Spring Boot 自动配置
- ✅ 响应式:WebFlux 非阻塞异步
- ✅ 高性能:少量线程处理大量请求
- ✅ 微服务:天然支持微服务架构
- ✅ 内嵌服务器:Reactor Netty(非 Tomcat)
关键区别:
- 传统 Spring MVC 基于 Servlet(阻塞式)
- Spring WebFlux 不依赖 Servlet(非阻塞式)
- 你的 Gateway 项目用的是 WebFlux + Netty
附录
1. 完整示例:用户管理系统
Servlet 版本(100+ 行)
java
// UserServlet.java
public class UserServlet extends HttpServlet {
private UserService userService = new UserServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String pathInfo = req.getPathInfo();
if ("/list".equals(pathInfo)) {
listUsers(req, resp);
} else if ("/view".equals(pathInfo)) {
viewUser(req, resp);
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String pathInfo = req.getPathInfo();
if ("/create".equals(pathInfo)) {
createUser(req, resp);
} else if ("/update".equals(pathInfo)) {
updateUser(req, resp);
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String pathInfo = req.getPathInfo();
if ("/delete".equals(pathInfo)) {
deleteUser(req, resp);
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
private void listUsers(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
List<User> users = userService.findAll();
req.setAttribute("users", users);
req.getRequestDispatcher("/WEB-INF/jsp/user/list.jsp").forward(req, resp);
}
private void viewUser(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String id = req.getParameter("id");
User user = userService.findById(id);
if (user == null) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
req.setAttribute("user", user);
req.getRequestDispatcher("/WEB-INF/jsp/user/view.jsp").forward(req, resp);
}
private void createUser(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String id = req.getParameter("id");
String name = req.getParameter("name");
String email = req.getParameter("email");
User user = new User();
user.setId(id);
user.setName(name);
user.setEmail(email);
userService.save(user);
resp.sendRedirect(req.getContextPath() + "/user/list");
}
private void updateUser(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String id = req.getParameter("id");
String name = req.getParameter("name");
String email = req.getParameter("email");
User user = new User();
user.setId(id);
user.setName(name);
user.setEmail(email);
userService.update(user);
resp.sendRedirect(req.getContextPath() + "/user/list");
}
private void deleteUser(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String id = req.getParameter("id");
userService.delete(id);
resp.sendRedirect(req.getContextPath() + "/user/list");
}
}
xml
<!-- web.xml -->
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.example.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/user/*</url-pattern>
</servlet-mapping>
Spring Boot 版本(20 行)
java
// UserController.java
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> listUsers() {
return userService.findAll();
}
@GetMapping("/{id}")
public User getUser(@PathVariable String id) {
return userService.findById(id);
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.save(user);
}
@PutMapping("/{id}")
public User updateUser(@PathVariable String id, @RequestBody User user) {
user.setId(id);
return userService.update(user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable String id) {
userService.delete(id);
}
}
2. 常见问题
Q1: Spring Boot 完全替代 Servlet 了吗?
A:不是。
- Spring Boot 底层仍然使用 Servlet(Spring MVC)
- 但 Spring WebFlux 不依赖 Servlet
- Servlet 仍然是 Java Web 的基础规范
- 学习 Servlet 有助于理解底层原理
Q2: 什么时候用 WebFlux,什么时候用 Spring MVC?
A:
- Spring MVC:传统 Web 应用、简单业务、阻塞式 I/O
- WebFlux:高并发、微服务、网关、非阻塞式 I/O
Q3: Spring Boot 和 Spring Cloud 的关系?
A:
- Spring Boot:快速开发单个微服务
- Spring Cloud:微服务整体解决方案(包含注册中心、配置中心、网关等)
- Spring Cloud 基于 Spring Boot
文档生成时间 : 2026-03-27
技术栈: Servlet / Spring / Spring Boot / Spring Cloud Gateway / WebFlux