惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Latest news
Latest news
T
Troy Hunt's Blog
V
Vulnerabilities – Threatpost
L
LINUX DO - 热门话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
V
V2EX
博客园 - 司徒正美
B
Blog RSS Feed
AWS News Blog
AWS News Blog
MyScale Blog
MyScale Blog
Scott Helme
Scott Helme
Cisco Talos Blog
Cisco Talos Blog
Last Week in AI
Last Week in AI
NISL@THU
NISL@THU
博客园 - Franky
P
Proofpoint News Feed
博客园_首页
C
CERT Recently Published Vulnerability Notes
雷峰网
雷峰网
S
Schneier on Security
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
G
GRAHAM CLULEY
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
WordPress大学
WordPress大学
The Hacker News
The Hacker News
T
Threatpost
阮一峰的网络日志
阮一峰的网络日志
A
Arctic Wolf
Microsoft Azure Blog
Microsoft Azure Blog
T
The Exploit Database - CXSecurity.com
Engineering at Meta
Engineering at Meta
罗磊的独立博客
T
The Blog of Author Tim Ferriss
D
Darknet – Hacking Tools, Hacker News & Cyber Security
I
Intezer
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
K
Kaspersky official blog
SecWiki News
SecWiki News
云风的 BLOG
云风的 BLOG
美团技术团队
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 【当耐特】
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Security Latest
Security Latest
C
Cyber Attacks, Cyber Crime and Cyber Security
B
Blog
S
Security Affairs

博客园 - CharyGao

OpenAI Codex AI降智解决方案, 原因解析与系统提示词修改指南 OpenClaw vs Coze/Dify/n8n 帮你半小时内选对合适的AI Skills 热潮过去后,我重新理解了 AI Agent 的方向 智读致用|《埃隆之书》 《一人企业》 一人公司:The Agency 免费“雇佣“144个AI专家,虚拟团队走进现实 用微软Agent Framework打造智能博客生成系统+AI智能体军团 告别加班(第二期):月报还是Word排版?本地AI解您愁 居然可以在 Claude 桌面端用三方模型了! Claude Code 每次启动都要确认权限?一行配置永久解决 98.5% 的人都不知道:SSH 居然还有个“隐藏菜单” 强程序员在 AI 时代的赚钱路径 骚操作来了!Claude编程的42个实战技巧大全 面试官:“简历写着熟练使用 Claude Code,连 simplify 代码审查命令都不知道!”,我:“那又如何呢?” SpringBoot+ResponseBodyEmitter异步流式推送神技 加密后的数据如何进行模糊查询? 最适合新手安装的10个小龙虾🦞 skills来了! 周末和孩子必看的亲子电影合集,陪伴孩子成长的每一步 拒绝代码泄露与“屎山”迷航:GitNexus纯本地知识图谱+可视化关系网,引发GitHub 8800星狂欢 还原BatchEncryption(201610版本)混淆的批处理文件 用上这个Skill,你的Claude Code/Codex 将会比别人快5倍 -- 用分布式思维驯服AI任务编排 前端项目中定义vs code要安装的插件 vscode中claude code插件代理地址设置 2026新手必学:GPT-5.5高效提示词指南 解决 URLEncoder.encode 编码空格变 + 号 Springboot通过谷歌Kaptcha 组件,生成图形验证码 HTTP 与 SpringBoot 参数提交与接收协议方式 SpringBoot多线程池配置 springboot使用logback自定义日志 SpringBoot + Cursor 最佳提示词工程手册 scoop国内安装方法 Prompt 工程实战总结:文本分类、信息抽取、语义匹配 PowerShell DSC(Desired State Configuration)实战指南 OpenResty Lua 代码断点 调试指南:VSCode + LuaPanda OpenClaw多智能体路由实战:飞书多机器人配置指南 OpenClaw 提示词全集 (Prompt Collection) n8n 2.0 中文汉化版一键部署教程 | 解除Execute Command限制 java中Redisson ,jedis,Lettuce和Spring Data Redis的四种深度对比和优缺点详解 Everything Claude Code(Anthropic 黑客松冠军开源配置) 从 ChatGPT 到 Coding Agent:AI 执行时代的未来猜想 【万字长文】Gemini 3 Pro 全面指南:从免费订阅到 CLI / Agent 实战 Codex 全面实战教程:从安装到工程协作,一篇跑通 3万字硬核拆解 Claude Code:从入门到工程化落地 Gemini 3 完整指南 Codex 完整指南 Claude Code 完整指南4-10 Claude Code 完整指南 claude code 自动保存对话插件 提示词99+ 拜拜Cursor,你好Kiro!(附全平台安装包下载,Win、Mac、Linux) 别再忍了!uv 下载慢如龟速?一招配置国内镜像,让你的 Python 体验坐上火箭! docker配置参数详解---/etc/docker/daemon.json完整参数 win11 清理 OpenCowork 让 AI 在飞书里真正「动手干活」 教你从0到1安装OpenClaw,快速接入飞书,打通任督二脉! SpringBoot 最大连接数及最大并发数是多少??? SpringBoot vs Nginx:5种实现vs1个指令,谁才是防盗链的“真·王者”? Spring Boot日志集成 Redisson 使用手册:从 API 误区到看门狗失效,在此终结分布式锁的噩梦 OpenClaw超级速查表 zeroclaw ubunut25 -ARM 修改国内镜像 openClaw国内镜像安装 知识图谱 —— 结构化知识的强大工具 什么是 Supervised learning(监督学习) 机器学习中的过拟合与欠拟合现象:理论与实践案例研究 解析 Anthropic 的模型上下文协议(MCP)及其优点
Java Web 技术演进:Servlet → Spring → Spring Boot
CharyGao · 2026-05-06 · via 博客园 - CharyGao

