Skip to content

Spring Boot 实战

Spring Boot 是 Spring 框架的一个子项目,它简化了 Spring 应用的开发和部署。本文将介绍 Spring Boot 的核心特性和使用方法。

1. 基本概念

什么是 Spring Boot

Spring Boot 是一个基于 Spring 框架的快速开发框架,它的设计目标是简化 Spring 应用的初始化和开发过程。Spring Boot 提供了自动配置、嵌入式服务器、 starter 依赖等特性,使得开发者可以更专注于业务逻辑的实现。

Spring Boot 的特点

  • 自动配置:根据项目依赖自动配置应用
  • 嵌入式服务器:内置 Tomcat、Jetty 等服务器
  • starter 依赖:提供一站式的依赖管理
  • 生产就绪:提供健康检查、指标监控等功能
  • 无代码生成:不需要生成代码或 XML 配置

2. 环境搭建

安装 JDK

Spring Boot 3.0+ 需要 JDK 17 或更高版本,Spring Boot 2.7 需要 JDK 8 或更高版本。

构建工具

Spring Boot 支持 Maven 和 Gradle 作为构建工具。

创建 Spring Boot 项目

使用 Spring Initializr

  1. 访问 Spring Initializr
  2. 填写项目信息(Group、Artifact、Name 等)
  3. 选择依赖(如 Spring Web、Spring Data JPA 等)
  4. 点击 "Generate" 下载项目

使用 IDE

大多数 IDE(如 IntelliJ IDEA、Eclipse)都支持直接创建 Spring Boot 项目。

3. 核心特性

自动配置

Spring Boot 会根据项目的依赖自动配置应用。例如,如果项目依赖了 spring-boot-starter-web,Spring Boot 会自动配置 Tomcat 服务器和 Spring MVC。

嵌入式服务器

Spring Boot 内置了 Tomcat、Jetty、Undertow 等服务器,不需要单独部署。

Starter 依赖

Starter 依赖是一组相关依赖的集合,它简化了依赖管理。例如,spring-boot-starter-web 包含了 Spring MVC、Tomcat 等依赖。

配置管理

Spring Boot 支持多种配置方式:

  • application.properties:属性文件
  • application.yml:YAML 文件
  • 环境变量:系统环境变量
  • 命令行参数:启动时的命令行参数

健康检查

Spring Boot 提供了健康检查端点,可以监控应用的状态。

指标监控

Spring Boot 提供了指标监控功能,可以收集应用的运行指标。

4. 项目结构

典型的 Spring Boot 项目结构

my-spring-boot-app/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           ├── Application.java         # 应用入口
│   │   │           ├── controller/             # 控制器
│   │   │           ├── service/                # 服务层
│   │   │           ├── repository/             # 数据访问层
│   │   │           └── model/                  # 数据模型
│   │   └── resources/
│   │       ├── application.properties         # 配置文件
│   │       └── static/                        # 静态资源
│   └── test/
│       └── java/
│           └── com/
│               └── example/
│                   └── ApplicationTests.java   # 测试类
├── pom.xml                                     # Maven 配置

应用入口

java
package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

5. 核心注解

@SpringBootApplication

这是一个组合注解,包含了 @Configuration@EnableAutoConfiguration@ComponentScan

@RestController

标记一个类为 REST 控制器,它是 @Controller@ResponseBody 的组合。

@RequestMapping

映射 HTTP 请求到控制器方法。

@GetMapping, @PostMapping, @PutMapping, @DeleteMapping

分别映射 GET、POST、PUT、DELETE 请求。

@Autowired

自动注入依赖。

@Service

标记一个类为服务层组件。

@Repository

标记一个类为数据访问层组件。

@Entity

标记一个类为 JPA 实体。

@Table

指定实体对应的数据库表名。

@Id

标记实体的主键。

@GeneratedValue

指定主键的生成策略。

6. Web 开发

创建 RESTful API

java
package com.example.controller;

import com.example.model.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping
    public List<User> getUsers() {
        return userService.getAllUsers();
    }
    
    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getUserById(id);
    }
    
    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.createUser(user);
    }
    
    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        return userService.updateUser(id, user);
    }
    
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
    }
}

服务层

java
package com.example.service;

