Spring Boot从入门到精通(完整版)
**# Spring Boot从入门到精通(完整版)
前言
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。
本文将从入门基础讲到高级原理,涵盖实际项目开发中的核心技术和最佳实践,帮助读者真正掌握Spring Boot的精髓。
第一章:Spring Boot入门
1.1 Spring Boot简介
Spring Boot是基于Spring框架开发的,它并不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式。它通过“约定优于配置”的理念,让你的项目快速运行起来。
Spring Boot的核心特点:
- 可以创建独立的Spring应用程序
- 内嵌Tomcat、Jetty等Servlet容器
- 提供自动配置的“starter”依赖
- 尽可能自动配置Spring
- 提供生产就绪功能,如指标、健康检查等
- 无需生成代码,无需XML配置
1.2 开发环境准备
1.2.1 安装JDK
Spring Boot 2.x需要JDK 8或更高版本,Spring Boot 3.x需要JDK 17或更高版本。推荐使用JDK 17(LTS长期支持版本)。
1.2.2 安装Maven或Gradle
推荐使用Maven作为构建工具。
Maven配置(settings.xml):
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
1.2.3 安装IDE
推荐使用IntelliJ IDEA(社区版或终极版)或Eclipse。
1.3 创建第一个Spring Boot项目
方式一:使用Spring Initializr
- 访问 https://start.spring.io/
- 选择项目类型(Maven/Gradle)
- 选择语言(Java/Kotlin/Groovy)
- 选择Spring Boot版本(推荐2.7.x或3.x)
- 填写项目信息(Group、Artifact)
- 添加依赖(Spring Web)
- 点击生成,下载项目压缩包
方式二:使用IDEA创建
- 打开IDEA,选择New Project
- 选择Spring Initializr
- 填写项目信息
- 选择依赖
- 完成创建
1.4 项目结构解析
demo
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ ├── controller # 控制器层
│ │ │ ├── service # 服务层
│ │ │ ├── repository # 数据访问层
│ │ │ ├── entity # 实体类
│ │ │ ├── config # 配置类
│ │ │ └── DemoApplication.java # 主类
│ │ └── resources
│ │ ├── application.yml # 配置文件
│ │ ├── static # 静态资源
│ │ └── templates # 模板文件
│ └── test
│ └── java
│ └── com
│ └── example
│ └── demo
│ └── DemoApplicationTests.java
└── pom.xml
主要文件说明:
DemoApplication.java:主类,程序入口application.yml:配置文件(推荐使用yml格式)pom.xml:Maven配置文件
1.5 编写第一个Controller
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
1.6 运行项目
- 直接运行主类的main方法
- 或使用Maven命令:
mvn spring-boot:run - 或打包后运行:
mvn package && java -jar target/demo-0.0.1-SNAPSHOT.jar - 访问 http://localhost:8080/hello
第二章:Spring Boot核心配置
2.1 配置文件
Spring Boot支持两种配置文件格式:
application.propertiesapplication.yml(推荐)
properties格式示例
# 服务器端口
server.port=8080
# 应用名称
spring.application.name=demo
# 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=123456
yml格式示例
server:
port: 8080
spring:
application:
name: demo
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
2.2 自定义配置
2.2.1 使用@Value注入
@RestController
public class MyController {
@Value("${myapp.name}")
private String appName;
@Value("${myapp.description:默认描述}")
private String description;
@GetMapping("/info")
public String info() {
return appName + ": " + description;
}
}
2.2.2 使用@ConfigurationProperties
@Component
@ConfigurationProperties(prefix = "myapp")
public class MyAppProperties {
private String name;
private String description;
private int version;
// getters and setters
}
2.3 多环境配置
创建不同环境的配置文件:
application-dev.yml(开发环境)application-test.yml(测试环境)application-prod.yml(生产环境)
在主配置文件中激活:
spring:
profiles:
active: dev
各环境配置示例:
# application-dev.yml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/dev_db
username: root
password: 123456
# application-prod.yml
server:
port: 80
spring:
datasource:
url: jdbc:mysql://prod-host:3306/prod_db
username: prod_user
password: ${DB_PASSWORD} # 使用环境变量
第三章:Spring Boot Web开发
3.1 RESTful API开发
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public Result<List<User>> getAllUsers() {
return Result.success(userService.findAll());
}
@GetMapping("/{id}")
public Result<User> getUserById(@PathVariable Long id) {
return Result.success(userService.findById(id));
}
@PostMapping
public Result<User> createUser(@Valid @RequestBody User user) {
return Result.success(userService.save(user));
}
@PutMapping("/{id}")
public Result<User> updateUser(@PathVariable Long id, @Valid @RequestBody User user) {
user.setId(id);
return Result.success(userService.save(user));
}
@DeleteMapping("/{id}")
public Result<Void> deleteUser(@PathVariable Long id) {
userService.deleteById(id);
return Result.success();
}
}
统一返回结果类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> {
private Integer code;
private String message;
private T data;
public static <T> Result<T> success(T data) {
return new Result<>(200, "操作成功", data);
}
public static <T> Result<T> success() {
return success(null);
}
public static <T> Result<T> error(String message) {
return new Result<>(500, message, null);
}
}
3.2 参数校验
添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
使用校验注解:
@Data
public class User {
@NotNull(message = "ID不能为空")
private Long id;
@NotBlank(message = "用户名不能为空")
@Size(min = 3, max = 20, message = "用户名长度必须在3-20之间")
private String username;
@Email(message = "邮箱格式不正确")
private String email;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
}
3.3 全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Map<String, String>> handleValidationException(MethodArgumentNotValidException e) {
Map<String, String> errors = new HashMap<>();
e.getBindingResult().getFieldErrors().forEach(error -> {
errors.put(error.getField(), error.getDefaultMessage());
});
return Result.error("参数校验失败");
}
@ExceptionHandler(BusinessException.class)
public Result<Void> handleBusinessException(BusinessException e) {
return Result.error(e.getMessage());
}
@ExceptionHandler(Exception.class)
public Result<Void> handleException(Exception e) {
log.error("系统异常", e);
return Result.error("系统异常,请联系管理员");
}
}
自定义业务异常:
@Getter
public class BusinessException extends RuntimeException {
private Integer code;
public BusinessException(String message) {
super(message);
this.code = 500;
}
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
}
}
3.4 拦截器配置
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
if (token == null || !validateToken(token)) {
response.setStatus(401);
response.getWriter().write("未登录或登录已过期");
return false;
}
return true;
}
private boolean validateToken(String token) {
// 验证token逻辑
return true;
}
}
注册拦截器:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/login", "/api/register");
}
}
第四章:Spring Boot数据访问
4.1 集成MyBatis-Plus(推荐)
MyBatis-Plus是MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。
添加依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
配置数据源
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.demo.entity
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
编写实体类
@Data
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String username;
private String email;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableLogic
private Integer deleted;
}
编写Mapper
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 自定义SQL方法
@Select("SELECT * FROM user WHERE age > #{age}")
List<User> selectByAgeGreaterThan(@Param("age") Integer age);
}
编写Service
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User findById(Long id) {
return userMapper.selectById(id);
}
public List<User> findAll() {
return userMapper.selectList(null);
}
public User save(User user) {
if (user.getId() == null) {
userMapper.insert(user);
} else {
userMapper.updateById(user);
}
return user;
}
public void deleteById(Long id) {
userMapper.deleteById(id);
}
public List<User> findByCondition(String username, Integer minAge) {
LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
if (username != null) {
wrapper.like(User::getUsername, username);
}
if (minAge != null) {
wrapper.ge(User::getAge, minAge);
}
wrapper.orderByDesc(User::getCreateTime);
return userMapper.selectList(wrapper);
}
}
自动填充配置
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
4.2 分页插件配置
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
分页查询示例:
public Page<User> findByPage(int pageNum, int pageSize, String username) {
Page<User> page = new Page<>(pageNum, pageSize);
LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
if (username != null) {
wrapper.like(User::getUsername, username);
}
return userMapper.selectPage(page, wrapper);
}
4.3 Spring Data JPA(备选方案)
如果你更喜欢JPA风格的数据访问,可以使用Spring Data JPA。
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
配置JPA
spring:
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.MySQL8Dialect
编写实体类
@Entity
@Table(name = "user")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String email;
private Integer age;
@Column(name = "create_time")
private LocalDateTime createTime;
}
编写Repository
public interface UserRepository extends JpaRepository<User, Long> {
// 方法名查询
List<User> findByUsername(String username);
Optional<User> findByEmail(String email);
List<User> findByAgeGreaterThan(Integer age);
// @Query查询
@Query("SELECT u FROM User u WHERE u.username LIKE %:keyword% OR u.email LIKE %:keyword%")
List<User> searchByKeyword(@Param("keyword") String keyword);
}
第五章:Spring Security安全认证
5.1 Spring Security基础配置
5.1.1 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
5.1.2 JWT工具类
@Component
public class JwtTokenUtil {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
public String generateToken(String username) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
return Jwts.builder()
.setSubject(username)
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(Keys.hmacShaKeyFor(secret.getBytes()), SignatureAlgorithm.HS256)
.compact();
}
public String getUsernameFromToken(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
.build()
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
.build()
.parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
}
5.1.3 安全配置类
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeHttpRequests()
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
5.1.4 JWT认证过滤器
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
String username = jwtTokenUtil.getUsernameFromToken(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(token)) {
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
filterChain.doFilter(request, response);
}
}
5.1.5 认证Controller
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private UserService userService;
@PostMapping("/login")
public Result<Map<String, String>> login(@RequestBody LoginRequest request) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String token = jwtTokenUtil.generateToken(request.getUsername());
Map<String, String> result = new HashMap<>();
result.put("token", token);
return Result.success(result);
}
@PostMapping("/register")
public Result<Void> register(@RequestBody RegisterRequest request) {
userService.register(request);
return Result.success();
}
}
第六章:Redis缓存集成
6.1 Redis基础配置
6.1.1 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
6.1.2 配置文件
spring:
redis:
host: localhost
port: 6379
password:
database: 0
timeout: 3000ms
lettuce:
pool:
max-active: 8
max-wait: -1ms
max-idle: 8
min-idle: 0
6.1.3 Redis配置类
@Configuration
@EnableCaching
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =
new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
}
6.2 缓存注解使用
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Cacheable(value = "user", key = "#id")
public User findById(Long id) {
System.out.println("从数据库查询,不是缓存");
return userMapper.selectById(id);
}
@CachePut(value = "user", key = "#user.id")
public User save(User user) {
if (user.getId() == null) {
userMapper.insert(user);
} else {
userMapper.updateById(user);
}
return user;
}
@CacheEvict(value = "user", key = "#id")
public void deleteById(Long id) {
userMapper.deleteById(id);
}
@CacheEvict(value = "user", allEntries = true)
public void clearAllCache() {
}
}
6.3 Redis分布式锁
@Service
public class DistributedLockService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String LOCK_PREFIX = "lock:";
private static final long DEFAULT_EXPIRE_TIME = 30;
public boolean tryLock(String key, String value) {
return Boolean.TRUE.equals(
redisTemplate.opsForValue()
.setIfAbsent(LOCK_PREFIX + key, value,
DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS)
);
}
public boolean releaseLock(String key, String value) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] " +
"then return redis.call('del', KEYS[1]) " +
"else return 0 end";
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
redisScript.setScriptText(script);
redisScript.setResultType(Long.class);
return 1L.equals(redisTemplate.execute(
redisScript, Collections.singletonList(LOCK_PREFIX + key), value)
);
}
}
第七章:Spring Boot核心原理
7.1 自动配置原理深度解析
Spring Boot的最大特点是"自动配置",其核心是@EnableAutoConfiguration注解。
7.1.1 @EnableAutoConfiguration的工作原理
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String[] exclude() default {};
Class<?>[] excludeName() default {};
}
关键组件:
- AutoConfigurationImportSelector:负责加载自动配置类
- SpringFactoriesLoader:从
META-INF/spring.factories加载配置 - Condition注解:
@ConditionalOnClass、@ConditionalOnMissingBean等
7.1.2 自动配置加载流程
启动Spring Boot应用
↓
@SpringBootApplication → @EnableAutoConfiguration
↓
AutoConfigurationImportSelector.selectImports()
↓
SpringFactoriesLoader.loadFactoryNames()
↓
读取 META-INF/spring.factories
↓
过滤自动配置类(@Conditional条件判断)
↓
加载符合条件的自动配置类
↓
创建Bean并注入Spring容器
7.1.3 自定义自动配置
创建自定义starter:
第一步:创建自动配置类
@Configuration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService(MyProperties properties) {
return new MyService(properties);
}
}
第二步:创建配置属性类
@ConfigurationProperties(prefix = "myapp")
public class MyProperties {
private String name = "default";
private int timeout = 3000;
// getters and setters
}
第三步:创建spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.myautoconfig.MyAutoConfiguration
7.2 Spring Boot启动流程详解
7.2.1 SpringApplication.run()执行流程
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
7.2.2 关键扩展点
| 扩展点 | 作用 | 示例 |
|---|---|---|
| SpringApplicationRunListener | 监听启动生命周期 | 自定义启动日志 |
| ApplicationContextInitializer | 刷新前初始化context | 设置激活profile |
| ApplicationRunner | 启动后执行 | 初始化数据 |
| CommandLineRunner | 启动后执行 | 接收命令行参数 |
第八章:生产环境最佳实践
8.1 Actuator监控端点
8.1.1 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
8.1.2 配置暴露端点
management:
endpoints:
web:
exposure:
include: health,info,metrics,env
endpoint:
health:
show-details: always
8.1.3 常用端点
/actuator/health:健康检查/actuator/info:应用信息/actuator/metrics:指标信息/actuator/env:环境变量
8.2 日志配置
8.2.1 logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<springProperty scope="context" name**
更多推荐




所有评论(0)