作为Java开发者,Spring Boot已经成为我们日常开发的标配工具。记得我第一次接触Spring Boot时,被它"约定优于配置"的理念深深吸引——再也不用写那些繁琐的XML配置了!经过多个项目的实战积累,我总结出一套高效的Spring Boot开发流程,今天就来和大家详细分享。
Spring Boot 3.x需要JDK 17+,而2.x版本兼容JDK 8。我推荐使用JDK 17 LTS版本,它平衡了新特性和稳定性。安装后务必检查环境变量:
bash复制java -version
如果显示类似"17.0.3"的版本号,说明安装成功。建议使用Amazon Corretto或OpenJDK发行版,它们都经过充分测试且免费商用。
IntelliJ IDEA Ultimate版对Spring Boot支持最好(社区版也够用)。安装后需要:
提示:IDEA的Spring Assistant插件可以可视化查看Bean依赖关系,调试时特别有用
Maven和Gradle各有优势:
对于新项目,我通常这样选择:
bash复制小型项目 → Maven
大型微服务 → Gradle
配置国内镜像加速依赖下载(Maven示例):
xml复制<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
官方初始化工具(https://start.spring.io)可以快速生成项目骨架。关键配置项:
标准Maven项目结构:
code复制src/
├── main/
│ ├── java/
│ │ └── com/example/
│ │ ├── config/ # 配置类
│ │ ├── controller/ # 控制器
│ │ ├── service/ # 服务层
│ │ ├── repository/ # 数据访问
│ │ └── entity/ # 实体类
│ └── resources/
│ ├── static/ # 静态资源
│ ├── templates/ # 模板文件
│ └── application.yml # 主配置
└── test/ # 测试代码
经验:保持包结构扁平化,避免过深嵌套。按功能而非层级分包更利于维护
使用JPA注解定义数据模型:
java复制@Entity
@Table(name = "sys_user") // 显式指定表名
@Data // Lombok注解,自动生成getter/setter
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 32, nullable = false)
private String username;
@JsonIgnore // 序列化时忽略密码字段
private String password;
@CreationTimestamp // 自动设置创建时间
private LocalDateTime createTime;
}
注意:实体类应该纯粹表示数据,不要包含业务逻辑
Spring Data JPA提供强大Repository支持:
java复制public interface UserRepository extends JpaRepository<User, Long> {
// 方法名自动推导查询
Optional<User> findByUsername(String username);
// 自定义JPQL查询
@Query("SELECT u FROM User u WHERE u.createTime > :startDate")
List<User> findRecentUsers(@Param("startDate") LocalDateTime startDate);
// 原生SQL查询
@Query(value = "SELECT * FROM users WHERE status = 1", nativeQuery = true)
List<User> findActiveUsers();
}
服务接口与实现分离:
java复制public interface UserService {
UserDTO createUser(CreateUserRequest request);
// 其他业务方法...
}
@Service
@RequiredArgsConstructor // Lombok自动注入
@Transactional(readOnly = true) // 默认只读
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
@Override
@Transactional // 写操作需要单独开启
public UserDTO createUser(CreateUserRequest request) {
if (userRepository.existsByUsername(request.getUsername())) {
throw new BusinessException("用户名已存在");
}
User user = new User();
user.setUsername(request.getUsername());
user.setPassword(passwordEncoder.encode(request.getPassword()));
return UserDTO.from(userRepository.save(user));
}
}
RESTful风格API示例:
java复制@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Result<UserDTO> createUser(@Valid @RequestBody CreateUserRequest request) {
return Result.success(userService.createUser(request));
}
@GetMapping("/{id}")
public Result<UserDTO> getUser(@PathVariable Long id) {
return Result.success(userService.getUserById(id));
}
// 统一异常处理
@ExceptionHandler(BusinessException.class)
public Result<?> handleException(BusinessException e) {
return Result.fail(e.getMessage());
}
}
application.yml支持profile分离:
yaml复制# application.yml
spring:
profiles:
active: dev # 默认使用dev配置
# application-dev.yml
server:
port: 8080
datasource:
url: jdbc:h2:mem:testdb
# application-prod.yml
server:
port: 80
datasource:
url: jdbc:mysql://prod-db:3306/app
username: ${DB_USER}
password: ${DB_PASS}
提示:敏感信息应该使用环境变量或配置中心注入
Logback高级配置示例:
xml复制<!-- logback-spring.xml -->
<configuration>
<property name="LOG_PATH" value="./logs"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.example" level="DEBUG"/>
<logger name="org.hibernate.SQL" level="DEBUG"/>
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</configuration>
使用JUnit 5 + Mockito:
java复制@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserServiceImpl userService;
@Test
void createUser_shouldSuccess() {
CreateUserRequest request = new CreateUserRequest("test", "123456");
when(userRepository.existsByUsername("test")).thenReturn(false);
when(userRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
UserDTO result = userService.createUser(request);
assertNotNull(result);
assertEquals("test", result.getUsername());
verify(userRepository).save(any());
}
}
SpringBootTest完整示例:
java复制@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@Transactional // 测试后回滚数据
class UserIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@Test
void createAndGetUser() throws Exception {
CreateUserRequest request = new CreateUserRequest("integration", "pass123");
// 创建用户
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isCreated());
// 查询用户
mockMvc.perform(get("/api/users/integration"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.username").value("integration"));
}
}
Maven打包配置示例:
xml复制<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<!-- 生成可执行JAR -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.example.Application</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Dockerfile最佳实践:
dockerfile复制# 使用多阶段构建减小镜像体积
FROM eclipse-temurin:17-jdk-jammy as builder
WORKDIR /app
COPY . .
RUN ./mvnw clean package
FROM eclipse-temurin:17-jre-jammy
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
构建和运行命令:
bash复制docker build -t myapp .
docker run -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod myapp
我在实际项目中发现,合理的线程池配置对高并发场景尤为重要:
yaml复制server:
tomcat:
threads:
max: 200
min-spare: 10
Spring Boot虽然开箱即用,但要真正发挥其威力,需要深入理解其设计理念。经过多个项目的实践,我总结出几个关键点:保持配置简洁、合理分层代码、重视测试覆盖、监控先行。这些经验帮助我构建了多个稳定运行的生产系统。