import com.example.model.User;
import com.example.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
    
    public User getUserById(Long id) {
        Optional<User> user = userRepository.findById(id);
        return user.orElseThrow(() -> new RuntimeException("User not found"));
    }
    
    public User createUser(User user) {
        return userRepository.save(user);
    }
    
    public User updateUser(Long id, User user) {
        User existingUser = getUserById(id);
        existingUser.setName(user.getName());
        existingUser.setEmail(user.getEmail());
        return userRepository.save(existingUser);
    }
    
    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }
}

数据访问层

java
package com.example.repository;

import com.example.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
    User findByEmail(String email);
}

数据模型

java
package com.example.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    
    // getter 和 setter 方法
    // ...
}

配置文件

properties
# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

7. 数据访问

Spring Data JPA

Spring Data JPA 是 Spring 提供的 JPA 简化工具,它可以自动生成 CRUD 方法。

基本用法

  1. 添加依赖
xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>
  1. 配置数据源
properties
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
  1. 创建实体
java
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    // ...
}
  1. 创建 Repository
java
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByName(String name);
    User findByEmail(String email);
}

Spring Data MongoDB

Spring Data MongoDB 是 Spring 提供的 MongoDB 简化工具。

基本用法

  1. 添加依赖
xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
  1. 配置数据源
properties
spring.data.mongodb.uri=mongodb://localhost:27017/mydb
  1. 创建实体
java
@Document
public class User {
    @Id
    private String id;
    private String name;
    private String email;
    // ...
}
  1. 创建 Repository
java
public interface UserRepository extends MongoRepository<User, String> {
    List<User> findByName(String name);
    User findByEmail(String email);
}

8. 安全

Spring Security

Spring Security 是 Spring 提供的安全框架,它可以处理认证和授权。

基本用法

  1. 添加依赖
xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. 配置安全
java
package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .requestMatchers("/api/public/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .and()
            .httpBasic();
        return http.build();
    }
    
    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}

9. 测试

单元测试

java
package com.example.service;

import com.example.model.User;
import com.example.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

@SpringBootTest
public class UserServiceTest {
    
    @Mock
    private UserRepository userRepository;
    
    @InjectMocks
    private UserService userService;
    
    @Test
    public void testGetUserById() {
        User user = new User();
        user.setId(1L);
        user.setName("John");
        user.setEmail("john@example.com");
        
        Mockito.when(userRepository.findById(1L)).thenReturn(Optional.of(user));
        
        User result = userService.getUserById(1L);
        assertEquals("John", result.getName());
        assertEquals("john@example.com", result.getEmail());
    }
    
    @Test
    public void testGetUserByIdNotFound() {
        Mockito.when(userRepository.findById(1L)).thenReturn(Optional.empty());
        assertThrows(RuntimeException.class, () -> userService.getUserById(1L));
    }
}

集成测试

java
package com.example;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    public void testGetUsers() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/api/users"))
            .andExpect(MockMvcResultMatchers.status().isOk());
    }
}

10. 部署

打包

使用 Maven 或 Gradle 打包应用:

bash
# Maven
mvn clean package

# Gradle
gradle clean build

运行

bash
java -jar target/my-spring-boot-app-1.0.0.jar

Docker 部署

  1. 创建 Dockerfile
dockerfile
FROM openjdk:17-jdk-slim
COPY target/my-spring-boot-app-1.0.0.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
  1. 构建 Docker 镜像
bash
docker build -t my-spring-boot-app .
  1. 运行 Docker 容器
bash
docker run -p 8080:8080 my-spring-boot-app

11. 最佳实践

项目结构

  • 遵循 Maven/Gradle 的标准项目结构
  • 按功能模块组织代码
  • 使用包名来区分不同的功能模块

代码风格

  • 遵循 Java 代码风格规范
  • 使用 Lombok 减少样板代码
  • 使用 SLF4J 进行日志记录

配置管理

  • 使用 application.yml 代替 application.properties
  • 使用 Spring Profiles 管理不同环境的配置
  • 敏感配置使用环境变量或加密

异常处理

  • 统一异常处理
  • 使用 @ControllerAdvice 处理全局异常
  • 返回友好的错误信息

性能优化

  • 使用缓存减少数据库查询
  • 使用异步处理提高响应速度
  • 优化数据库查询

安全

  • 使用 HTTPS
  • 实现 CSRF 保护
  • 定期更新依赖

12. 常见问题与解决方案

端口冲突

