SpringBoot 集成使用

发布于 2024-11-05 00:35:45 字数 11207 浏览 2 评论 0

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 两个版本差别比较大,需要注意下用法

junit5 vs junit4

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 IDDescription
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

use 2.4.2 print log garbled

  • 使用 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 启动流程

  1. 准备环境,根据不同的环境创建不同的 Environment
  2. 准备、加载上下文,为不同的环境选择不同的 Spring Context,然后加载资源,配置 Bean
  3. 初始化,这个阶段刷新 Spring Context,启动应用

网上搜到的流程图

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

短暂陪伴

暂无简介

0 文章
0 评论
21 人气
更多

推荐作者

emdigitizer10

文章 0 评论 0

残龙傲雪

文章 0 评论 0

奢望

文章 0 评论 0

微信用户

文章 0 评论 0

又爬满兰若

文章 0 评论 0

独孤求败

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文