导读:作为SpringBoot系列的第一篇文章,本文将带你快速入门SpringBoot,了解其核心概念和基本原理,并通过一个实例演示如何创建你的第一个SpringBoot应用。
SpringBoot是Spring团队推出的一个用于简化Spring应用开发的框架。它消除了传统Spring应用中繁琐的配置,提供了一种快速创建可独立运行、生产级别Spring应用的方式。
在传统Spring应用开发中,我们面临这些问题:
而SpringBoot通过其设计理念解决了这些问题:
传统Spring开发 vs SpringBoot开发
┌─────────────────────────┐ ┌─────────────────────────┐
│ 1. 创建Maven/Gradle项目 │ │ 1. 创建SpringBoot项目 │
│ 2. 添加依赖 │ │ 2. 选择Starter依赖 │
│ 3. 配置web.xml │ │ 3. 编写业务代码 │
│ 4. 配置Spring XML │ │ 4. 运行应用 │
│ 5. 配置数据源、事务等 │ └─────────────────────────┘
│ 6. 部署到服务器 │
└─────────────────────────┘
以IDEA为例:
src/main/java
└── com.example.demo
├── DemoApplication.java // 启动类
├── controller // 控制器
├── service // 服务层
├── repository // 数据访问层
└── model // 数据模型
src/main/resources
├── application.properties // 配置文件
├── static // 静态资源
└── templates // 模板文件
src/test // 测试代码
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootApplication
注解是一个组合注解,它包含:
@SpringBootConfiguration
:标识该类为配置类@EnableAutoConfiguration
:启用自动配置@ComponentScan
:启用组件扫描让我们创建一个简单的用户管理API:
package com.example.demo.model;
public class User {
private Long id;
private String name;
private String email;
// 构造函数、getter和setter省略
public User(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
// Getter和Setter
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
package com.example.demo.controller;
import com.example.demo.model.User;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
@RestController
@RequestMapping("/api/users")
public class UserController {
private final ConcurrentHashMap<Long, User> users = new ConcurrentHashMap<>();
private final AtomicLong idGenerator = new AtomicLong();
// 获取所有用户
@GetMapping
public List<User> getAllUsers() {
return new ArrayList<>(users.values());
}
// 根据ID获取用户
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
User user = users.get(id);
if (user == null) {
throw new RuntimeException("User not found with id: " + id);
}
return user;
}
// 创建用户
@PostMapping
public User createUser(@RequestBody User user) {
Long id = idGenerator.incrementAndGet();
user.setId(id);
users.put(id, user);
return user;
}
// 更新用户
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
if (!users.containsKey(id)) {
throw new RuntimeException("User not found with id: " + id);
}
user.setId(id);
users.put(id, user);
return user;
}
// 删除用户
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
if (!users.containsKey(id)) {
throw new RuntimeException("User not found with id: " + id);
}
users.remove(id);
}
}
package com.example.demo.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException ex) {
ErrorResponse error = new ErrorResponse(HttpStatus.NOT_FOUND.value(), ex.getMessage());
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
public static class ErrorResponse {
private int status;
private String message;
public ErrorResponse(int status, String message) {
this.status = status;
this.message = message;
}
// Getter和Setter
public int getStatus() { return status; }
public void setStatus(int status) { this.status = status; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
}
# src/main/resources/application.properties
server.port=8080
spring.application.name=user-service
# 日志配置
logging.level.root=INFO
logging.level.com.example.demo=DEBUG
# Jackson配置
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
执行主类DemoApplication
的main
方法,或使用Maven/Gradle命令:
# Maven
mvn spring-boot:run
# Gradle
gradle bootRun
使用Postman或curl测试API:
# 创建用户
curl -X POST http://localhost:8080/api/users -H "Content-Type: application/json" -d '{"name":"张三","email":"[email protected]"}'
# 获取所有用户
curl http://localhost:8080/api/users
# 获取单个用户
curl http://localhost:8080/api/users/1
# 更新用户
curl -X PUT http://localhost:8080/api/users/1 -H "Content-Type: application/json" -d '{"name":"张三(已更新)","email":"[email protected]"}'
# 删除用户
curl -X DELETE http://localhost:8080/api/users/1
SpringBoot支持多种配置文件格式:
application.properties:键值对格式
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/test
application.yml:YAML格式,层次结构更清晰
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
SpringBoot配置的加载顺序(优先级从高到低):
System.getProperties()
)application-{profile}.properties
外部配置application.properties
外部配置@Configuration
类上的@PropertySource
使用profile可以为不同环境提供不同的配置:
application.properties # 主配置文件
application-dev.properties # 开发环境
application-test.properties # 测试环境
application-prod.properties # 生产环境
激活指定环境:
# 在application.properties中指定
spring.profiles.active=dev
# 或通过命令行参数
java -jar app.jar --spring.profiles.active=prod
可以将配置文件中的属性绑定到Java对象:
# application.properties
app.name=用户服务
app.description=用户管理系统
app.version=1.0.0
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private String description;
private String version;
// Getter和Setter
}
SpringBoot的自动配置是其核心特性,它能够根据classpath中的依赖自动配置Spring应用。
自动配置主要通过以下注解实现:
@EnableAutoConfiguration
:启用自动配置@Conditional
系列注解:条件化配置@ConfigurationProperties
:外部化配置@SpringBootApplication
@EnableAutoConfiguration
触发自动配置SpringFactoriesLoader
加载META-INF/spring.factories
中的配置类@Conditional
条件,决定哪些配置生效可以通过以下方式查看自动配置报告:
# 在application.properties中添加
debug=true
启动应用后,控制台会打印自动配置报告,显示哪些自动配置生效了,哪些没有生效。
问题:启动时报端口被占用错误
解决:修改配置文件中的端口
server.port=8081
问题:依赖版本冲突导致应用无法启动
解决:使用Maven的
或排除冲突依赖
<dependency>
<groupId>org.examplegroupId>
<artifactId>example-libartifactId>
<exclusions>
<exclusion>
<groupId>org.conflictinggroupId>
<artifactId>conflict-libartifactId>
exclusion>
exclusions>
dependency>
问题:预期的自动配置没有生效
解决:
本文介绍了SpringBoot的基本概念、核心特性以及如何创建第一个SpringBoot应用。通过实战案例,我们学习了如何构建RESTful API,并了解了SpringBoot的配置和自动配置原理。
在下一篇文章中,我们将深入探讨SpringBoot的RESTful API开发,包括请求参数处理、响应封装、数据校验、文档生成等高级特性。
预告:下一篇将详细讲解《SpringBoot RESTful API开发详解》,敬请期待!
系列目录:SpringBoot从入门到精通系列索引
交流讨论:欢迎在评论区留言讨论,共同进步!