问题:应用启动时端口被占用 解决方案:修改 application.properties 中的 server.port 配置。

数据库连接失败

问题:无法连接到数据库 解决方案:检查数据库配置是否正确,数据库服务是否运行。

依赖冲突

问题:依赖版本冲突 解决方案:使用 Maven Dependency Plugin 分析依赖,排除冲突的依赖。

启动慢

问题:应用启动时间长 解决方案

  • 减少不必要的依赖
  • 使用 Spring Boot DevTools 进行热部署
  • 优化自动配置

13. 实践示例

构建一个简单的博客系统

1. 创建项目

使用 Spring Initializr 创建一个 Spring Boot 项目,添加以下依赖:

  • Spring Web
  • Spring Data JPA
  • MySQL Driver
  • Spring Security
  • Thymeleaf

2. 数据模型

java
@Entity
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String content;
    private LocalDateTime createdDate;
    
    @ManyToOne
    private User author;
    
    // getter 和 setter 方法
    // ...
}

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private String email;
    
    // getter 和 setter 方法
    // ...
}

3. Repository

java
public interface PostRepository extends JpaRepository<Post, Long> {
    List<Post> findByAuthorId(Long authorId);
}

public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}

4. 服务层

java
@Service
public class PostService {
    @Autowired
    private PostRepository postRepository;
    
    public List<Post> getAllPosts() {
        return postRepository.findAll();
    }
    
    public Post getPostById(Long id) {
        return postRepository.findById(id).orElseThrow(() -> new RuntimeException("Post not found"));
    }
    
    public Post createPost(Post post) {
        post.setCreatedDate(LocalDateTime.now());
        return postRepository.save(post);
    }
    
    public Post updatePost(Long id, Post post) {
        Post existingPost = getPostById(id);
        existingPost.setTitle(post.getTitle());
        existingPost.setContent(post.getContent());
        return postRepository.save(existingPost);
    }
    
    public void deletePost(Long id) {
        postRepository.deleteById(id);
    }
    
    public List<Post> getPostsByAuthor(Long authorId) {
        return postRepository.findByAuthorId(authorId);
    }
}

5. 控制器

java
@Controller
public class PostController {
    @Autowired
    private PostService postService;
    @Autowired
    private UserService userService;
    
    @GetMapping("/")
    public String home(Model model) {
        model.addAttribute("posts", postService.getAllPosts());
        return "home";
    }
    
    @GetMapping("/post/{id}")
    public String getPost(@PathVariable Long id, Model model) {
        model.addAttribute("post", postService.getPostById(id));
        return "post";
    }
    
    @GetMapping("/post/new")
    public String createPostForm(Model model) {
        model.addAttribute("post", new Post());
        return "create-post";
    }
    
    @PostMapping("/post")
    public String createPost(@ModelAttribute Post post, Principal principal) {
        User user = userService.findByUsername(principal.getName());
        post.setAuthor(user);
        postService.createPost(post);
        return "redirect:/";
    }
    
    @GetMapping("/post/{id}/edit")
    public String editPostForm(@PathVariable Long id, Model model) {
        model.addAttribute("post", postService.getPostById(id));
        return "edit-post";
    }
    
    @PostMapping("/post/{id}")
    public String updatePost(@PathVariable Long id, @ModelAttribute Post post) {
        postService.updatePost(id, post);
        return "redirect:/post/" + id;
    }
    
    @PostMapping("/post/{id}/delete")
    public String deletePost(@PathVariable Long id) {
        postService.deletePost(id);
        return "redirect:/";
    }
}

6. 模板

创建 Thymeleaf 模板文件:

  • home.html:首页,显示所有博客文章
  • post.html:文章详情页
  • create-post.html:创建文章表单
  • edit-post.html:编辑文章表单

7. 配置

properties
spring.datasource.url=jdbc:mysql://localhost:3306/blog
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
spring.thymeleaf.cache=false

14. 总结

Spring Boot 是一个强大的快速开发框架,它简化了 Spring 应用的开发和部署过程。通过学习 Spring Boot 的核心特性和使用方法,我们可以更高效地构建和部署 Java 应用。

Spring Boot 的核心特性包括:

  • 自动配置
  • 嵌入式服务器
  • starter 依赖
  • 配置管理
  • 健康检查和指标监控

通过遵循 Spring Boot 的最佳实践,我们可以构建出高质量、可维护的 Java 应用。