Spring Boot
- 内嵌式容器简化Web项目
- 没有冗余代码生成和XML配置的要求
与和SpringCloud
SpringCloud依赖于SpringBoot组件,使用SpringMVC编写HTTP接口,同时SpringCloud是一套完整的微服务解决框架
环境搭建
<parent> <!--继承父工程 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
</parent>
<dependencies>
<!--引入依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
@SpringBootApplication
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
热部署
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
IDEA需要开启自动编译
配置
YML语法
# 普通数据配置
name: hello
# 对象配置
person:
name: kb
age: 3
# 配置数组、集合(字符串)
city:
- beijing
- tianjing
- chongqing
# 配置数组、集合(对象)
student:
- name: tom
age: 3
- name: ll
age: 2
属性注入
- @Value
@Value("${name}")
private String name;
- @ConfigurationProperties
@RestController
@ConfigurationProperties(prefix = "person")
public class Controller {
private String name;
private Integer age;
@RequestMapping("/hi")
public String hello(){
return name+age;
}
// 省略setter
}
全局异常捕获
@ControllerAdvice
public class ErrorHandler {
@ResponseBody
@ExceptionHandler(Throwable.class)
public String error(Exception e){
return e.getMessage();
}
}
异步调用
- 添加
@EnableAsync
- 在需要异步调用的方法上面添加
@Async
多环境配置
spring.profiles.active=dev
添加开发环境配置文件application-dev.properties
事务管理
- 依赖
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>1.3</version>
</dependency>
- 添加
@Transactional
多数据源
配置多个DataSource,一个DataSource配置一个事务管理器,声明事务时指定事务管理器, 不同的ORM框架有不同的指定数据源的方式
jta-atomikos
通过把多个DataSource交给jta事务管理器管理,使用jta事务管理器来解决分布式事务问题
打包
jar
- 添加插件
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
- 执行
mvn package
war
添加打包插件
- 设置打包方式
<packaging>war</packaging>
- 执行打包命令
性能
组件自动扫描带来的问题
使用 @SpringBootApplication 注解后,会触发自动配置( auto-configuration )和 组件扫描 ( component scanning )
JVM参数调整
将tomcat改为undertow
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
监控中心
Actuator是spring boot的一个附加功能,可在应用程序生产环境时监视和管理应用程序
- 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 添加配置
# 暴露出所有监控接口
management:
endpoints:
web:
exposure:
include: "*"
路径 | 作用 |
---|---|
/actuator/beans | 显示应用程序中所有Spring bean的完整列表。 |
/actuator/configprops | 显示所有配置信息。 |
/actuator/env | 陈列所有的环境变量。 |
/actuator/mappings | 显示所有@RequestMapping的url整理列表。 |
/actuator/health | 显示应用程序运行状况信息 up表示成功 down失败 |
/actuator/info | 返回配置中前缀为info的配置项 |
集成其他框架
集成freemarker
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
- 配置
spring.freemarker.allow-request-override=false
spring.freemarker.cache=true
spring.freemarker.check-template-location=true
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=false
spring.freemarker.expose-session-attributes=false
spring.freemarker.expose-spring-macro-helpers=false
spring.freemarker.suffix=.ftl
spring.freemarker.template-loader-path=classpath:/templates/
- 创建Controller
@Controller
public class HelloController {
@RequestMapping("hello")
public String index(ModelMap map){
map.put("hello","java");
return "index";
}
}
- 在template目录下创建index.ftl
<body>
${hello}
</body>
集成Mybatis
- 引入依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
- 配置数据库信息和mybatis配置
# 数据库连接信息
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///ssm
# mybatis相关配置
mybatis.mapper-locations=mappers/*.xml
mybatis.configuration.map-underscore-to-camel-case=true
- 配置mybatis包扫描路径
@MapperScan(basePackages = "wang.ismy.springmybatis.mapper")
public class SpringMybatisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringMybatisApplication.class, args);
}
}
整合PageHelper
- 引入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.13</version>
</dependency>
- 配置
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql
pagehelper.page-size-zero=true
集成Junit
- 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- 建立测试
@SpringBootTest
@RunWith(SpringRunner.class)
public class ControllerTest{
@Autowired
UserMapper mapper;
@Test
public void test(){
assertNotNull(mapper);
}
}
集成Spring data jpa
- 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
- 配置
# 数据库连接信息
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///ssm
# spring data jpa相关配置
spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
使用通用Mapper
- 依赖
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
- 继承
public interface UserMapper extends BaseMapper<User> { }
- @MapperScan注解需要使用tk.mybatis包
集成Redis
- 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置
# redis相关配置
spring.redis.host=127.0.0.1
spring.redis.port=6379
- 使用
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
@Autowired
RedisTemplate<String,String> redisTemplate;
@Test
public void test(){
String name = redisTemplate.boundValueOps("name").get();
Assert.assertEquals("my",name);
}
}
集成swagger
- 依赖
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.9.1.RELEASE</version>
</dependency>
- 配置
swagger.base-package=wang.ismy.consume
@EnableSwagger2Doc
zuul整合各个微服务文档
- 依赖
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.9.1.RELEASE</version>
</dependency>
- 配置
@Component
@Primary
@EnableSwagger2Doc
class DocumentationConfig implements SwaggerResourcesProvider {
@Override
public List<SwaggerResource> get() {
List resources = new ArrayList<>();
resources.add(swaggerResource("consumer", "/api-consumer/v2/api-docs", "2.0"));
return resources;
}
private SwaggerResource swaggerResource(String name, String location, String version) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion(version);
return swaggerResource;
}
}
高级
@ConditionOnXX
条件化注入bean
切换内置服务器
- 排除tomcat依赖
- 引入其他内置服务器依赖
@EnableXX原理
此类注解使用了@Import修饰,通过@Import注解来导入一些配置类
@Import使用:
- 导入Bean
- 导入配置类
- ImportSelector的实现类
- 自定义需要导入的类逻辑(返回全限定类名)
- ImportBeanDefinitionRegistrar 实现类
- 自定义(编程式向IOC容器注册)
@EnableAutoConfiguration原理
- @Import AutoConfigurationImportSelector 加载配置类
- AutoConfigurationImportSelector读取META-INF/spring.factories 加载配置类
自定义starter
- 定义autoconfigure模块
- 定义starter模块依赖autoconfigure模块
- 在autoconfigure模块定义META-INF/spring.factories
事件监听
- SpringApplicationRunListener
- CommandLineRunner 项目启动后执行(放入ioc容器即可被识别)
- ApplicationRunner 项目启动后执行(放入ioc容器即可被识别)
为了在应用启动成功之后执行某些操作,某些情况下使用InitializingBean接口并不能满足请求,其回调方法afterPropertiesSet在Bean属性被设置后被调用,此时系统的部分组件可能仍处于未初始化状态。
为解决这个问题,可使用Spring的事件监听机制,监听SpringBoot的AvailabilityChangeEvent<ReadinessState>
当状态为ReadinessState.ACCEPTING_TRAFFIC,表示应用可以开始准备接收请求了,此时再启动所需要的操作
@EventListener
public void onSystemReady(AvailabilityChangeEvent<ReadinessState> event) {
if (event.getState().equals(ReadinessState.ACCEPTING_TRAFFIC)) {
// do something
}
}