技术演进历程

Servlet (1997)
    ↓
Spring Framework (2003, 基于Servlet)
    ↓
Spring Boot (2014, 自动配置的Spring)

Servlet - Java Web 的核心技术

什么是 Servlet?

Servlet 是 Java Web 的标准规范,定义了如何处理 HTTP 请求。它是最早的 Java Web 开发方式。

纯 Servlet 开发(原始方式)

// ❌ 纯 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");
    }
}

java

web.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>

xml

Servlet 的特点

优点 缺点
标准、稳定 开发繁琐
底层控制力强 配置复杂
性能好 不支持依赖注入
适合理解原理 代码重复多
  不支持 AOP

Servlet 的生命周期

1. 实例化 (Instantiation)
   ↓
2. 初始化 (Initialization) - 调用 init() 方法
   ↓
3. 请求处理 (Request Handling) - 调用 service() 方法
   ↓
4. 销毁 (Destruction) - 调用 destroy() 方法

示例

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 销毁");
    }
}

java


Spring Framework  - 基于 Servlet 的框架

什么是 Spring?

Spring 是在 Servlet 基础上构建的应用框架 ,提供了依赖注入(DI)和面向切面编程(AOP)。

Spring MVC(基于 Servlet)

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

java

Spring 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>

xml

Spring 的特点

优点 缺点
依赖注入(DI) 配置繁琐
AOP 支持 需要大量 XML
集成各种技术 学习曲线陡峭
解耦 启动慢
声明式事务  

Spring 的核心特性

1. 依赖注入(Dependency Injection)
// 传统方式:手动创建依赖
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;  // 自动注入
}

java

2. 面向切面编程(AOP)
// 定义切面
@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;
    }
}

java

3. 声明式事务
@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);
        // 如果抛出异常,两个操作都会回滚
    }
}

java


Spring Boot - 自动配置的 Spring

什么是 Spring Boot?

Spring Boot 是 Spring 的自动配置版本,简化了配置,提供了快速开发能力。

Spring Boot(零配置)

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

java

application.yml 配置(极简)

# ✅ 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

yaml

Spring Boot 的特点

优点 说明
零配置 自动配置,无需 XML
内嵌服务器 Tomcat/Jetty 内置
快速开发 Starters 简化依赖
生产就绪 监控、健康检查开箱即用
微服务友好 天然支持微服务
自动重启 开发时自动重启

Spring Boot Starters

Spring Boot 提供了大量的 Starters 来简化依赖管理:

<!-- 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>

xml

