1. 监控应用状态
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
查看全部指令:
localhost:8080/actuator
查看健康状态:
localhost:8080/actuator/health
查看容器beans信息:
localhost:8080/actuator/beans
2.lombok
字节码增强的方式简化代码编写
使用方式:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
- idea安装 lombok plugin
3. 使用事务的两种方式
- 编程式事务
- TransactionTemplate(TransactionCallback/TransactionCallbackWithoutResult)
- PlatformTransactionManager
- 声明式事务
配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
使用
@Transactional
4.CommandLineRunner
实现CommandLineRunner的run方法,可以在Configuration配置后执行,并且获得main方法的args。
public class DemoApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(DemoApplication, args);
}
@Override
public void run(String... args) throws Exception {
}
}
5.数据源自动装配
- 配置starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
- 配置数据源
h2
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Mysql
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
- 配置连接池
若不配置,Springboot默认使用HikariCP,当使用其他数据源时,需要先exinclude HikariCP,再配置其他连接池。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<artifactId>HikariCP</artifactId>
<groupId>com.zaxxer</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
- 配置数据库信息
application.properties
spring.datasource.url=jdbc:h2:mem:foo
spring.datasource.username=sa
spring.datasource.password=n/z7PyA5cvcXvs8px8FVmBVpaRyNsvJb3X7YfS38DJrIg25EbZaZGvH4aHcnc97Om0islpCAPc3MqsGvsrxVJw==
spring.datasource.druid.initial-size=5
spring.datasource.druid.max-active=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.filters=conn,config,stat,slf4j
spring.datasource.druid.connection-properties=config.decrypt=true;config.decrypt.key=${public-key}
spring.datasource.druid.filter.config.enabled=true
spring.datasource.druid.test-on-borrow=true
spring.datasource.druid.test-on-return=true
spring.datasource.druid.test-while-idle=true
6. H2 Database
内存数据库,可以使用SQL直接操作。
配置
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
application.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.hikari.maximumPoolSize=5
spring.datasource.hikari.minimumIdle=5
spring.datasource.hikari.idleTimeout=600000
spring.datasource.hikari.connectionTimeout=30000
spring.datasource.hikari.maxLifetime=1800000
在Resource中可以配置初始建表脚本(schema.sql)和数据脚本(data.sql)
7. Druid连接池
提供丰富的监控信息
慢sql监控
#spring.datasource.druid.filter.stat.enabled=true
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=100
8.在非事务注解方法调用内部事务注解方法,不会有事务
@Component
public class FooServiceImpl implements FooService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
@Transactional(rollbackFor = RollbackException.class)
public void insertThenRollback() throws RollbackException {
jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('BBB')");
throw new RollbackException();
}
//内部调用,不会回滚
public void insert() throws RollbackException {
this.insertThenRollback();
}
解决方法是通过代理对象调用,或获取代理对象
@Component
public class FooServiceImpl implements FooService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private FooService fooService;
@Override
@Transactional(rollbackFor = RollbackException.class)
public void insertThenRollback() throws RollbackException {
jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('BBB')");
throw new RollbackException();
}
// 通过代理对象调用
public void insert() throws RollbackException {
fooService.insertThenRollback();
}
// 通过代理对象调用
public void insert2() throws RollbackException {
((FooService) (AopContext.currentProxy())).insertThenRollback();
}
9、多数据源配置
application.properties
foo.datasource.url=jdbc:h2:mem:foo
foo.datasource.username=sa
foo.datasource.password=
bar.datasource.url=jdbc:h2:mem:bar
bar.datasource.username=sa
bar.datasource.password=
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
JdbcTemplateAutoConfiguration.class})
@Slf4j
public class MultiDataSourceDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MultiDataSourceDemoApplication.class, args);
}
@Bean
@ConfigurationProperties("foo.datasource")
public DataSourceProperties fooDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
public DataSource fooDataSource() {
DataSourceProperties dataSourceProperties = fooDataSourceProperties();
log.info("foo datasource: {}", dataSourceProperties.getUrl());
return dataSourceProperties.initializeDataSourceBuilder().build();
}
@Bean
@Resource
public PlatformTransactionManager fooTxManager(DataSource fooDataSource) {
return new DataSourceTransactionManager(fooDataSource);
}
@Bean
@ConfigurationProperties("bar.datasource")
public DataSourceProperties barDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
public DataSource barDataSource() {
DataSourceProperties dataSourceProperties = barDataSourceProperties();
log.info("bar datasource: {}", dataSourceProperties.getUrl());
return dataSourceProperties.initializeDataSourceBuilder().build();
}
@Bean
@Resource
public PlatformTransactionManager barTxManager(DataSource barDataSource) {
return new DataSourceTransactionManager(barDataSource);
}
}
10、自定义处理数据库异常
配置 resource/sql-error-codes.xml. 当出现指定异常码时,抛出自定义异常。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="H2" class="org.springframework.jdbc.support.SQLErrorCodes">
<property name="badSqlGrammarCodes">
<value>42000,42001,42101,42102,42111,42112,42121,42122,42132</value>
</property>
<property name="duplicateKeyCodes">
<value>23001,23505</value>
</property>
<property name="dataIntegrityViolationCodes">
<value>22001,22003,22012,22018,22025,23000,23002,23003,23502,23503,23506,23507,23513</value>
</property>
<property name="dataAccessResourceFailureCodes">
<value>90046,90100,90117,90121,90126</value>
</property>
<property name="cannotAcquireLockCodes">
<value>50200</value>
</property>
<property name="customTranslations">
<bean class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">
<property name="errorCodes" value="23001,23505" />
<property name="exceptionClass"
value="geektime.spring.data.errorcodedemo.CustomDuplicatedKeyException" />
</bean>
</property>
</bean>
</beans>
public class CustomDuplicatedKeyException extends DuplicateKeyException {
public CustomDuplicatedKeyException(String msg) {
super(msg);
}
public CustomDuplicatedKeyException(String msg, Throwable cause) {
super(msg, cause);
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class ErrorCodeDemoApplicationTests {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test(expected = CustomDuplicatedKeyException.class)
public void testThrowingCustomException() {
jdbcTemplate.execute("INSERT INTO FOO (ID, BAR) VALUES (1, 'a')");
jdbcTemplate.execute("INSERT INTO FOO (ID, BAR) VALUES (1, 'b')");
}
}
Spring默认是 PROGATION_REQUIRED.
PROGATION_REQUIRED_NEW和PROGATION_NESTED的区别?
PROGATION_REQUIRED_NEW:外部事务异常不会影响内部事务
PROGATION_NESTED: 外部事务异常会影响内部事务(回滚)
Spring默认是-1, 意味着隔离级别取决于数据库。