Java Web 技术演进:Servlet → Spring → Spring Boot

Java Web 技术演进:Servlet → Spring → Spring Boot

📋 目录


技术演进历程

复制代码
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

相关推荐
ljt27249606613 小时前
Flutter笔记--popUntilWithResult
前端·笔记·flutter
kyle~3 小时前
JNI与JNA ---打通Java服务端与C++机器人系统的通信链路
java·c++·机器人
XiYang-DING3 小时前
【Java SE】缓存池和常量池的区别
java·spring·缓存
Code blocks3 小时前
Firms-Java:NASA火灾卫星数据Java客户端开源
java·spring boot·后端·开源软件
树獭非懒3 小时前
Google A2UI:让 AI 智能体「开口说界面」
前端·人工智能·后端
Wect3 小时前
LeetCode 4. 寻找两个正序数组的中位数:二分优化思路详解
前端·算法·typescript
李剑一3 小时前
纯干货,前端字体极致优化!谷歌、阿里、字节、腾讯都在用的终极解决方案,Vue3 + Vite 直接抄,页面提速不妥协!
前端·vue.js·面试
月亮!3 小时前
6大AI测试工具极限压测:微软TuringAI竟率先崩溃
java·人工智能·python·测试工具·microsoft·云原生·压力测试
memeflyfly3 小时前
Vercel 自动部署完全指南:从配置到问题排查
前端·前端工程化