Spring Boot 自动配置原理

@SpringBootApplication
// 等价于:
// @SpringBootConfiguration
// @EnableAutoConfiguration  // 自动配置
// @ComponentScan              // 组件扫描
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

java

自动配置流程

1. @EnableAutoConfiguration 启用自动配置
   ↓
2. 读取 classpath 下的 META-INF/spring.factories
   ↓
3. 加载所有自动配置类
   ↓
4. 根据 @Conditional 注解判断是否需要配置
   ↓
5. 自动装配 Bean

示例:自动配置 DataSource

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

java


核心区别对比

1. 开发方式对比

特性 Servlet Spring Spring Boot
配置方式 web.xml XML/注解 零配置
依赖管理 手动管理 手动管理 自动管理(Starters)
服务器 外部部署 外部部署 内嵌服务器
启动方式 部署到 Tomcat 部署到 Tomcat java -jar 运行
开发效率
学习曲线 陡峭 陡峭 平缓
依赖注入
AOP
事务管理 手动 声明式 声明式(简化)

2. 代码对比

查询用户接口

Servlet 版本(30+ 行):

// ❌ 纯 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());
    }
}

java

Spring MVC 版本(10 行):

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

java

Spring Boot 版本(3 行):

// ✅ Spring Boot
@RestController
@RequestMapping("/user")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping("/{id}")
    public User getUser(@PathVariable String id) {
        return userService.getUserById(id);
    }
}

java

3. 配置对比

数据库配置

Servlet + JDBC 版本

// ❌ 手动创建连接池
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();
        }
    }
}

java

Spring Boot + JPA 版本

# ✅ 只需配置
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: password
  jpa:
    hibernate:
      ddl-auto: update

yaml

// ✅ 使用 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


三者的关系

技术栈关系图

┌─────────────────────────────────────────────────────┐
│                 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?

适用场景
// ✅ 场景:学习 Servlet 原理
public class CustomServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        // 需要完全控制请求处理流程
    }
}

java

推荐场景

  • ✅ 学习 Servlet 原理和底层机制
  • ✅ 需要完全控制请求处理流程
  • ✅ 性能极致优化的场景
  • ✅ 理解 Java Web 基础

不推荐场景

  • ❌ 常规 Web 应用开发
  • ❌ 快速原型开发
  • ❌ 微服务开发
  • ❌ 企业级应用开发

2. 什么时候用 Spring?

适用场景
// ✅ 场景:传统企业项目
@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();
    }
}

java

推荐场景

  • ✅ 传统企业项目
  • ✅ 需要精细控制配置
  • ✅ 已有 Spring 项目维护
  • ✅ 需要复杂的 AOP 配置

不推荐场景

  • ❌ 新项目(推荐 Spring Boot)
  • ❌ 快速开发
  • ❌ 微服务
  • ❌ 云原生应用

3. 什么时候用 Spring Boot?

适用场景
// ✅ 场景:新项目、微服务
@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);
    }
}

java

推荐场景

  • ✅ 新项目开发(强烈推荐)
  • ✅ 微服务开发
  • ✅ 快速原型开发
  • ✅ 云原生应用
  • ✅ RESTful API 开发
  • ✅ 容器化部署

示例:微服务架构

┌─────────────────────────────────────────┐
│         API Gateway                      │
│     (Spring Cloud Gateway)              │
└─────────────────────────────────────────┘
        ↓              ↓              ↓
┌──────────┐  ┌──────────┐  ┌──────────┐
│ 用户服务  │  │ 订单服务  │  │ 商品服务  │
│(Boot)    │  │(Boot)    │  │(Boot)    │
└──────────┘  └──────────┘  └──────────┘
     ↓              ↓              ↓
┌─────────────────────────────────────────┐
│         注册中心                         │
│   (Spring Cloud Netflix/Eureka)        │
└─────────────────────────────────────────┘

4. 特殊场景:Spring Boot + WebFlux

你的 Evo-Apigw 项目使用的就是这个组合:

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

java

特点

  • 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+ 行)
// 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");
    }
}

java

<!-- 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>

xml

Spring Boot 版本(20 行)
// 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);
    }
}

java

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