SpringBoot 集成使用
SpringBoot 版本为 2.x, 2.4.0 开始版本号没有 .RELEASE 后缀
推荐 idea 插件
- Maven Helper: 查看 Maven 引入的 jar 包是否有冲突
- Codota: 右键选中代码会提示很多相关 API 用法,节省不少查阅资料的时间
- IntelliJad:是一个 Java class 文件的反编译工具,可以对 Jar 选择 class 文件右键 Decompile,会出现反编译的结果
开发者工具
添加如下依赖到 pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope><!-- -->
<optional>true</optional>
</dependency>
修改源码后,使用快捷键 Ctrl + F9 手动构建项目后,Spring Boot 会自动重新加载
默认配置下,针对 /static、/public 和 /templates 目录中的文件修改,不会自动重启,因为禁用缓存后,这些文件的修改可以实时更新
如果不想手动构建,需要对 IDEA 做一些 配置更改
使用 springboot 的 maven 插件 spring-boot-maven-plugin,可以直接打出可运行的 jar:
mvn clean package
运行后在 target 文件夹下就可以看到 jar 了,直接用 Java 命令即可运行:
java -jar springboot-demo-jar-1.0-SNAPSHOT.jar
如果不喜欢默认的项目名+版本号作为运行 jar 文件名,可以加一个配置指定文件名:
<project ...>
...
<build>
<finalName>xxx-app</finalName>
...
</build>
</project>
测试
springboot2.x 的版本, 默认使用的是 junit5 版本, junit4 和 junit5 两个版本差别比较大,需要注意下用法
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MySpringTestBeanTest {
@Autowired
XXX xxx;
@Test
public void xxxTest() {
xxx.sayHello();
}
}
测试样例可以参考 官方教程
运行监控
Spring Boot 内置了一个监控功能 Actuator:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
运行项目后输入 http://localhost:8080/actuator,可以查看应用程序当前状态
默认只有 health 和 info 可使用 web 访问,要暴露更多的 访问点 给 Web,需要在 application.yml 中加上配置:
management:
endpoints:
web:
exposure:
include: info, health, beans, env, metrics
常用的如下:
Endpoint ID | Description |
---|---|
auditevents | 显示应用暴露的审计事件 (比如认证进入、订单失败) |
info | 显示应用的基本信息 |
health | 显示应用的健康状态 |
metrics | 显示应用多样的度量信息 |
loggers | 显示和修改配置的 loggers |
logfile | 返回 log file 中的内容(如果 logging.file 或者 logging.path 被设置) |
httptrace | 显示 HTTP 足迹,最近 100 个 HTTP request/repsponse |
env | 显示当前的环境特性 |
flyway | 显示数据库迁移路径的详细信息 |
liquidbase | 显示 Liquibase 数据库迁移的纤细信息 |
shutdown | 让你逐步关闭应用 |
mappings | 显示所有的 @RequestMapping 路径 |
scheduledtasks | 显示应用中的调度任务 |
threaddump | 执行一个线程 dump |
heapdump | 返回一个 GZip 压缩的 JVM 堆 dump |
在运行时改变日志等级
loggers endpoint 也允许你在运行时改变应用的日志等级。
举个例子,为了改变 root logger 的等级为 DEBUG ,发送一个 POST 请求到 http://localhost:8080/actuator/loggers/root,加入如下参数 :
{
"configuredLevel": "DEBUG"
}
这个功能对于线上问题的排查非常有用。
同时,你可以通过传递 null 值给 configuredLevel 来重置日志等级。
spring-boot-autoconfigure 包含了 Spring Boot 对于第三方库的自动配置,在编写自定义配置时可以参考使用
如果是 idea 使用 gradle 编译的话,如果出现中文乱码则打开 Help>Edit Custom VM Options,在最后一行加上:
-Dfile.encoding=UTF-8
最佳实践
关于 @Autowired 与 @Resource
如果在 idea 中使用类似:
class UserServiceImpl {
@Autowire
private UserDao userDao;
}
基于字段的依赖注入方式时会有黄色警告(不建议使用字段注入):
- 对于必需的依赖项,建议使用基于构造函数的注入,以使它们成为不可变的,并防止它们为 null。
- 对于可选的依赖项,建议使用基于 Setter 的注入
public class UserServiceImpl {
private UserDao userDao;
//基于构造函数的依赖注入
@Autowire
public UserServiceImpl(UserDao userDao){
this.userDao = userDao;
}
//setter 方式
@Autowire
public serUserDao(UserDao userDao){
this.userDao = userDao;
}
}
@Autowired 通过类型装配,若注入类型一样的对象就无法选择具体注入哪一个,则要配合 @Qualifiler 结合使用;@Resource 默认通过类型名注入
一般模块间的依赖推荐使用:
- 存在多态,推荐使用 @Resource
- 允许不存在,推荐 @Autowired 并设置 required 属性为 false
@Component
@Component 注解默认实例化的对象是单例,如果想声明成多例对象可以使用 @Scope(“prototype”), Scope 的全部可选项
- singleton 全局只有一个实例,即单例模式
- prototype 每次注入 Bean 都是一个新的实例
- request 每次 HTTP 请求都会产生新的 Bean
- session 每次 HTTP 请求都会产生新的 Bean,该 Bean 在仅在当前 session 内有效
- global session 每次 HTTP 请求都会产生新的 Bean,该 Bean 在 当前 global Session(基于 portlet 的 web 应用中)内有效
对于不常使⽤的 Bean 设置延迟加载,这样偶尔使⽤的时候再加载,不必要从⼀开始该 Bean 就占 ⽤资源
在 Bean 的初始化和清理方法上标记 @PostConstruct 和 @PreDestroy
先使用 @PropertySource 读取配置文件,然后通过 @Value 以${key:defaultValue}的形式注入,可以极大地简化读取配置的麻烦
- Profile: 创建某个 Bean 时,Spring 容器可以根据注解 @Profile 来决定是否创建
- Conditional: Spring 还可以根据 @Conditional 决定是否创建某个 Bean
- FactoryBean 可以⽣成某⼀个类型的 Bean 实例,也就是说我们可以借助于它⾃定义 Bean 的创建过程,实现 FactoryBean 接口即可(获取 FactoryBean,需要在 id 之前添加 &)。
如果你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加 @Component 注解的,因此就不能使用自动化装配的方案了,但是我们可以使用 @Bean。
pom 中使用阿里云镜像
<repositories>
<repository>
<id>nexus-aliyun</id>
<name>nexus-aliyun</name>
<url> http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
使用 gradle 的话:
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
第三方库想找到最新版本,除到各自官网查找外,可以到 Maven Central Repository Search 中搜索
中文乱码解决
spring boot 2.4.2 如果控制台存在中文乱码问题,需修改 application.yml:
logging:
charset:
console: gbk
- 使用 spring-boot:run 时控制台输出乱码
pom.xml 中修改
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!-- spring-boot:run 中文乱码解决 -->
<configuration>
<fork>true</fork>
<!--增加 jvm 参数-->
<jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
</configuration>
</plugin>
Aware
Spring 框架中提供了许多实现了 Aware 接口的类,这些类主要是为了辅助 Spring 访问容器中的数据:
- BeanNameAware:能够获取 bean 的名称
- BeanFactoryAware:获取当前 BeanFactory,这样可以调用容器的服务
- ApplicationContextAware:获取 ApplicationContext
- MessageSourceAware:获取 MessageSource 相关文本信息
- ApplicationEventPublisherAware: 获取 ApplicationEventPublisher,用于发布事件
- ResourceLoaderAware: 获取资源加载器,可以获取外部资源文件
- ……
使用时直接实现对应接口即可:
@Component
public class ApplicationContextAwareImpl implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//这里就可以获取到 ApplicationContext
}
}
Spring Retry
spring-retry 优雅引入重试机制:只需要在需要重试的方法上加上 @Retryable 注解并配置重试策略属性就好,不需要太多侵入代码:
- delay:默认 1 秒
- maxDelay:最大重试等待时间
- multiplier:用于计算下一个延迟时间的乘数(延迟大于 0 时生效)
- random:随机重试等待时间
<dependencys>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
</dependencys>
一定不要忘了在启动类上加上 @EnableRetry
使用
@Service
class TestService {
@Retryable(maxAttempts=5,backoff = @Backoff(delay = 100))
public void retrySomething() throws Exception{
logger.info("printSomething is called");
throw new SQLException();
}
}
不过需要注意的是如果被 @Retryable 注解的方法的调用方和被调用方处于同一个类中,那么重试将会失效
另外 Spring 的重试机制只支持对异常进行捕获,而无法对返回值进行校验判断重试。如果想要更灵活的重试策略可以使用Guava Retry
面试常问
谈谈你对 IOC 和 AOP 的理解?他们的实现原理是什么?
IOC 叫做控制反转,指的是通过 Spring 来管理对象的创建、配置和生命周期,这样相当于把控制权交给了
Spring,不需要人工来管理对象之间复杂的依赖关系,这样做的好处就是解耦。在 Spring 里面,主要提供
了 BeanFactory 和 ApplicationContext 两种 IOC 容器,通过他们来实现对 Bean 的管理。
AOP 叫做面向切面编程,他是一个编程范式,目的就是提高代码的模块性。Spring AOP 基于动态代理的
方式实现,如果是实现了接口的话就会使用 JDK 动态代理,反之则使用 CGLIB 代理,Spring 中 AOP 的应
用主要体现在 事务、日志、异常处理等方面,通过在代码的前后做一些增强处理,可以实现对业务逻辑的
隔离,提高代码的模块化能力,同时也是解耦。Spring 主要提供了 Aspect 切面、JoinPoint 连接点、
PointCut 切入点、Advice 增强等实现方式。
Spring Boot 启动流程
- 准备环境,根据不同的环境创建不同的 Environment
- 准备、加载上下文,为不同的环境选择不同的 Spring Context,然后加载资源,配置 Bean
- 初始化,这个阶段刷新 Spring Context,启动应用
网上搜到的流程图
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 域环境中的组策略安全测试
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论