style(all): 使用IDEA默认的格式化方案

This commit is contained in:
小锅盖 2020-05-20 17:56:16 +08:00
parent 07a5419a5c
commit 89a4ffae18
117 changed files with 3588 additions and 3556 deletions

View File

@ -6,8 +6,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LoadApplication {
public static void main(String[] args) {
SpringApplication.run(LoadApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(LoadApplication.class, args);
}
}

View File

@ -13,13 +13,13 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
@EnableSwagger2
public class SwaggerAutoConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(ApiInfo.DEFAULT)
.select()
.apis(RequestHandlerSelectors.basePackage("com.baomidou.samples.dynamicload.controller"))
.paths(PathSelectors.any())
.build();
}
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(ApiInfo.DEFAULT)
.select()
.apis(RequestHandlerSelectors.basePackage("com.baomidou.samples.dynamicload.controller"))
.paths(PathSelectors.any())
.build();
}
}

View File

@ -1,26 +1,18 @@
package com.baomidou.samples.dynamicload.controller;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.BasicDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.creator.DruidDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.HikariDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.JndiDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.*;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.samples.dynamicload.dto.DataSourceDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.util.Set;
import javax.sql.DataSource;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.sql.DataSource;
import java.util.Set;
@RestController
@AllArgsConstructor
@ -28,78 +20,78 @@ import org.springframework.web.bind.annotation.RestController;
@Api(tags = "添加删除数据源")
public class LoadController {
private final DataSource dataSource;
private final DataSourceCreator dataSourceCreator;
private final BasicDataSourceCreator basicDataSourceCreator;
private final JndiDataSourceCreator jndiDataSourceCreator;
private final DruidDataSourceCreator druidDataSourceCreator;
private final HikariDataSourceCreator hikariDataSourceCreator;
private final DataSource dataSource;
private final DataSourceCreator dataSourceCreator;
private final BasicDataSourceCreator basicDataSourceCreator;
private final JndiDataSourceCreator jndiDataSourceCreator;
private final DruidDataSourceCreator druidDataSourceCreator;
private final HikariDataSourceCreator hikariDataSourceCreator;
@GetMapping
@ApiOperation("获取当前所有数据源")
public Set<String> now() {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
return ds.getCurrentDataSources().keySet();
}
@GetMapping
@ApiOperation("获取当前所有数据源")
public Set<String> now() {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
return ds.getCurrentDataSources().keySet();
}
@PostMapping("/add")
@ApiOperation("通用添加数据源(推荐)")
public Set<String> add(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPollName(), dataSource);
return ds.getCurrentDataSources().keySet();
}
@PostMapping("/add")
@ApiOperation("通用添加数据源(推荐)")
public Set<String> add(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPollName(), dataSource);
return ds.getCurrentDataSources().keySet();
}
@PostMapping("/addBasic")
@ApiOperation(value = "添加基础数据源", notes = "调用Springboot内置方法创建数据源兼容1,2")
public Set<String> addBasic(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = basicDataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPollName(), dataSource);
return ds.getCurrentDataSources().keySet();
}
@PostMapping("/addBasic")
@ApiOperation(value = "添加基础数据源", notes = "调用Springboot内置方法创建数据源兼容1,2")
public Set<String> addBasic(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = basicDataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPollName(), dataSource);
return ds.getCurrentDataSources().keySet();
}
@PostMapping("/addJndi")
@ApiOperation("添加JNDI数据源")
public Set<String> addJndi(String pollName, String jndiName) {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = jndiDataSourceCreator.createDataSource(jndiName);
ds.addDataSource(pollName, dataSource);
return ds.getCurrentDataSources().keySet();
}
@PostMapping("/addJndi")
@ApiOperation("添加JNDI数据源")
public Set<String> addJndi(String pollName, String jndiName) {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = jndiDataSourceCreator.createDataSource(jndiName);
ds.addDataSource(pollName, dataSource);
return ds.getCurrentDataSources().keySet();
}
@PostMapping("/addDruid")
@ApiOperation("基础Druid数据源")
public Set<String> addDruid(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = druidDataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPollName(), dataSource);
return ds.getCurrentDataSources().keySet();
}
@PostMapping("/addDruid")
@ApiOperation("基础Druid数据源")
public Set<String> addDruid(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = druidDataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPollName(), dataSource);
return ds.getCurrentDataSources().keySet();
}
@PostMapping("/addHikariCP")
@ApiOperation("基础HikariCP数据源")
public Set<String> addHikariCP(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPollName(), dataSource);
return ds.getCurrentDataSources().keySet();
}
@PostMapping("/addHikariCP")
@ApiOperation("基础HikariCP数据源")
public Set<String> addHikariCP(@Validated @RequestBody DataSourceDTO dto) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
BeanUtils.copyProperties(dto, dataSourceProperty);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource dataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(dto.getPollName(), dataSource);
return ds.getCurrentDataSources().keySet();
}
@DeleteMapping
@ApiOperation("删除数据源")
public String remove(String name) {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
ds.removeDataSource(name);
return "删除成功";
}
@DeleteMapping
@ApiOperation("删除数据源")
public String remove(String name) {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
ds.removeDataSource(name);
return "删除成功";
}
}

View File

@ -1,9 +1,10 @@
package com.baomidou.samples.dynamicload.dto;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotBlank;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @author TaoYu
* @date 2020/1/27
@ -11,23 +12,23 @@ import lombok.Data;
@Data
public class DataSourceDTO {
@NotBlank
@ApiModelProperty(value = "连接池名称", example = "test")
private String pollName;
@NotBlank
@ApiModelProperty(value = "连接池名称", example = "test")
private String pollName;
@NotBlank
@ApiModelProperty(value = "JDBC driver", example = "org.h2.Driver")
private String driverClassName;
@NotBlank
@ApiModelProperty(value = "JDBC driver", example = "org.h2.Driver")
private String driverClassName;
@NotBlank
@ApiModelProperty(value = "JDBC url 地址", example = "jdbc:h2:mem:test10")
private String url;
@NotBlank
@ApiModelProperty(value = "JDBC url 地址", example = "jdbc:h2:mem:test10")
private String url;
@NotBlank
@ApiModelProperty(value = "JDBC 用户名", example = "sa")
private String username;
@NotBlank
@ApiModelProperty(value = "JDBC 用户名", example = "sa")
private String username;
@ApiModelProperty(value = "JDBC 密码")
private String password;
@ApiModelProperty(value = "JDBC 密码")
private String password;
}

View File

@ -9,8 +9,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.baomidou.samples.druid.mybatis.mapper")
public class DruidMybatisApplication {
public static void main(String[] args) {
SpringApplication.run(DruidMybatisApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(DruidMybatisApplication.class, args);
}
}

View File

@ -2,33 +2,33 @@ package com.baomidou.samples.druid.mybatis.entity;
public class User {
private Integer id;
private Integer id;
private String name;
private String name;
private Integer age;
private Integer age;
public Integer getId() {
return id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void setAge(Integer age) {
this.age = age;
}
}

View File

@ -1,16 +1,17 @@
package com.baomidou.samples.druid.mybatis.mapper;
import com.baomidou.samples.druid.mybatis.entity.User;
import java.util.List;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface UserMapper {
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
boolean addUser(@Param("name") String name, @Param("age") Integer age);
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
boolean addUser(@Param("name") String name, @Param("age") Integer age);
@Select("SELECT * FROM user where age > #{age}")
List<User> selectUsers(@Param("age") Integer age);
@Select("SELECT * FROM user where age > #{age}")
List<User> selectUsers(@Param("age") Integer age);
}

View File

@ -2,13 +2,14 @@ package com.baomidou.samples.druid.mybatis.service;
import com.baomidou.samples.druid.mybatis.entity.User;
import java.util.List;
public interface UserService {
void addUser(User user);
void addUser(User user);
List selectUsersFromDs();
List selectUsersFromDs();
List selectUserFromDsGroup();
List selectUserFromDsGroup();
}

View File

@ -5,30 +5,31 @@ import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.samples.druid.mybatis.entity.User;
import com.baomidou.samples.druid.mybatis.mapper.UserMapper;
import com.baomidou.samples.druid.mybatis.service.UserService;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private UserMapper userMapper;
@Override
public void addUser(User user) {
userMapper.addUser(user.getName(), user.getAge());
}
@Override
public void addUser(User user) {
userMapper.addUser(user.getName(), user.getAge());
}
@DS("slave_1")
@Override
public List selectUsersFromDs() {
return userMapper.selectUsers(1);
}
@DS("slave_1")
@Override
public List selectUsersFromDs() {
return userMapper.selectUsers(1);
}
@DS("slave")
@Override
public List selectUserFromDsGroup() {
return userMapper.selectUsers(1);
}
@DS("slave")
@Override
public List selectUserFromDsGroup() {
return userMapper.selectUsers(1);
}
}

View File

@ -3,38 +3,39 @@ package com.baomidou.samples.druid.mybatis.test;
import com.baomidou.samples.druid.mybatis.DruidMybatisApplication;
import com.baomidou.samples.druid.mybatis.entity.User;
import com.baomidou.samples.druid.mybatis.service.UserService;
import java.util.Random;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Random;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DruidMybatisApplication.class)
public class DruidMybatisApplicationTest {
private Random random = new Random();
private Random random = new Random();
@Autowired
private UserService userService;
@Autowired
private UserService userService;
@Test
public void addUser() {
User user = new User();
user.setName("测试用户" + random.nextInt());
user.setAge(random.nextInt(100));
userService.addUser(user);
}
@Test
public void addUser() {
User user = new User();
user.setName("测试用户" + random.nextInt());
user.setAge(random.nextInt(100));
userService.addUser(user);
}
@Test
public void selectUsersFromDs() {
userService.selectUsersFromDs();
}
@Test
public void selectUsersFromDs() {
userService.selectUsersFromDs();
}
@Test
public void selectUserFromDsGroup() {
userService.selectUserFromDsGroup();
}
@Test
public void selectUserFromDsGroup() {
userService.selectUserFromDsGroup();
}
}

View File

@ -1,21 +1,22 @@
package com.baomidou.samples.jdbc;
import javax.sql.DataSource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}

View File

@ -2,33 +2,33 @@ package com.baomidou.samples.jdbc.entity;
public class User {
private Integer id;
private Integer id;
private String name;
private String name;
private Integer age;
private Integer age;
public Integer getId() {
return id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void setAge(Integer age) {
this.age = age;
}
}

View File

@ -1,13 +1,14 @@
package com.baomidou.samples.jdbc.service;
import com.baomidou.samples.jdbc.entity.User;
import java.util.List;
public interface UserService {
void addUser(User user);
void addUser(User user);
List selectUsersFromDs();
List selectUsersFromDs();
List selectUserFromDsGroup();
List selectUserFromDsGroup();
}

View File

@ -4,32 +4,33 @@ package com.baomidou.samples.jdbc.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.samples.jdbc.entity.User;
import com.baomidou.samples.jdbc.service.UserService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void addUser(User user) {
jdbcTemplate.update("INSERT INTO user (name,age) VALUES(?, ?)",
new Object[]{user.getName(), user.getAge()});
}
@Override
public void addUser(User user) {
jdbcTemplate.update("INSERT INTO user (name,age) VALUES(?, ?)",
new Object[]{user.getName(), user.getAge()});
}
@DS("slave_1")
@Override
public List selectUsersFromDs() {
return jdbcTemplate.queryForList("SELECT * FROM user");
}
@DS("slave_1")
@Override
public List selectUsersFromDs() {
return jdbcTemplate.queryForList("SELECT * FROM user");
}
@DS("slave")
@Override
public List selectUserFromDsGroup() {
return jdbcTemplate.queryForList("SELECT * FROM user");
}
@DS("slave")
@Override
public List selectUserFromDsGroup() {
return jdbcTemplate.queryForList("SELECT * FROM user");
}
}

View File

@ -3,37 +3,38 @@ package com.baomidou.samples.jdbc.test;
import com.baomidou.samples.jdbc.Application;
import com.baomidou.samples.jdbc.entity.User;
import com.baomidou.samples.jdbc.service.UserService;
import java.util.Random;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Random;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {
private Random random = new Random();
private Random random = new Random();
@Autowired
private UserService userService;
@Autowired
private UserService userService;
@Test
public void addUser() {
User user = new User();
user.setName("测试用户" + random.nextInt());
user.setAge(random.nextInt(100));
userService.addUser(user);
}
@Test
public void addUser() {
User user = new User();
user.setName("测试用户" + random.nextInt());
user.setAge(random.nextInt(100));
userService.addUser(user);
}
@Test
public void selectUsersFromDs() {
userService.selectUsersFromDs();
}
@Test
public void selectUsersFromDs() {
userService.selectUsersFromDs();
}
@Test
public void selectUserFromDsGroup() {
userService.selectUserFromDsGroup();
}
@Test
public void selectUserFromDsGroup() {
userService.selectUserFromDsGroup();
}
}

View File

@ -8,8 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.baomidou.samples.mybatis.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -2,33 +2,33 @@ package com.baomidou.samples.mybatis.entity;
public class User {
private Integer id;
private Integer id;
private String name;
private String name;
private Integer age;
private Integer age;
public Integer getId() {
return id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void setAge(Integer age) {
this.age = age;
}
}

View File

@ -1,17 +1,18 @@
package com.baomidou.samples.mybatis.mapper;
import com.baomidou.samples.mybatis.entity.User;
import java.util.List;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
//@DS("slave")这里可以使用但不建议不要和service同时使用
public interface UserMapper {
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
boolean addUser(@Param("name") String name, @Param("age") Integer age);
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
boolean addUser(@Param("name") String name, @Param("age") Integer age);
@Select("SELECT * FROM user")
List<User> selectUsers();
@Select("SELECT * FROM user")
List<User> selectUsers();
}

View File

@ -2,13 +2,14 @@ package com.baomidou.samples.mybatis.service;
import com.baomidou.samples.mybatis.entity.User;
import java.util.List;
public interface UserService {
void addUser(User user);
void addUser(User user);
List selectUsersFromDs();
List selectUsersFromDs();
List selectUserFromDsGroup();
List selectUserFromDsGroup();
}

View File

@ -5,30 +5,31 @@ import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.samples.mybatis.entity.User;
import com.baomidou.samples.mybatis.mapper.UserMapper;
import com.baomidou.samples.mybatis.service.UserService;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private UserMapper userMapper;
@Override
public void addUser(User user) {
userMapper.addUser(user.getName(), user.getAge());
}
@Override
public void addUser(User user) {
userMapper.addUser(user.getName(), user.getAge());
}
@DS("slave_1")
@Override
public List selectUsersFromDs() {
return userMapper.selectUsers();
}
@DS("slave_1")
@Override
public List selectUsersFromDs() {
return userMapper.selectUsers();
}
@DS("slave")
@Override
public List selectUserFromDsGroup() {
return userMapper.selectUsers();
}
@DS("slave")
@Override
public List selectUserFromDsGroup() {
return userMapper.selectUsers();
}
}

View File

@ -4,37 +4,38 @@ package com.baomidou.samples.mybatis.test;
import com.baomidou.samples.mybatis.Application;
import com.baomidou.samples.mybatis.entity.User;
import com.baomidou.samples.mybatis.service.UserService;
import java.util.Random;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Random;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {
private Random random = new Random();
private Random random = new Random();
@Autowired
private UserService userService;
@Autowired
private UserService userService;
@Test
public void addUser() {
User user = new User();
user.setName("测试用户" + random.nextInt());
user.setAge(random.nextInt(100));
userService.addUser(user);
}
@Test
public void addUser() {
User user = new User();
user.setName("测试用户" + random.nextInt());
user.setAge(random.nextInt(100));
userService.addUser(user);
}
@Test
public void selectUsersFromDs() {
userService.selectUsersFromDs();
}
@Test
public void selectUsersFromDs() {
userService.selectUsersFromDs();
}
@Test
public void selectUserFromDsGroup() {
userService.selectUserFromDsGroup();
}
@Test
public void selectUserFromDsGroup() {
userService.selectUserFromDsGroup();
}
}

View File

@ -8,8 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.baomidou.samples.mybatisplus2.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -5,34 +5,34 @@ import com.baomidou.mybatisplus.enums.IdType;
public class User {
@TableId(type = IdType.AUTO)
private Integer id;
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private String name;
private Integer age;
private Integer age;
public Integer getId() {
return id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void setAge(Integer age) {
this.age = age;
}
}

View File

@ -6,6 +6,6 @@ import com.baomidou.samples.mybatisplus2.entity.User;
public interface UserService extends IService<User> {
void addUser(User user);
void addUser(User user);
}

View File

@ -12,9 +12,9 @@ import org.springframework.stereotype.Service;
@DS("slave")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Override
@Override
// @DS("master")//这里必须包一层不能调用mp默认的插入因为会走到从库去
public void addUser(User user) {
baseMapper.insert(user);
}
public void addUser(User user) {
baseMapper.insert(user);
}
}

View File

@ -3,33 +3,34 @@ package com.baomidou.samples.mybatisplus2.test;
import com.baomidou.samples.mybatisplus2.Application;
import com.baomidou.samples.mybatisplus2.entity.User;
import com.baomidou.samples.mybatisplus2.service.UserService;
import java.util.Random;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Random;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {
private Random random = new Random();
private Random random = new Random();
@Autowired
private UserService userService;
@Autowired
private UserService userService;
@Test
public void testAddUser() {
User user = new User();
user.setName("测试用户" + random.nextInt());
user.setAge(random.nextInt(100));
userService.addUser(user);
}
@Test
public void testAddUser() {
User user = new User();
user.setName("测试用户" + random.nextInt());
user.setAge(random.nextInt(100));
userService.addUser(user);
}
@Test
public void testSelectUser() {
userService.selectList(null);
}
@Test
public void testSelectUser() {
userService.selectList(null);
}
}

View File

@ -8,8 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.baomidou.samples.mybatisplus.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -5,34 +5,34 @@ import com.baomidou.mybatisplus.annotation.TableId;
public class User {
@TableId(type = IdType.AUTO)
private Integer id;
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private String name;
private Integer age;
private Integer age;
public Integer getId() {
return id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void setAge(Integer age) {
this.age = age;
}
}

View File

@ -6,6 +6,6 @@ import com.baomidou.samples.mybatisplus.entity.User;
public interface UserService extends IService<User> {
void addUser(User user);
void addUser(User user);
}

View File

@ -12,9 +12,9 @@ import org.springframework.stereotype.Service;
@DS("slave")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Override
@DS("master")//这里必须包一层不能调用mp默认的插入因为会走到从库去
public void addUser(User user) {
baseMapper.insert(user);
}
@Override
@DS("master")//这里必须包一层不能调用mp默认的插入因为会走到从库去
public void addUser(User user) {
baseMapper.insert(user);
}
}

View File

@ -3,32 +3,33 @@ package com.baomidou.samples.mybatisplus3.test;
import com.baomidou.samples.mybatisplus.Application;
import com.baomidou.samples.mybatisplus.entity.User;
import com.baomidou.samples.mybatisplus.service.UserService;
import java.util.Random;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Random;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {
private Random random = new Random();
private Random random = new Random();
@Autowired
private UserService userService;
@Autowired
private UserService userService;
@Test
public void testAddUser() {
User user = new User();
user.setName("测试用户" + random.nextInt());
user.setAge(random.nextInt(100));
userService.addUser(user);
}
@Test
public void testAddUser() {
User user = new User();
user.setName("测试用户" + random.nextInt());
user.setAge(random.nextInt(100));
userService.addUser(user);
}
@Test
public void testSelectUser() {
userService.list(null);
}
@Test
public void testSelectUser() {
userService.list(null);
}
}

View File

@ -8,8 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.baomidou.samples.nest.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -1,38 +1,39 @@
package com.baomidou.samples.nest;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@Component
public class CreateDatabaseOnStarted implements ApplicationListener<ApplicationStartedEvent> {
@Autowired
private DataSource dataSource;
@Autowired
private DataSource dataSource;
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
try {
Connection connection = dataSource.getConnection();
connection.createStatement().execute("CREATE TABLE IF NOT EXISTS teacher (\n" +
" id BIGINT(20) NOT NULL AUTO_INCREMENT,\n" +
" name VARCHAR(30) NULL DEFAULT NULL ,\n" +
" age INT(11) NULL DEFAULT NULL ,\n" +
" PRIMARY KEY (id)\n" +
");");
connection.createStatement().execute("CREATE TABLE IF NOT EXISTS student (\n" +
" id BIGINT(20) NOT NULL AUTO_INCREMENT,\n" +
" name VARCHAR(30) NULL DEFAULT NULL ,\n" +
" age INT(11) NULL DEFAULT NULL ,\n" +
" PRIMARY KEY (id)\n" +
");");
connection.close();
} catch (SQLException e) {
e.printStackTrace();
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
try {
Connection connection = dataSource.getConnection();
connection.createStatement().execute("CREATE TABLE IF NOT EXISTS teacher (\n" +
" id BIGINT(20) NOT NULL AUTO_INCREMENT,\n" +
" name VARCHAR(30) NULL DEFAULT NULL ,\n" +
" age INT(11) NULL DEFAULT NULL ,\n" +
" PRIMARY KEY (id)\n" +
");");
connection.createStatement().execute("CREATE TABLE IF NOT EXISTS student (\n" +
" id BIGINT(20) NOT NULL AUTO_INCREMENT,\n" +
" name VARCHAR(30) NULL DEFAULT NULL ,\n" +
" age INT(11) NULL DEFAULT NULL ,\n" +
" PRIMARY KEY (id)\n" +
");");
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

View File

@ -9,27 +9,27 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Autowired
private TeacherService teacherService;
@Autowired
private TeacherService teacherService;
@Autowired
private SchoolService schoolService;
@Autowired
private SchoolService schoolService;
@GetMapping("/tx1")
public void tx1() {
//外层不加事物里面每个单独加事物支持不过感觉没毛用
schoolService.addTeacherAndStudent();
}
@GetMapping("/tx1")
public void tx1() {
//外层不加事物里面每个单独加事物支持不过感觉没毛用
schoolService.addTeacherAndStudent();
}
@GetMapping("/tx2")
public void tx2() {
//外层加事物里面每个也加事物不支持!!其实只要加了事物就不支持多库
schoolService.addTeacherAndStudentWithTx();
}
@GetMapping("/tx2")
public void tx2() {
//外层加事物里面每个也加事物不支持!!其实只要加了事物就不支持多库
schoolService.addTeacherAndStudentWithTx();
}
@GetMapping("/tx3")
public void tx3() {
//单独调用加事物单库支持
teacherService.addTeacherWithTx("tt", 12);
}
@GetMapping("/tx3")
public void tx3() {
//单独调用加事物单库支持
teacherService.addTeacherWithTx("tt", 12);
}
}

View File

@ -2,33 +2,33 @@ package com.baomidou.samples.nest.entiry;
public class Student {
private Integer id;
private Integer id;
private String name;
private String name;
private Integer age;
private Integer age;
public Integer getId() {
return id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void setAge(Integer age) {
this.age = age;
}
}

View File

@ -2,33 +2,33 @@ package com.baomidou.samples.nest.entiry;
public class Teacher {
private Integer id;
private Integer id;
private String name;
private String name;
private Integer age;
private Integer age;
public Integer getId() {
return id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void setAge(Integer age) {
this.age = age;
}
}

View File

@ -1,16 +1,17 @@
package com.baomidou.samples.nest.mapper;
import com.baomidou.samples.nest.entiry.Student;
import java.util.List;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface StudentMapper {
@Insert("INSERT INTO student (name,age) values (#{name},#{age})")
boolean addStudent(@Param("name") String name, @Param("age") Integer age);
@Insert("INSERT INTO student (name,age) values (#{name},#{age})")
boolean addStudent(@Param("name") String name, @Param("age") Integer age);
@Select("SELECT * FROM student")
List<Student> selectStudents();
@Select("SELECT * FROM student")
List<Student> selectStudents();
}

View File

@ -1,16 +1,17 @@
package com.baomidou.samples.nest.mapper;
import com.baomidou.samples.nest.entiry.Teacher;
import java.util.List;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface TeacherMapper {
@Insert("INSERT INTO teacher (name,age) values (#{name},#{age})")
boolean addTeacher(@Param("name") String name, @Param("age") Integer age);
@Insert("INSERT INTO teacher (name,age) values (#{name},#{age})")
boolean addTeacher(@Param("name") String name, @Param("age") Integer age);
@Select("SELECT * FROM teacher")
List<Teacher> selectTeachers();
@Select("SELECT * FROM teacher")
List<Teacher> selectTeachers();
}

View File

@ -2,11 +2,11 @@ package com.baomidou.samples.nest.service;
public interface SchoolService {
void selectTeachersAndStudents();
void selectTeachersAndStudents();
void selectTeachersInnerStudents();
void selectTeachersInnerStudents();
void addTeacherAndStudent();
void addTeacherAndStudent();
void addTeacherAndStudentWithTx();
void addTeacherAndStudentWithTx();
}

View File

@ -1,14 +1,15 @@
package com.baomidou.samples.nest.service;
import com.baomidou.samples.nest.entiry.Student;
import java.util.List;
public interface StudentService {
boolean addStudentWithTx(String name, Integer age);
boolean addStudentWithTx(String name, Integer age);
boolean addStudentNoTx(String name, Integer age);
boolean addStudentNoTx(String name, Integer age);
List<Student> selectStudents();
List<Student> selectStudents();
}

View File

@ -1,17 +1,18 @@
package com.baomidou.samples.nest.service;
import com.baomidou.samples.nest.entiry.Teacher;
import java.util.List;
public interface TeacherService {
boolean addTeacherWithTx(String name, Integer age);
boolean addTeacherWithTx(String name, Integer age);
boolean addTeacherNoTx(String name, Integer age);
boolean addTeacherNoTx(String name, Integer age);
List<Teacher> selectTeachers();
List<Teacher> selectTeachers();
void selectTeachersInnerStudents();
void selectTeachersInnerStudents();
}

View File

@ -10,33 +10,33 @@ import org.springframework.transaction.annotation.Transactional;
@Service
public class SchoolServiceImpl implements SchoolService {
@Autowired
private TeacherService teacherService;
@Autowired
private TeacherService teacherService;
@Autowired
private StudentService studentService;
@Autowired
private StudentService studentService;
@Override
public void selectTeachersAndStudents() {
teacherService.selectTeachers();
studentService.selectStudents();
}
@Override
public void selectTeachersAndStudents() {
teacherService.selectTeachers();
studentService.selectStudents();
}
@Override
public void selectTeachersInnerStudents() {
teacherService.selectTeachersInnerStudents();
}
@Override
public void selectTeachersInnerStudents() {
teacherService.selectTeachersInnerStudents();
}
@Override
public void addTeacherAndStudent() {
teacherService.addTeacherWithTx("ss", 1);
studentService.addStudentWithTx("tt", 2);
}
@Override
public void addTeacherAndStudent() {
teacherService.addTeacherWithTx("ss", 1);
studentService.addStudentWithTx("tt", 2);
}
@Override
@Transactional
public void addTeacherAndStudentWithTx() {
teacherService.addTeacherWithTx("ss", 1);
studentService.addStudentWithTx("tt", 2);
}
@Override
@Transactional
public void addTeacherAndStudentWithTx() {
teacherService.addTeacherWithTx("ss", 1);
studentService.addStudentWithTx("tt", 2);
}
}

View File

@ -4,31 +4,32 @@ import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.samples.nest.entiry.Student;
import com.baomidou.samples.nest.mapper.StudentMapper;
import com.baomidou.samples.nest.service.StudentService;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@Service
@DS("student")
public class StudentServiceImpl implements StudentService {
@Resource
private StudentMapper studentMapper;
@Resource
private StudentMapper studentMapper;
@Override
@Transactional
public boolean addStudentWithTx(String name, Integer age) {
return studentMapper.addStudent(name, age);
}
@Override
@Transactional
public boolean addStudentWithTx(String name, Integer age) {
return studentMapper.addStudent(name, age);
}
@Override
public boolean addStudentNoTx(String name, Integer age) {
return studentMapper.addStudent(name, age);
}
@Override
public boolean addStudentNoTx(String name, Integer age) {
return studentMapper.addStudent(name, age);
}
@Override
public List<Student> selectStudents() {
return studentMapper.selectStudents();
}
@Override
public List<Student> selectStudents() {
return studentMapper.selectStudents();
}
}

View File

@ -5,40 +5,41 @@ import com.baomidou.samples.nest.entiry.Teacher;
import com.baomidou.samples.nest.mapper.TeacherMapper;
import com.baomidou.samples.nest.service.StudentService;
import com.baomidou.samples.nest.service.TeacherService;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@Service
@DS("teacher")
public class TeacherServiceImpl implements TeacherService {
@Resource
private TeacherMapper teacherMapper;
@Autowired
private StudentService studentService;
@Resource
private TeacherMapper teacherMapper;
@Autowired
private StudentService studentService;
@Override
@Transactional
public boolean addTeacherWithTx(String name, Integer age) {
return teacherMapper.addTeacher(name, age);
}
@Override
@Transactional
public boolean addTeacherWithTx(String name, Integer age) {
return teacherMapper.addTeacher(name, age);
}
@Override
public boolean addTeacherNoTx(String name, Integer age) {
return teacherMapper.addTeacher(name, age);
}
@Override
public boolean addTeacherNoTx(String name, Integer age) {
return teacherMapper.addTeacher(name, age);
}
@Override
public List<Teacher> selectTeachers() {
return teacherMapper.selectTeachers();
}
@Override
public List<Teacher> selectTeachers() {
return teacherMapper.selectTeachers();
}
@Override
public void selectTeachersInnerStudents() {
teacherMapper.selectTeachers();
studentService.selectStudents();
}
@Override
public void selectTeachersInnerStudents() {
teacherMapper.selectTeachers();
studentService.selectStudents();
}
}

View File

@ -5,46 +5,47 @@ import com.baomidou.samples.nest.Application;
import com.baomidou.samples.nest.service.SchoolService;
import com.baomidou.samples.nest.service.StudentService;
import com.baomidou.samples.nest.service.TeacherService;
import java.util.Random;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Random;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {
private Random random = new Random();
private Random random = new Random();
@Autowired
private TeacherService teacherService;
@Autowired
private StudentService studentService;
@Autowired
private SchoolService schoolService;
@Autowired
private TeacherService teacherService;
@Autowired
private StudentService studentService;
@Autowired
private SchoolService schoolService;
@Test
public void nest1() {
//直接在controller
teacherService.selectTeachers();
studentService.selectStudents();
}
@Test
public void nest1() {
//直接在controller
teacherService.selectTeachers();
studentService.selectStudents();
}
@Test
public void nest2() {
schoolService.selectTeachersAndStudents();
}
@Test
public void nest2() {
schoolService.selectTeachersAndStudents();
}
@Test
public void nest3() {
schoolService.selectTeachersInnerStudents();
}
@Test
public void nest3() {
schoolService.selectTeachersInnerStudents();
}
@Test
public void tx() {
teacherService.selectTeachers();
}
@Test
public void tx() {
teacherService.selectTeachers();
}
}

View File

@ -9,8 +9,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.baomidou.samples.seata.dao")
public class SeataApplication {
public static void main(String[] args) {
SpringApplication.run(SeataApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(SeataApplication.class, args);
}
}

View File

@ -4,16 +4,16 @@ package com.baomidou.samples.seata.common;
* 订单状态
*/
public enum OrderStatus {
/**
* INIT
*/
INIT,
/**
* SUCCESS
*/
SUCCESS,
/**
* FAIL
*/
FAIL
/**
* INIT
*/
INIT,
/**
* SUCCESS
*/
SUCCESS,
/**
* FAIL
*/
FAIL
}

View File

@ -15,12 +15,12 @@ import org.springframework.web.bind.annotation.RestController;
@Slf4j
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private OrderService orderService;
@PostMapping("/placeOrder")
public String placeOrder(@Validated @RequestBody PlaceOrderRequest request) {
orderService.placeOrder(request);
return "下单成功";
}
@PostMapping("/placeOrder")
public String placeOrder(@Validated @RequestBody PlaceOrderRequest request) {
orderService.placeOrder(request);
return "下单成功";
}
}

View File

@ -1,23 +1,24 @@
package com.baomidou.samples.seata.dto;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PlaceOrderRequest {
@NotNull
private Long userId;
@NotNull
private Long userId;
@NotNull
private Long productId;
@NotNull
private Long productId;
@NotNull
private Integer amount;
@NotNull
private Integer amount;
}

View File

@ -11,7 +11,7 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
public class ReduceBalanceRequest {
private Long userId;
private Long userId;
private Integer price;
private Integer price;
}

View File

@ -11,7 +11,7 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
public class ReduceStockRequest {
private Long productId;
private Long productId;
private Integer amount;
private Integer amount;
}

View File

@ -2,21 +2,22 @@ package com.baomidou.samples.seata.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.util.Date;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
@Data
@Builder
public class Account {
@TableId(type = IdType.AUTO)
private Long id;
@TableId(type = IdType.AUTO)
private Long id;
/**
* 余额
*/
private Double balance;
/**
* 余额
*/
private Double balance;
private Date lastUpdateTime;
private Date lastUpdateTime;
}

View File

@ -12,27 +12,27 @@ import lombok.Data;
@TableName("p_order")
public class Order {
@TableId(type = IdType.AUTO)
private Integer id;
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 用户ID
*/
private Long userId;
/**
* 商品ID
*/
private Long productId;
/**
* 订单状态
*/
private OrderStatus status;
/**
* 数量
*/
private Integer amount;
/**
* 总金额
*/
private Double totalPrice;
/**
* 用户ID
*/
private Long userId;
/**
* 商品ID
*/
private Long productId;
/**
* 订单状态
*/
private OrderStatus status;
/**
* 数量
*/
private Integer amount;
/**
* 总金额
*/
private Double totalPrice;
}

View File

@ -2,24 +2,25 @@ package com.baomidou.samples.seata.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.util.Date;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
@Data
@Builder
public class Product {
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 价格
*/
private Double price;
/**
* 库存
*/
private Integer stock;
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 价格
*/
private Double price;
/**
* 库存
*/
private Integer stock;
private Date lastUpdateTime;
private Date lastUpdateTime;
}

View File

@ -2,10 +2,10 @@ package com.baomidou.samples.seata.service;
public interface AccountService {
/**
* @param userId 用户 ID
* @param price 扣减金额
*/
void reduceBalance(Long userId, Double price);
/**
* @param userId 用户 ID
* @param price 扣减金额
*/
void reduceBalance(Long userId, Double price);
}

View File

@ -4,10 +4,10 @@ import com.baomidou.samples.seata.dto.PlaceOrderRequest;
public interface OrderService {
/**
* 下单
*
* @param placeOrderRequest 订单请求参数
*/
void placeOrder(PlaceOrderRequest placeOrderRequest);
/**
* 下单
*
* @param placeOrderRequest 订单请求参数
*/
void placeOrder(PlaceOrderRequest placeOrderRequest);
}

View File

@ -2,12 +2,12 @@ package com.baomidou.samples.seata.service;
public interface ProductService {
/**
* 扣减库存
*
* @param productId 商品 ID
* @param amount 扣减数量
* @return 商品总价
*/
Double reduceStock(Long productId, Integer amount);
/**
* 扣减库存
*
* @param productId 商品 ID
* @param amount 扣减数量
* @return 商品总价
*/
Double reduceStock(Long productId, Integer amount);
}

View File

@ -5,43 +5,44 @@ import com.baomidou.samples.seata.dao.AccountDao;
import com.baomidou.samples.seata.entity.Account;
import com.baomidou.samples.seata.service.AccountService;
import io.seata.core.context.RootContext;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Slf4j
@Service
public class AccountServiceImpl implements AccountService {
@Resource
private AccountDao accountDao;
@Resource
private AccountDao accountDao;
/**
* 事务传播特性设置为 REQUIRES_NEW 开启新的事务
*/
@DS("account")
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void reduceBalance(Long userId, Double price) {
log.info("=============ACCOUNT START=================");
log.info("当前 XID: {}", RootContext.getXID());
/**
* 事务传播特性设置为 REQUIRES_NEW 开启新的事务
*/
@DS("account")
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void reduceBalance(Long userId, Double price) {
log.info("=============ACCOUNT START=================");
log.info("当前 XID: {}", RootContext.getXID());
Account account = accountDao.selectById(userId);
Double balance = account.getBalance();
log.info("下单用户{}余额为 {},商品总价为{}", userId, balance, price);
Account account = accountDao.selectById(userId);
Double balance = account.getBalance();
log.info("下单用户{}余额为 {},商品总价为{}", userId, balance, price);
if (balance < price) {
log.warn("用户 {} 余额不足,当前余额:{}", userId, balance);
throw new RuntimeException("余额不足");
if (balance < price) {
log.warn("用户 {} 余额不足,当前余额:{}", userId, balance);
throw new RuntimeException("余额不足");
}
log.info("开始扣减用户 {} 余额", userId);
double currentBalance = account.getBalance() - price;
account.setBalance(currentBalance);
accountDao.updateById(account);
log.info("扣减用户 {} 余额成功,扣减后用户账户余额为{}", userId, currentBalance);
log.info("=============ACCOUNT END=================");
}
log.info("开始扣减用户 {} 余额", userId);
double currentBalance = account.getBalance() - price;
account.setBalance(currentBalance);
accountDao.updateById(account);
log.info("扣减用户 {} 余额成功,扣减后用户账户余额为{}", userId, currentBalance);
log.info("=============ACCOUNT END=================");
}
}

View File

@ -10,54 +10,55 @@ import com.baomidou.samples.seata.service.OrderService;
import com.baomidou.samples.seata.service.ProductService;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
@Resource
private OrderDao orderDao;
@Autowired
private AccountService accountService;
@Autowired
private ProductService productService;
@Resource
private OrderDao orderDao;
@Autowired
private AccountService accountService;
@Autowired
private ProductService productService;
@DS("order")
@Override
@Transactional
@GlobalTransactional
public void placeOrder(PlaceOrderRequest request) {
log.info("=============ORDER START=================");
Long userId = request.getUserId();
Long productId = request.getProductId();
Integer amount = request.getAmount();
log.info("收到下单请求,用户:{}, 商品:{},数量:{}", userId, productId, amount);
@DS("order")
@Override
@Transactional
@GlobalTransactional
public void placeOrder(PlaceOrderRequest request) {
log.info("=============ORDER START=================");
Long userId = request.getUserId();
Long productId = request.getProductId();
Integer amount = request.getAmount();
log.info("收到下单请求,用户:{}, 商品:{},数量:{}", userId, productId, amount);
log.info("当前 XID: {}", RootContext.getXID());
log.info("当前 XID: {}", RootContext.getXID());
Order order = Order.builder()
.userId(userId)
.productId(productId)
.status(OrderStatus.INIT)
.amount(amount)
.build();
Order order = Order.builder()
.userId(userId)
.productId(productId)
.status(OrderStatus.INIT)
.amount(amount)
.build();
orderDao.insert(order);
log.info("订单一阶段生成,等待扣库存付款中");
// 扣减库存并计算总价
Double totalPrice = productService.reduceStock(productId, amount);
// 扣减余额
accountService.reduceBalance(userId, totalPrice);
orderDao.insert(order);
log.info("订单一阶段生成,等待扣库存付款中");
// 扣减库存并计算总价
Double totalPrice = productService.reduceStock(productId, amount);
// 扣减余额
accountService.reduceBalance(userId, totalPrice);
order.setStatus(OrderStatus.SUCCESS);
order.setTotalPrice(totalPrice);
orderDao.updateById(order);
log.info("订单已成功下单");
log.info("=============ORDER END=================");
}
order.setStatus(OrderStatus.SUCCESS);
order.setTotalPrice(totalPrice);
orderDao.updateById(order);
log.info("订单已成功下单");
log.info("=============ORDER END=================");
}
}

View File

@ -5,46 +5,47 @@ import com.baomidou.samples.seata.dao.ProductDao;
import com.baomidou.samples.seata.entity.Product;
import com.baomidou.samples.seata.service.ProductService;
import io.seata.core.context.RootContext;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Slf4j
@Service
public class ProductServiceImpl implements ProductService {
@Resource
private ProductDao productDao;
@Resource
private ProductDao productDao;
/**
* 事务传播特性设置为 REQUIRES_NEW 开启新的事务
*/
@DS("product")
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public Double reduceStock(Long productId, Integer amount) {
log.info("=============PRODUCT START=================");
log.info("当前 XID: {}", RootContext.getXID());
/**
* 事务传播特性设置为 REQUIRES_NEW 开启新的事务
*/
@DS("product")
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public Double reduceStock(Long productId, Integer amount) {
log.info("=============PRODUCT START=================");
log.info("当前 XID: {}", RootContext.getXID());
// 检查库存
Product product = productDao.selectById(productId);
Integer stock = product.getStock();
log.info("商品编号为 {} 的库存为{},订单商品数量为{}", productId, stock, amount);
// 检查库存
Product product = productDao.selectById(productId);
Integer stock = product.getStock();
log.info("商品编号为 {} 的库存为{},订单商品数量为{}", productId, stock, amount);
if (stock < amount) {
log.warn("商品编号为{} 库存不足,当前库存:{}", productId, stock);
throw new RuntimeException("库存不足");
if (stock < amount) {
log.warn("商品编号为{} 库存不足,当前库存:{}", productId, stock);
throw new RuntimeException("库存不足");
}
log.info("开始扣减商品编号为 {} 库存,单价商品价格为{}", productId, product.getPrice());
// 扣减库存
int currentStock = stock - amount;
product.setStock(currentStock);
productDao.updateById(product);
double totalPrice = product.getPrice() * amount;
log.info("扣减商品编号为 {} 库存成功,扣减后库存为{}, {} 件商品总价为 {} ", productId, currentStock, amount, totalPrice);
log.info("=============PRODUCT END=================");
return totalPrice;
}
log.info("开始扣减商品编号为 {} 库存,单价商品价格为{}", productId, product.getPrice());
// 扣减库存
int currentStock = stock - amount;
product.setStock(currentStock);
productDao.updateById(product);
double totalPrice = product.getPrice() * amount;
log.info("扣减商品编号为 {} 库存成功,扣减后库存为{}, {} 件商品总价为 {} ", productId, currentStock, amount, totalPrice);
log.info("=============PRODUCT END=================");
return totalPrice;
}
}

View File

@ -8,8 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.baomidou.samples.spel.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -2,28 +2,29 @@ package com.baomidou.samples.spel.controller;
import com.baomidou.samples.spel.entity.User;
import com.baomidou.samples.spel.service.UserService;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserService userService;
@Autowired
private UserService userService;
@GetMapping("/users")
public List<User> usersFromSession(HttpServletRequest request) {
request.getSession().setAttribute("tenantName", "tenant1");
return userService.selectSpelBySession();
}
@GetMapping("/users")
public List<User> usersFromSession(HttpServletRequest request) {
request.getSession().setAttribute("tenantName", "tenant1");
return userService.selectSpelBySession();
}
@GetMapping("/users/header")
public String usersFromHeader() {
userService.selectSpelByHeader();
return "success";
}
@GetMapping("/users/header")
public String usersFromHeader() {
userService.selectSpelByHeader();
return "success";
}
}

View File

@ -2,43 +2,43 @@ package com.baomidou.samples.spel.entity;
public class User {
private Integer id;
private Integer id;
private String name;
private String name;
private Integer age;
private Integer age;
private String tenantName;
private String tenantName;
public Integer getId() {
return id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getTenantName() {
return tenantName;
}
public String getTenantName() {
return tenantName;
}
public void setTenantName(String tenantName) {
this.tenantName = tenantName;
}
public void setTenantName(String tenantName) {
this.tenantName = tenantName;
}
}

View File

@ -1,17 +1,18 @@
package com.baomidou.samples.spel.mapper;
import com.baomidou.samples.spel.entity.User;
import java.util.List;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
//@DS("slave")这里可以使用但不建议不要和service同时使用
public interface UserMapper {
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
boolean addUser(@Param("name") String name, @Param("age") Integer age);
@Insert("INSERT INTO user (name,age) values (#{name},#{age})")
boolean addUser(@Param("name") String name, @Param("age") Integer age);
@Select("SELECT * FROM user")
List<User> selectUsers();
@Select("SELECT * FROM user")
List<User> selectUsers();
}

View File

@ -2,15 +2,16 @@ package com.baomidou.samples.spel.service;
import com.baomidou.samples.spel.entity.User;
import java.util.List;
public interface UserService {
List selectSpelBySession();
List selectSpelBySession();
List selectSpelByHeader();
List selectSpelByHeader();
List selectSpelByKey(String tenantName);
List selectSpelByKey(String tenantName);
List selecSpelByTenant(User user);
List selecSpelByTenant(User user);
}

View File

@ -5,38 +5,39 @@ import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.samples.spel.entity.User;
import com.baomidou.samples.spel.mapper.UserMapper;
import com.baomidou.samples.spel.service.UserService;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
@DS("slave")
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private UserMapper userMapper;
@Override
@DS("#session.tenantName")
public List selectSpelBySession() {
return userMapper.selectUsers();
}
@Override
@DS("#session.tenantName")
public List selectSpelBySession() {
return userMapper.selectUsers();
}
@Override
@DS("#header.tenantName")
public List selectSpelByHeader() {
return userMapper.selectUsers();
}
@Override
@DS("#header.tenantName")
public List selectSpelByHeader() {
return userMapper.selectUsers();
}
@Override
@DS("#tenantName")
public List selectSpelByKey(String tenantName) {
return userMapper.selectUsers();
}
@Override
@DS("#tenantName")
public List selectSpelByKey(String tenantName) {
return userMapper.selectUsers();
}
@Override
@DS("#user.tenantName")
public List selecSpelByTenant(User user) {
return userMapper.selectUsers();
}
@Override
@DS("#user.tenantName")
public List selecSpelByTenant(User user) {
return userMapper.selectUsers();
}
}

View File

@ -1,12 +1,8 @@
package com.baomidou.samples.spel.test;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.baomidou.samples.spel.Application;
import com.baomidou.samples.spel.entity.User;
import com.baomidou.samples.spel.service.UserService;
import javax.servlet.http.HttpSession;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -19,51 +15,56 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.http.HttpSession;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {
@Autowired
private WebApplicationContext wac;
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Autowired
private UserService userService;
@Autowired
private HttpSession session;
private MockMvc mockMvc;
@Autowired
private UserService userService;
@Autowired
private HttpSession session;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void selectSpelBySession() {
session.setAttribute("tenantName", "tenant1");
userService.selectSpelBySession();
}
@Test
public void selectSpelBySession() {
session.setAttribute("tenantName", "tenant1");
userService.selectSpelBySession();
}
@Test
public void selectSpelByHeader() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/users/header")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("tenantName", "tenant1")
)
.andDo(print()).andExpect(status().isOk())
.andReturn().getResponse()
.getContentAsString();
}
@Test
public void selectSpelByHeader() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/users/header")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("tenantName", "tenant1")
)
.andDo(print()).andExpect(status().isOk())
.andReturn().getResponse()
.getContentAsString();
}
@Test
public void selectSpelByKey() {
userService.selectSpelByKey("tenant1");
}
@Test
public void selectSpelByKey() {
userService.selectSpelByKey("tenant1");
}
@Test
public void selecSpelByTenant() {
User user = new User();
user.setTenantName("tenant2");
userService.selecSpelByTenant(user);
}
@Test
public void selecSpelByTenant() {
User user = new User();
user.setTenantName("tenant2");
userService.selecSpelByTenant(user);
}
}

View File

@ -3,65 +3,66 @@ package com.baomidou.samples.load;
import com.baomidou.dynamic.datasource.provider.AbstractJdbcDataSourceProvider;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public DynamicDataSourceProvider dynamicDataSourceProvider() {
return new AbstractJdbcDataSourceProvider("org.h2.Driver", "jdbc:h2:mem:test", "sa", "") {
@Override
protected Map<String, DataSourceProperty> executeStmt(Statement statement)
throws SQLException {
//*************** 实际运行应直接从库中查出演示所以需要先插入数据***************
statement.execute("CREATE TABLE IF NOT EXISTS `DB`\n"
+ "(\n"
+ " `name` VARCHAR(30) NULL DEFAULT NULL,\n"
+ " `username` VARCHAR(30) NULL DEFAULT NULL,\n"
+ " `password` VARCHAR(30) NULL DEFAULT NULL,\n"
+ " `url` VARCHAR(30) NULL DEFAULT NULL,\n"
+ " `driver` VARCHAR(30) NULL DEFAULT NULL\n"
+ ")");
statement.executeUpdate(
"insert into DB values ('master','sa','','jdbc:h2:mem:test','org.h2.Driver')");
statement.executeUpdate(
"insert into DB values ('slave_1','sa','','jdbc:h2:mem:test','org.h2.Driver')");
statement.executeUpdate(
"insert into DB values ('slave_2','sa','','jdbc:h2:mem:test','org.h2.Driver')");
statement.executeUpdate(
"insert into DB values ('slave_3','sa','','jdbc:h2:mem:test','org.h2.Driver')");
Map<String, DataSourceProperty> map = new HashMap<>();
//*************** END ***************
@Bean
public DynamicDataSourceProvider dynamicDataSourceProvider() {
return new AbstractJdbcDataSourceProvider("org.h2.Driver", "jdbc:h2:mem:test", "sa", "") {
@Override
protected Map<String, DataSourceProperty> executeStmt(Statement statement)
throws SQLException {
//*************** 实际运行应直接从库中查出演示所以需要先插入数据***************
statement.execute("CREATE TABLE IF NOT EXISTS `DB`\n"
+ "(\n"
+ " `name` VARCHAR(30) NULL DEFAULT NULL,\n"
+ " `username` VARCHAR(30) NULL DEFAULT NULL,\n"
+ " `password` VARCHAR(30) NULL DEFAULT NULL,\n"
+ " `url` VARCHAR(30) NULL DEFAULT NULL,\n"
+ " `driver` VARCHAR(30) NULL DEFAULT NULL\n"
+ ")");
statement.executeUpdate(
"insert into DB values ('master','sa','','jdbc:h2:mem:test','org.h2.Driver')");
statement.executeUpdate(
"insert into DB values ('slave_1','sa','','jdbc:h2:mem:test','org.h2.Driver')");
statement.executeUpdate(
"insert into DB values ('slave_2','sa','','jdbc:h2:mem:test','org.h2.Driver')");
statement.executeUpdate(
"insert into DB values ('slave_3','sa','','jdbc:h2:mem:test','org.h2.Driver')");
Map<String, DataSourceProperty> map = new HashMap<>();
//*************** END ***************
ResultSet rs = statement.executeQuery("select * from DB");
while (rs.next()) {
String name = rs.getString("name");
String username = rs.getString("username");
String password = rs.getString("password");
String url = rs.getString("url");
String driver = rs.getString("driver");
DataSourceProperty property = new DataSourceProperty();
property.setUsername(username);
property.setPassword(password);
property.setUrl(url);
property.setDriverClassName(driver);
map.put(name, property);
}
return map;
}
};
}
ResultSet rs = statement.executeQuery("select * from DB");
while (rs.next()) {
String name = rs.getString("name");
String username = rs.getString("username");
String password = rs.getString("password");
String url = rs.getString("url");
String driver = rs.getString("driver");
DataSourceProperty property = new DataSourceProperty();
property.setUsername(username);
property.setPassword(password);
property.setUrl(url);
property.setDriverClassName(driver);
map.put(name, property);
}
return map;
}
};
}
}

View File

@ -16,10 +16,11 @@
*/
package com.baomidou.dynamic.datasource;
import org.springframework.jdbc.datasource.AbstractDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.AbstractDataSource;
/**
* 抽象动态获取数据源
@ -29,34 +30,34 @@ import org.springframework.jdbc.datasource.AbstractDataSource;
*/
public abstract class AbstractRoutingDataSource extends AbstractDataSource {
/**
* 子类实现决定最终数据源
*
* @return 数据源
*/
protected abstract DataSource determineDataSource();
/**
* 子类实现决定最终数据源
*
* @return 数据源
*/
protected abstract DataSource determineDataSource();
@Override
public Connection getConnection() throws SQLException {
return determineDataSource().getConnection();
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return determineDataSource().getConnection(username, password);
}
@Override
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> iface) throws SQLException {
if (iface.isInstance(this)) {
return (T) this;
@Override
public Connection getConnection() throws SQLException {
return determineDataSource().getConnection();
}
return determineDataSource().unwrap(iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return (iface.isInstance(this) || determineDataSource().isWrapperFor(iface));
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return determineDataSource().getConnection(username, password);
}
@Override
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> iface) throws SQLException {
if (iface.isInstance(this)) {
return (T) this;
}
return determineDataSource().unwrap(iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return (iface.isInstance(this) || determineDataSource().isWrapperFor(iface));
}
}

View File

@ -19,9 +19,10 @@ package com.baomidou.dynamic.datasource;
import com.baomidou.dynamic.datasource.matcher.ExpressionMatcher;
import com.baomidou.dynamic.datasource.matcher.Matcher;
import com.baomidou.dynamic.datasource.matcher.RegexMatcher;
import lombok.Getter;
import java.util.LinkedList;
import java.util.List;
import lombok.Getter;
/**
* 基于多种策略的自动切换数据源
@ -31,24 +32,24 @@ import lombok.Getter;
*/
public class DynamicDataSourceConfigure {
@Getter
private List<Matcher> matchers = new LinkedList<>();
@Getter
private List<Matcher> matchers = new LinkedList<>();
private DynamicDataSourceConfigure() {
}
private DynamicDataSourceConfigure() {
}
public static DynamicDataSourceConfigure config() {
return new DynamicDataSourceConfigure();
}
public static DynamicDataSourceConfigure config() {
return new DynamicDataSourceConfigure();
}
public DynamicDataSourceConfigure regexMatchers(String pattern, String ds) {
matchers.add(new RegexMatcher(pattern, ds));
return this;
}
public DynamicDataSourceConfigure regexMatchers(String pattern, String ds) {
matchers.add(new RegexMatcher(pattern, ds));
return this;
}
public DynamicDataSourceConfigure expressionMatchers(String expression, String ds) {
matchers.add(new ExpressionMatcher(expression, ds));
return this;
}
public DynamicDataSourceConfigure expressionMatchers(String expression, String ds) {
matchers.add(new ExpressionMatcher(expression, ds));
return this;
}
}

View File

@ -17,10 +17,11 @@
package com.baomidou.dynamic.datasource;
import com.baomidou.dynamic.datasource.strategy.DynamicDataSourceStrategy;
import lombok.Data;
import javax.sql.DataSource;
import java.util.LinkedList;
import java.util.List;
import javax.sql.DataSource;
import lombok.Data;
/**
* 分组数据源
@ -31,30 +32,30 @@ import lombok.Data;
@Data
public class DynamicGroupDataSource {
private String groupName;
private String groupName;
private DynamicDataSourceStrategy dynamicDataSourceStrategy;
private DynamicDataSourceStrategy dynamicDataSourceStrategy;
private List<DataSource> dataSources = new LinkedList<>();
private List<DataSource> dataSources = new LinkedList<>();
public DynamicGroupDataSource(String groupName, DynamicDataSourceStrategy dynamicDataSourceStrategy) {
this.groupName = groupName;
this.dynamicDataSourceStrategy = dynamicDataSourceStrategy;
}
public DynamicGroupDataSource(String groupName, DynamicDataSourceStrategy dynamicDataSourceStrategy) {
this.groupName = groupName;
this.dynamicDataSourceStrategy = dynamicDataSourceStrategy;
}
public void addDatasource(DataSource dataSource) {
dataSources.add(dataSource);
}
public void addDatasource(DataSource dataSource) {
dataSources.add(dataSource);
}
public void removeDatasource(DataSource dataSource) {
dataSources.remove(dataSource);
}
public void removeDatasource(DataSource dataSource) {
dataSources.remove(dataSource);
}
public DataSource determineDataSource() {
return dynamicDataSourceStrategy.determineDataSource(dataSources);
}
public DataSource determineDataSource() {
return dynamicDataSourceStrategy.determineDataSource(dataSources);
}
public int size() {
return dataSources.size();
}
public int size() {
return dataSources.size();
}
}

View File

@ -21,18 +21,19 @@ import com.baomidou.dynamic.datasource.strategy.DynamicDataSourceStrategy;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.p6spy.engine.spy.P6DataSource;
import io.seata.rm.datasource.DataSourceProxy;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils;
import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.sql.DataSource;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils;
/**
* 核心动态数据源组件
@ -43,227 +44,227 @@ import org.springframework.util.StringUtils;
@Slf4j
public class DynamicRoutingDataSource extends AbstractRoutingDataSource implements InitializingBean, DisposableBean {
private static final String UNDERLINE = "_";
private static final String UNDERLINE = "_";
@Setter
private DynamicDataSourceProvider provider;
@Setter
private String primary;
@Setter
private boolean strict;
@Setter
private Class<? extends DynamicDataSourceStrategy> strategy;
private boolean p6spy;
private boolean seata;
/**
* 所有数据库
*/
private Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();
/**
* 分组数据库
*/
private Map<String, DynamicGroupDataSource> groupDataSources = new ConcurrentHashMap<>();
@Setter
private DynamicDataSourceProvider provider;
@Setter
private String primary;
@Setter
private boolean strict;
@Setter
private Class<? extends DynamicDataSourceStrategy> strategy;
private boolean p6spy;
private boolean seata;
/**
* 所有数据库
*/
private Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();
/**
* 分组数据库
*/
private Map<String, DynamicGroupDataSource> groupDataSources = new ConcurrentHashMap<>();
@Override
public DataSource determineDataSource() {
return getDataSource(DynamicDataSourceContextHolder.peek());
}
private DataSource determinePrimaryDataSource() {
log.debug("dynamic-datasource switch to the primary datasource");
return groupDataSources.containsKey(primary) ? groupDataSources.get(primary).determineDataSource() : dataSourceMap.get(primary);
}
/**
* 获取当前所有的数据源
*
* @return 当前所有数据源
*/
public Map<String, DataSource> getCurrentDataSources() {
return dataSourceMap;
}
/**
* 获取的当前所有的分组数据源
*
* @return 当前所有的分组数据源
*/
public Map<String, DynamicGroupDataSource> getCurrentGroupDataSources() {
return groupDataSources;
}
/**
* 获取数据源
*
* @param ds 数据源名称
* @return 数据源
*/
public DataSource getDataSource(String ds) {
if (StringUtils.isEmpty(ds)) {
return determinePrimaryDataSource();
} else if (!groupDataSources.isEmpty() && groupDataSources.containsKey(ds)) {
log.debug("dynamic-datasource switch to the datasource named [{}]", ds);
return groupDataSources.get(ds).determineDataSource();
} else if (dataSourceMap.containsKey(ds)) {
log.debug("dynamic-datasource switch to the datasource named [{}]", ds);
return dataSourceMap.get(ds);
@Override
public DataSource determineDataSource() {
return getDataSource(DynamicDataSourceContextHolder.peek());
}
if (strict) {
throw new RuntimeException("dynamic-datasource could not find a datasource named" + ds);
}
return determinePrimaryDataSource();
}
/**
* 添加数据源
*
* @param ds 数据源名称
* @param dataSource 数据源
*/
public synchronized void addDataSource(String ds, DataSource dataSource) {
if (!dataSourceMap.containsKey(ds)) {
dataSource = wrapDataSource(ds, dataSource);
dataSourceMap.put(ds, dataSource);
this.addGroupDataSource(ds, dataSource);
log.info("dynamic-datasource - load a datasource named [{}] success", ds);
} else {
log.warn("dynamic-datasource - load a datasource named [{}] failed, because it already exist", ds);
private DataSource determinePrimaryDataSource() {
log.debug("dynamic-datasource switch to the primary datasource");
return groupDataSources.containsKey(primary) ? groupDataSources.get(primary).determineDataSource() : dataSourceMap.get(primary);
}
}
private DataSource wrapDataSource(String ds, DataSource dataSource) {
if (p6spy) {
dataSource = new P6DataSource(dataSource);
log.info("dynamic-datasource [{}] wrap p6spy plugin", ds);
/**
* 获取当前所有的数据源
*
* @return 当前所有数据源
*/
public Map<String, DataSource> getCurrentDataSources() {
return dataSourceMap;
}
if (seata) {
dataSource = new DataSourceProxy(dataSource);
log.info("dynamic-datasource [{}] wrap seata plugin", ds);
}
return dataSource;
}
private void addGroupDataSource(String ds, DataSource dataSource) {
if (ds.contains(UNDERLINE)) {
String group = ds.split(UNDERLINE)[0];
if (groupDataSources.containsKey(group)) {
groupDataSources.get(group).addDatasource(dataSource);
} else {
/**
* 获取的当前所有的分组数据源
*
* @return 当前所有的分组数据源
*/
public Map<String, DynamicGroupDataSource> getCurrentGroupDataSources() {
return groupDataSources;
}
/**
* 获取数据源
*
* @param ds 数据源名称
* @return 数据源
*/
public DataSource getDataSource(String ds) {
if (StringUtils.isEmpty(ds)) {
return determinePrimaryDataSource();
} else if (!groupDataSources.isEmpty() && groupDataSources.containsKey(ds)) {
log.debug("dynamic-datasource switch to the datasource named [{}]", ds);
return groupDataSources.get(ds).determineDataSource();
} else if (dataSourceMap.containsKey(ds)) {
log.debug("dynamic-datasource switch to the datasource named [{}]", ds);
return dataSourceMap.get(ds);
}
if (strict) {
throw new RuntimeException("dynamic-datasource could not find a datasource named" + ds);
}
return determinePrimaryDataSource();
}
/**
* 添加数据源
*
* @param ds 数据源名称
* @param dataSource 数据源
*/
public synchronized void addDataSource(String ds, DataSource dataSource) {
if (!dataSourceMap.containsKey(ds)) {
dataSource = wrapDataSource(ds, dataSource);
dataSourceMap.put(ds, dataSource);
this.addGroupDataSource(ds, dataSource);
log.info("dynamic-datasource - load a datasource named [{}] success", ds);
} else {
log.warn("dynamic-datasource - load a datasource named [{}] failed, because it already exist", ds);
}
}
private DataSource wrapDataSource(String ds, DataSource dataSource) {
if (p6spy) {
dataSource = new P6DataSource(dataSource);
log.info("dynamic-datasource [{}] wrap p6spy plugin", ds);
}
if (seata) {
dataSource = new DataSourceProxy(dataSource);
log.info("dynamic-datasource [{}] wrap seata plugin", ds);
}
return dataSource;
}
private void addGroupDataSource(String ds, DataSource dataSource) {
if (ds.contains(UNDERLINE)) {
String group = ds.split(UNDERLINE)[0];
if (groupDataSources.containsKey(group)) {
groupDataSources.get(group).addDatasource(dataSource);
} else {
try {
DynamicGroupDataSource groupDatasource = new DynamicGroupDataSource(group, strategy.newInstance());
groupDatasource.addDatasource(dataSource);
groupDataSources.put(group, groupDatasource);
} catch (Exception e) {
log.error("dynamic-datasource - add the datasource named [{}] error", ds, e);
dataSourceMap.remove(ds);
}
}
}
}
/**
* 删除数据源
*
* @param ds 数据源名称
*/
public synchronized void removeDataSource(String ds) {
if (!StringUtils.hasText(ds)) {
throw new RuntimeException("remove parameter could not be empty");
}
if (primary.equals(ds)) {
throw new RuntimeException("could not remove primary datasource");
}
if (dataSourceMap.containsKey(ds)) {
DataSource dataSource = dataSourceMap.get(ds);
try {
closeDataSource(ds, dataSource);
} catch (Exception e) {
throw new RuntimeException("dynamic-datasource - remove the database named " + ds + " failed", e);
}
dataSourceMap.remove(ds);
if (ds.contains(UNDERLINE)) {
String group = ds.split(UNDERLINE)[0];
if (groupDataSources.containsKey(group)) {
groupDataSources.get(group).removeDatasource(dataSource);
}
}
log.info("dynamic-datasource - remove the database named [{}] success", ds);
} else {
log.warn("dynamic-datasource - could not find a database named [{}]", ds);
}
}
public void setP6spy(boolean p6spy) {
if (p6spy) {
try {
Class.forName("com.p6spy.engine.spy.P6DataSource");
log.info("dynamic-datasource detect P6SPY plugin and enabled it");
this.p6spy = true;
} catch (Exception e) {
log.warn("dynamic-datasource enabled P6SPY ,however without p6spy dependency");
}
} else {
this.p6spy = false;
}
}
public void setSeata(boolean seata) {
if (seata) {
try {
Class.forName("io.seata.rm.datasource.DataSourceProxy");
this.seata = true;
log.info("dynamic-datasource detect ALIBABA SEATA and enabled it");
} catch (Exception e) {
this.seata = false;
log.warn("dynamic-datasource enabled ALIBABA SEATA ,however without seata dependency");
}
}
}
@Override
public void destroy() throws Exception {
log.info("dynamic-datasource start closing ....");
for (Map.Entry<String, DataSource> item : dataSourceMap.entrySet()) {
closeDataSource(item.getKey(), item.getValue());
}
log.info("dynamic-datasource all closed success,bye");
}
private void closeDataSource(String name, DataSource dataSource)
throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
if (seata) {
DataSourceProxy dataSourceProxy = (DataSourceProxy) dataSource;
dataSource = dataSourceProxy.getTargetDataSource();
}
if (p6spy) {
Field realDataSourceField = P6DataSource.class.getDeclaredField("realDataSource");
realDataSourceField.setAccessible(true);
dataSource = (DataSource) realDataSourceField.get(dataSource);
}
Class<? extends DataSource> clazz = dataSource.getClass();
try {
DynamicGroupDataSource groupDatasource = new DynamicGroupDataSource(group, strategy.newInstance());
groupDatasource.addDatasource(dataSource);
groupDataSources.put(group, groupDatasource);
} catch (Exception e) {
log.error("dynamic-datasource - add the datasource named [{}] error", ds, e);
dataSourceMap.remove(ds);
Method closeMethod = clazz.getDeclaredMethod("close");
closeMethod.invoke(dataSource);
} catch (NoSuchMethodException e) {
log.warn("dynamic-datasource close the datasource named [{}] failed,", name);
}
}
}
}
/**
* 删除数据源
*
* @param ds 数据源名称
*/
public synchronized void removeDataSource(String ds) {
if (!StringUtils.hasText(ds)) {
throw new RuntimeException("remove parameter could not be empty");
}
if (primary.equals(ds)) {
throw new RuntimeException("could not remove primary datasource");
}
if (dataSourceMap.containsKey(ds)) {
DataSource dataSource = dataSourceMap.get(ds);
try {
closeDataSource(ds, dataSource);
} catch (Exception e) {
throw new RuntimeException("dynamic-datasource - remove the database named " + ds + " failed", e);
}
dataSourceMap.remove(ds);
if (ds.contains(UNDERLINE)) {
String group = ds.split(UNDERLINE)[0];
if (groupDataSources.containsKey(group)) {
groupDataSources.get(group).removeDatasource(dataSource);
@Override
public void afterPropertiesSet() throws Exception {
Map<String, DataSource> dataSources = provider.loadDataSources();
// 添加并分组数据源
for (Map.Entry<String, DataSource> dsItem : dataSources.entrySet()) {
addDataSource(dsItem.getKey(), dsItem.getValue());
}
// 检测默认数据源设置
if (groupDataSources.containsKey(primary)) {
log.info("dynamic-datasource initial loaded [{}] datasource,primary group datasource named [{}]", dataSources.size(), primary);
} else if (dataSourceMap.containsKey(primary)) {
log.info("dynamic-datasource initial loaded [{}] datasource,primary datasource named [{}]", dataSources.size(), primary);
} else {
throw new RuntimeException("dynamic-datasource Please check the setting of primary");
}
}
log.info("dynamic-datasource - remove the database named [{}] success", ds);
} else {
log.warn("dynamic-datasource - could not find a database named [{}]", ds);
}
}
public void setP6spy(boolean p6spy) {
if (p6spy) {
try {
Class.forName("com.p6spy.engine.spy.P6DataSource");
log.info("dynamic-datasource detect P6SPY plugin and enabled it");
this.p6spy = true;
} catch (Exception e) {
log.warn("dynamic-datasource enabled P6SPY ,however without p6spy dependency");
}
} else {
this.p6spy = false;
}
}
public void setSeata(boolean seata) {
if (seata) {
try {
Class.forName("io.seata.rm.datasource.DataSourceProxy");
this.seata = true;
log.info("dynamic-datasource detect ALIBABA SEATA and enabled it");
} catch (Exception e) {
this.seata = false;
log.warn("dynamic-datasource enabled ALIBABA SEATA ,however without seata dependency");
}
}
}
@Override
public void destroy() throws Exception {
log.info("dynamic-datasource start closing ....");
for (Map.Entry<String, DataSource> item : dataSourceMap.entrySet()) {
closeDataSource(item.getKey(), item.getValue());
}
log.info("dynamic-datasource all closed success,bye");
}
private void closeDataSource(String name, DataSource dataSource)
throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
if (seata) {
DataSourceProxy dataSourceProxy = (DataSourceProxy) dataSource;
dataSource = dataSourceProxy.getTargetDataSource();
}
if (p6spy) {
Field realDataSourceField = P6DataSource.class.getDeclaredField("realDataSource");
realDataSourceField.setAccessible(true);
dataSource = (DataSource) realDataSourceField.get(dataSource);
}
Class<? extends DataSource> clazz = dataSource.getClass();
try {
Method closeMethod = clazz.getDeclaredMethod("close");
closeMethod.invoke(dataSource);
} catch (NoSuchMethodException e) {
log.warn("dynamic-datasource close the datasource named [{}] failed,", name);
}
}
@Override
public void afterPropertiesSet() throws Exception {
Map<String, DataSource> dataSources = provider.loadDataSources();
// 添加并分组数据源
for (Map.Entry<String, DataSource> dsItem : dataSources.entrySet()) {
addDataSource(dsItem.getKey(), dsItem.getValue());
}
// 检测默认数据源设置
if (groupDataSources.containsKey(primary)) {
log.info("dynamic-datasource initial loaded [{}] datasource,primary group datasource named [{}]", dataSources.size(), primary);
} else if (dataSourceMap.containsKey(primary)) {
log.info("dynamic-datasource initial loaded [{}] datasource,primary datasource named [{}]", dataSources.size(), primary);
} else {
throw new RuntimeException("dynamic-datasource Please check the setting of primary");
}
}
}

View File

@ -17,11 +17,7 @@
package com.baomidou.dynamic.datasource.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.*;
/**
* The core Annotation to switch datasource. It can be annotate at class or method.
@ -34,10 +30,10 @@ import java.lang.annotation.Target;
@Documented
public @interface DS {
/**
* groupName or specific database name or spring SPEL name.
*
* @return the database you want to switch
*/
String value();
/**
* groupName or specific database name or spring SPEL name.
*
* @return the database you want to switch
*/
String value();
}

View File

@ -16,9 +16,10 @@
*/
package com.baomidou.dynamic.datasource.aop;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import java.lang.reflect.Method;
import java.util.Map;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
/**
* @author TaoYu
@ -26,22 +27,22 @@ import org.springframework.aop.aspectj.AspectJExpressionPointcut;
*/
public class DynamicAspectJExpressionPointcut extends AspectJExpressionPointcut {
private Map<String, String> matchesCache;
private Map<String, String> matchesCache;
private String ds;
private String ds;
public DynamicAspectJExpressionPointcut(String expression, String ds, Map<String, String> matchesCache) {
this.ds = ds;
this.matchesCache = matchesCache;
setExpression(expression);
}
@Override
public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
boolean matches = super.matches(method, targetClass, beanHasIntroductions);
if (matches) {
matchesCache.put(targetClass.getName() + "." + method.getName(), ds);
public DynamicAspectJExpressionPointcut(String expression, String ds, Map<String, String> matchesCache) {
this.ds = ds;
this.matchesCache = matchesCache;
setExpression(expression);
}
@Override
public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
boolean matches = super.matches(method, targetClass, beanHasIntroductions);
if (matches) {
matchesCache.put(targetClass.getName() + "." + method.getName(), ds);
}
return matches;
}
return matches;
}
}

View File

@ -21,10 +21,6 @@ import com.baomidou.dynamic.datasource.matcher.Matcher;
import com.baomidou.dynamic.datasource.matcher.RegexMatcher;
import com.baomidou.dynamic.datasource.processor.DsProcessor;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.Setter;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
@ -36,90 +32,95 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author TaoYu
* @since 1.2.0
*/
public class DynamicDataSourceAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
/**
* The identification of SPEL
*/
private static final String DYNAMIC_PREFIX = "#";
/**
* The identification of SPEL
*/
private static final String DYNAMIC_PREFIX = "#";
@Setter
private DsProcessor dsProcessor;
@Setter
private DsProcessor dsProcessor;
private Advice advice;
private Advice advice;
private Pointcut pointcut;
private Pointcut pointcut;
private Map<String, String> matchesCache = new HashMap<>();
private Map<String, String> matchesCache = new HashMap<>();
public DynamicDataSourceAdvisor(List<Matcher> matchers) {
this.pointcut = buildPointcut(matchers);
this.advice = buildAdvice();
}
private Advice buildAdvice() {
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
try {
Method method = invocation.getMethod();
String methodPath = invocation.getThis().getClass().getName() + "." + method.getName();
String key = matchesCache.get(methodPath);
if (key != null && !key.isEmpty() && key.startsWith(DYNAMIC_PREFIX)) {
key = dsProcessor.determineDatasource(invocation, key);
}
DynamicDataSourceContextHolder.push(key);
return invocation.proceed();
} finally {
DynamicDataSourceContextHolder.poll();
}
}
};
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public Advice getAdvice() {
return this.advice;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (this.advice instanceof BeanFactoryAware) {
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
public DynamicDataSourceAdvisor(List<Matcher> matchers) {
this.pointcut = buildPointcut(matchers);
this.advice = buildAdvice();
}
}
private Pointcut buildPointcut(List<Matcher> matchers) {
ComposablePointcut composablePointcut = null;
for (Matcher matcher : matchers) {
if (matcher instanceof RegexMatcher) {
RegexMatcher regexMatcher = (RegexMatcher) matcher;
Pointcut pointcut = new DynamicJdkRegexpMethodPointcut(regexMatcher.getPattern(), regexMatcher.getDs(), matchesCache);
if (composablePointcut == null) {
composablePointcut = new ComposablePointcut(pointcut);
} else {
composablePointcut.union(pointcut);
}
} else {
ExpressionMatcher expressionMatcher = (ExpressionMatcher) matcher;
Pointcut pointcut = new DynamicAspectJExpressionPointcut(expressionMatcher.getExpression(), expressionMatcher.getDs(),
matchesCache);
if (composablePointcut == null) {
composablePointcut = new ComposablePointcut(pointcut);
} else {
composablePointcut.union(pointcut);
}
}
private Advice buildAdvice() {
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
try {
Method method = invocation.getMethod();
String methodPath = invocation.getThis().getClass().getName() + "." + method.getName();
String key = matchesCache.get(methodPath);
if (key != null && !key.isEmpty() && key.startsWith(DYNAMIC_PREFIX)) {
key = dsProcessor.determineDatasource(invocation, key);
}
DynamicDataSourceContextHolder.push(key);
return invocation.proceed();
} finally {
DynamicDataSourceContextHolder.poll();
}
}
};
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public Advice getAdvice() {
return this.advice;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (this.advice instanceof BeanFactoryAware) {
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
}
}
private Pointcut buildPointcut(List<Matcher> matchers) {
ComposablePointcut composablePointcut = null;
for (Matcher matcher : matchers) {
if (matcher instanceof RegexMatcher) {
RegexMatcher regexMatcher = (RegexMatcher) matcher;
Pointcut pointcut = new DynamicJdkRegexpMethodPointcut(regexMatcher.getPattern(), regexMatcher.getDs(), matchesCache);
if (composablePointcut == null) {
composablePointcut = new ComposablePointcut(pointcut);
} else {
composablePointcut.union(pointcut);
}
} else {
ExpressionMatcher expressionMatcher = (ExpressionMatcher) matcher;
Pointcut pointcut = new DynamicAspectJExpressionPointcut(expressionMatcher.getExpression(), expressionMatcher.getDs(),
matchesCache);
if (composablePointcut == null) {
composablePointcut = new ComposablePointcut(pointcut);
} else {
composablePointcut.union(pointcut);
}
}
}
return composablePointcut;
}
return composablePointcut;
}
}

View File

@ -32,37 +32,37 @@ import org.springframework.beans.factory.BeanFactoryAware;
* @since 1.2.0
*/
public class DynamicDataSourceAnnotationAdvisor extends AbstractPointcutAdvisor implements
BeanFactoryAware {
BeanFactoryAware {
private Advice advice;
private Advice advice;
private Pointcut pointcut;
private Pointcut pointcut;
public DynamicDataSourceAnnotationAdvisor(@NonNull DynamicDataSourceAnnotationInterceptor dynamicDataSourceAnnotationInterceptor) {
this.advice = dynamicDataSourceAnnotationInterceptor;
this.pointcut = buildPointcut();
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public Advice getAdvice() {
return this.advice;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (this.advice instanceof BeanFactoryAware) {
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
public DynamicDataSourceAnnotationAdvisor(@NonNull DynamicDataSourceAnnotationInterceptor dynamicDataSourceAnnotationInterceptor) {
this.advice = dynamicDataSourceAnnotationInterceptor;
this.pointcut = buildPointcut();
}
}
private Pointcut buildPointcut() {
Pointcut cpc = new AnnotationMatchingPointcut(DS.class, true);
Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(DS.class);
return new ComposablePointcut(cpc).union(mpc);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public Advice getAdvice() {
return this.advice;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (this.advice instanceof BeanFactoryAware) {
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
}
}
private Pointcut buildPointcut() {
Pointcut cpc = new AnnotationMatchingPointcut(DS.class, true);
Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(DS.class);
return new ComposablePointcut(cpc).union(mpc);
}
}

View File

@ -20,12 +20,13 @@ import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.processor.DsProcessor;
import com.baomidou.dynamic.datasource.support.DataSourceClassResolver;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import java.lang.reflect.Method;
import lombok.Setter;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.annotation.AnnotationUtils;
import java.lang.reflect.Method;
/**
* Core Interceptor of Dynamic Datasource
*
@ -34,29 +35,29 @@ import org.springframework.core.annotation.AnnotationUtils;
*/
public class DynamicDataSourceAnnotationInterceptor implements MethodInterceptor {
/**
* The identification of SPEL.
*/
private static final String DYNAMIC_PREFIX = "#";
private static final DataSourceClassResolver RESOLVER = new DataSourceClassResolver();
@Setter
private DsProcessor dsProcessor;
/**
* The identification of SPEL.
*/
private static final String DYNAMIC_PREFIX = "#";
private static final DataSourceClassResolver RESOLVER = new DataSourceClassResolver();
@Setter
private DsProcessor dsProcessor;
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
try {
DynamicDataSourceContextHolder.push(determineDatasource(invocation));
return invocation.proceed();
} finally {
DynamicDataSourceContextHolder.poll();
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
try {
DynamicDataSourceContextHolder.push(determineDatasource(invocation));
return invocation.proceed();
} finally {
DynamicDataSourceContextHolder.poll();
}
}
}
private String determineDatasource(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
DS ds = method.isAnnotationPresent(DS.class) ? method.getAnnotation(DS.class)
: AnnotationUtils.findAnnotation(RESOLVER.targetClass(invocation), DS.class);
String key = ds.value();
return (!key.isEmpty() && key.startsWith(DYNAMIC_PREFIX)) ? dsProcessor.determineDatasource(invocation, key) : key;
}
private String determineDatasource(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
DS ds = method.isAnnotationPresent(DS.class) ? method.getAnnotation(DS.class)
: AnnotationUtils.findAnnotation(RESOLVER.targetClass(invocation), DS.class);
String key = ds.value();
return (!key.isEmpty() && key.startsWith(DYNAMIC_PREFIX)) ? dsProcessor.determineDatasource(invocation, key) : key;
}
}

View File

@ -16,31 +16,32 @@
*/
package com.baomidou.dynamic.datasource.aop;
import java.util.Map;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import java.util.Map;
/**
* @author TaoYu
* @since 2.5.0
*/
public class DynamicJdkRegexpMethodPointcut extends JdkRegexpMethodPointcut {
private Map<String, String> matchesCache;
private Map<String, String> matchesCache;
private String ds;
private String ds;
public DynamicJdkRegexpMethodPointcut(String pattern, String ds, Map<String, String> matchesCache) {
this.ds = ds;
this.matchesCache = matchesCache;
setPattern(pattern);
}
@Override
protected boolean matches(String pattern, int patternIndex) {
boolean matches = super.matches(pattern, patternIndex);
if (matches) {
matchesCache.put(pattern, ds);
public DynamicJdkRegexpMethodPointcut(String pattern, String ds, Map<String, String> matchesCache) {
this.ds = ds;
this.matchesCache = matchesCache;
setPattern(pattern);
}
@Override
protected boolean matches(String pattern, int patternIndex) {
boolean matches = super.matches(pattern, patternIndex);
if (matches) {
matchesCache.put(pattern, ds);
}
return matches;
}
return matches;
}
}

View File

@ -18,11 +18,12 @@ package com.baomidou.dynamic.datasource.creator;
import com.baomidou.dynamic.datasource.exception.ErrorCreateDataSourceException;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import java.lang.reflect.Method;
import javax.sql.DataSource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import javax.sql.DataSource;
import java.lang.reflect.Method;
/**
* 基础数据源创建器
*
@ -33,62 +34,62 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BasicDataSourceCreator {
private static Method createMethod;
private static Method typeMethod;
private static Method urlMethod;
private static Method usernameMethod;
private static Method passwordMethod;
private static Method driverClassNameMethod;
private static Method buildMethod;
private static Method createMethod;
private static Method typeMethod;
private static Method urlMethod;
private static Method usernameMethod;
private static Method passwordMethod;
private static Method driverClassNameMethod;
private static Method buildMethod;
static {
//to support springboot 1.5 and 2.x
Class<?> builderClass = null;
try {
builderClass = Class.forName("org.springframework.boot.jdbc.DataSourceBuilder");
} catch (Exception ignored) {
static {
//to support springboot 1.5 and 2.x
Class<?> builderClass = null;
try {
builderClass = Class.forName("org.springframework.boot.jdbc.DataSourceBuilder");
} catch (Exception ignored) {
}
if (builderClass == null) {
try {
builderClass = Class.forName("org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder");
} catch (Exception e) {
log.warn("not in springBoot ENV,could not create BasicDataSourceCreator");
}
}
if (builderClass != null) {
try {
createMethod = builderClass.getDeclaredMethod("create");
typeMethod = builderClass.getDeclaredMethod("type", Class.class);
urlMethod = builderClass.getDeclaredMethod("url", String.class);
usernameMethod = builderClass.getDeclaredMethod("username", String.class);
passwordMethod = builderClass.getDeclaredMethod("password", String.class);
driverClassNameMethod = builderClass.getDeclaredMethod("driverClassName", String.class);
buildMethod = builderClass.getDeclaredMethod("build");
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (builderClass == null) {
try {
builderClass = Class.forName("org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder");
} catch (Exception e) {
log.warn("not in springBoot ENV,could not create BasicDataSourceCreator");
}
}
if (builderClass != null) {
try {
createMethod = builderClass.getDeclaredMethod("create");
typeMethod = builderClass.getDeclaredMethod("type", Class.class);
urlMethod = builderClass.getDeclaredMethod("url", String.class);
usernameMethod = builderClass.getDeclaredMethod("username", String.class);
passwordMethod = builderClass.getDeclaredMethod("password", String.class);
driverClassNameMethod = builderClass.getDeclaredMethod("driverClassName", String.class);
buildMethod = builderClass.getDeclaredMethod("build");
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 创建基础数据源
*
* @param dataSourceProperty 数据源参数
* @return 数据源
*/
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
try {
Object o1 = createMethod.invoke(null);
Object o2 = typeMethod.invoke(o1, dataSourceProperty.getType());
Object o3 = urlMethod.invoke(o2, dataSourceProperty.getUrl());
Object o4 = usernameMethod.invoke(o3, dataSourceProperty.getUsername());
Object o5 = passwordMethod.invoke(o4, dataSourceProperty.getPassword());
Object o6 = driverClassNameMethod.invoke(o5, dataSourceProperty.getDriverClassName());
return (DataSource) buildMethod.invoke(o6);
} catch (Exception e) {
throw new ErrorCreateDataSourceException(
"dynamic-datasource create basic database named " + dataSourceProperty.getPoolName() + " error");
/**
* 创建基础数据源
*
* @param dataSourceProperty 数据源参数
* @return 数据源
*/
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
try {
Object o1 = createMethod.invoke(null);
Object o2 = typeMethod.invoke(o1, dataSourceProperty.getType());
Object o3 = urlMethod.invoke(o2, dataSourceProperty.getUrl());
Object o4 = usernameMethod.invoke(o3, dataSourceProperty.getUsername());
Object o5 = passwordMethod.invoke(o4, dataSourceProperty.getPassword());
Object o6 = driverClassNameMethod.invoke(o5, dataSourceProperty.getDriverClassName());
return (DataSource) buildMethod.invoke(o6);
} catch (Exception e) {
throw new ErrorCreateDataSourceException(
"dynamic-datasource create basic database named " + dataSourceProperty.getPoolName() + " error");
}
}
}
}

View File

@ -16,16 +16,17 @@
*/
package com.baomidou.dynamic.datasource.creator;
import static com.baomidou.dynamic.datasource.support.DdConstants.DRUID_DATASOURCE;
import static com.baomidou.dynamic.datasource.support.DdConstants.HIKARI_DATASOURCE;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.support.ScriptRunner;
import javax.sql.DataSource;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import javax.sql.DataSource;
import static com.baomidou.dynamic.datasource.support.DdConstants.DRUID_DATASOURCE;
import static com.baomidou.dynamic.datasource.support.DdConstants.HIKARI_DATASOURCE;
/**
* 数据源创建器
*
@ -36,129 +37,129 @@ import org.springframework.util.StringUtils;
@Setter
public class DataSourceCreator {
/**
* 是否存在druid
*/
private static Boolean druidExists = false;
/**
* 是否存在hikari
*/
private static Boolean hikariExists = false;
/**
* 是否存在druid
*/
private static Boolean druidExists = false;
/**
* 是否存在hikari
*/
private static Boolean hikariExists = false;
static {
try {
Class.forName(DRUID_DATASOURCE);
druidExists = true;
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName(HIKARI_DATASOURCE);
hikariExists = true;
} catch (ClassNotFoundException ignored) {
}
}
private BasicDataSourceCreator basicDataSourceCreator;
private JndiDataSourceCreator jndiDataSourceCreator;
private HikariDataSourceCreator hikariDataSourceCreator;
private DruidDataSourceCreator druidDataSourceCreator;
private String globalPublicKey;
/**
* 创建数据源
*
* @param dataSourceProperty 数据源信息
* @return 数据源
*/
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
DataSource dataSource;
//如果是jndi数据源
String jndiName = dataSourceProperty.getJndiName();
if (jndiName != null && !jndiName.isEmpty()) {
dataSource = createJNDIDataSource(jndiName);
} else {
Class<? extends DataSource> type = dataSourceProperty.getType();
if (type == null) {
if (druidExists) {
dataSource = createDruidDataSource(dataSourceProperty);
} else if (hikariExists) {
dataSource = createHikariDataSource(dataSourceProperty);
} else {
dataSource = createBasicDataSource(dataSourceProperty);
static {
try {
Class.forName(DRUID_DATASOURCE);
druidExists = true;
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName(HIKARI_DATASOURCE);
hikariExists = true;
} catch (ClassNotFoundException ignored) {
}
} else if (DRUID_DATASOURCE.equals(type.getName())) {
dataSource = createDruidDataSource(dataSourceProperty);
} else if (HIKARI_DATASOURCE.equals(type.getName())) {
dataSource = createHikariDataSource(dataSourceProperty);
} else {
dataSource = createBasicDataSource(dataSourceProperty);
}
}
this.runScrip(dataSourceProperty, dataSource);
return dataSource;
}
private void runScrip(DataSourceProperty dataSourceProperty, DataSource dataSource) {
String schema = dataSourceProperty.getSchema();
String data = dataSourceProperty.getData();
if (StringUtils.hasText(schema) || StringUtils.hasText(data)) {
ScriptRunner scriptRunner = new ScriptRunner(dataSourceProperty.isContinueOnError(), dataSourceProperty.getSeparator());
if (StringUtils.hasText(schema)) {
scriptRunner.runScript(dataSource, schema);
}
if (StringUtils.hasText(data)) {
scriptRunner.runScript(dataSource, data);
}
private BasicDataSourceCreator basicDataSourceCreator;
private JndiDataSourceCreator jndiDataSourceCreator;
private HikariDataSourceCreator hikariDataSourceCreator;
private DruidDataSourceCreator druidDataSourceCreator;
private String globalPublicKey;
/**
* 创建数据源
*
* @param dataSourceProperty 数据源信息
* @return 数据源
*/
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
DataSource dataSource;
//如果是jndi数据源
String jndiName = dataSourceProperty.getJndiName();
if (jndiName != null && !jndiName.isEmpty()) {
dataSource = createJNDIDataSource(jndiName);
} else {
Class<? extends DataSource> type = dataSourceProperty.getType();
if (type == null) {
if (druidExists) {
dataSource = createDruidDataSource(dataSourceProperty);
} else if (hikariExists) {
dataSource = createHikariDataSource(dataSourceProperty);
} else {
dataSource = createBasicDataSource(dataSourceProperty);
}
} else if (DRUID_DATASOURCE.equals(type.getName())) {
dataSource = createDruidDataSource(dataSourceProperty);
} else if (HIKARI_DATASOURCE.equals(type.getName())) {
dataSource = createHikariDataSource(dataSourceProperty);
} else {
dataSource = createBasicDataSource(dataSourceProperty);
}
}
this.runScrip(dataSourceProperty, dataSource);
return dataSource;
}
}
/**
* 创建基础数据源
*
* @param dataSourceProperty 数据源参数
* @return 数据源
*/
public DataSource createBasicDataSource(DataSourceProperty dataSourceProperty) {
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
dataSourceProperty.setPublicKey(globalPublicKey);
private void runScrip(DataSourceProperty dataSourceProperty, DataSource dataSource) {
String schema = dataSourceProperty.getSchema();
String data = dataSourceProperty.getData();
if (StringUtils.hasText(schema) || StringUtils.hasText(data)) {
ScriptRunner scriptRunner = new ScriptRunner(dataSourceProperty.isContinueOnError(), dataSourceProperty.getSeparator());
if (StringUtils.hasText(schema)) {
scriptRunner.runScript(dataSource, schema);
}
if (StringUtils.hasText(data)) {
scriptRunner.runScript(dataSource, data);
}
}
}
return basicDataSourceCreator.createDataSource(dataSourceProperty);
}
/**
* 创建JNDI数据源
*
* @param jndiName jndi数据源名称
* @return 数据源
*/
public DataSource createJNDIDataSource(String jndiName) {
return jndiDataSourceCreator.createDataSource(jndiName);
}
/**
* 创建Druid数据源
*
* @param dataSourceProperty 数据源参数
* @return 数据源
*/
public DataSource createDruidDataSource(DataSourceProperty dataSourceProperty) {
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
dataSourceProperty.setPublicKey(globalPublicKey);
/**
* 创建基础数据源
*
* @param dataSourceProperty 数据源参数
* @return 数据源
*/
public DataSource createBasicDataSource(DataSourceProperty dataSourceProperty) {
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
dataSourceProperty.setPublicKey(globalPublicKey);
}
return basicDataSourceCreator.createDataSource(dataSourceProperty);
}
return druidDataSourceCreator.createDataSource(dataSourceProperty);
}
/**
* 创建Hikari数据源
*
* @param dataSourceProperty 数据源参数
* @return 数据源
* @author 离世庭院 小锅盖
*/
public DataSource createHikariDataSource(DataSourceProperty dataSourceProperty) {
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
dataSourceProperty.setPublicKey(globalPublicKey);
/**
* 创建JNDI数据源
*
* @param jndiName jndi数据源名称
* @return 数据源
*/
public DataSource createJNDIDataSource(String jndiName) {
return jndiDataSourceCreator.createDataSource(jndiName);
}
/**
* 创建Druid数据源
*
* @param dataSourceProperty 数据源参数
* @return 数据源
*/
public DataSource createDruidDataSource(DataSourceProperty dataSourceProperty) {
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
dataSourceProperty.setPublicKey(globalPublicKey);
}
return druidDataSourceCreator.createDataSource(dataSourceProperty);
}
/**
* 创建Hikari数据源
*
* @param dataSourceProperty 数据源参数
* @return 数据源
* @author 离世庭院 小锅盖
*/
public DataSource createHikariDataSource(DataSourceProperty dataSourceProperty) {
if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) {
dataSourceProperty.setPublicKey(globalPublicKey);
}
return hikariDataSourceCreator.createDataSource(dataSourceProperty);
}
return hikariDataSourceCreator.createDataSource(dataSourceProperty);
}
}

View File

@ -27,16 +27,17 @@ import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourcePrope
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidConfig;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidSlf4jConfig;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidWallConfigUtil;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.sql.DataSource;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.util.StringUtils;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* Druid数据源创建器
*
@ -46,115 +47,115 @@ import org.springframework.util.StringUtils;
@Data
public class DruidDataSourceCreator {
private DruidConfig druidConfig;
private DruidConfig druidConfig;
@Autowired(required = false)
private ApplicationContext applicationContext;
@Autowired(required = false)
private ApplicationContext applicationContext;
public DruidDataSourceCreator(DruidConfig druidConfig) {
this.druidConfig = druidConfig;
}
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername(dataSourceProperty.getUsername());
dataSource.setPassword(dataSourceProperty.getPassword());
dataSource.setUrl(dataSourceProperty.getUrl());
dataSource.setDriverClassName(dataSourceProperty.getDriverClassName());
dataSource.setName(dataSourceProperty.getPoolName());
DruidConfig config = dataSourceProperty.getDruid();
Properties properties = config.toProperties(druidConfig);
String filters = properties.getProperty("druid.filters");
List<Filter> proxyFilters = new ArrayList<>(2);
if (!StringUtils.isEmpty(filters) && filters.contains("stat")) {
StatFilter statFilter = new StatFilter();
statFilter.configFromProperties(properties);
proxyFilters.add(statFilter);
}
if (!StringUtils.isEmpty(filters) && filters.contains("wall")) {
WallConfig wallConfig = DruidWallConfigUtil.toWallConfig(dataSourceProperty.getDruid().getWall(), druidConfig.getWall());
WallFilter wallFilter = new WallFilter();
wallFilter.setConfig(wallConfig);
proxyFilters.add(wallFilter);
}
if (!StringUtils.isEmpty(filters) && filters.contains("slf4j")) {
Slf4jLogFilter slf4jLogFilter = new Slf4jLogFilter();
// 由于properties上面被用了LogFilter不能使用configFromProperties方法这里只能一个个set了
DruidSlf4jConfig slf4jConfig = druidConfig.getSlf4j();
slf4jLogFilter.setStatementLogEnabled(slf4jConfig.getEnable());
slf4jLogFilter.setStatementExecutableSqlLogEnable(slf4jConfig.getStatementExecutableSqlLogEnable());
proxyFilters.add(slf4jLogFilter);
public DruidDataSourceCreator(DruidConfig druidConfig) {
this.druidConfig = druidConfig;
}
if (this.applicationContext != null) {
for (String filterId : druidConfig.getProxyFilters()) {
proxyFilters.add(this.applicationContext.getBean(filterId, Filter.class));
}
}
dataSource.setProxyFilters(proxyFilters);
dataSource.configFromPropety(properties);
//连接参数单独设置
dataSource.setConnectProperties(config.getConnectionProperties());
//设置druid内置properties不支持的的参数
Boolean testOnReturn = config.getTestOnReturn() == null ? druidConfig.getTestOnReturn() : config.getTestOnReturn();
if (testOnReturn != null && testOnReturn.equals(true)) {
dataSource.setTestOnReturn(true);
}
Integer validationQueryTimeout =
config.getValidationQueryTimeout() == null ? druidConfig.getValidationQueryTimeout() : config.getValidationQueryTimeout();
if (validationQueryTimeout != null && !validationQueryTimeout.equals(-1)) {
dataSource.setValidationQueryTimeout(validationQueryTimeout);
}
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername(dataSourceProperty.getUsername());
dataSource.setPassword(dataSourceProperty.getPassword());
dataSource.setUrl(dataSourceProperty.getUrl());
dataSource.setDriverClassName(dataSourceProperty.getDriverClassName());
dataSource.setName(dataSourceProperty.getPoolName());
DruidConfig config = dataSourceProperty.getDruid();
Properties properties = config.toProperties(druidConfig);
String filters = properties.getProperty("druid.filters");
List<Filter> proxyFilters = new ArrayList<>(2);
if (!StringUtils.isEmpty(filters) && filters.contains("stat")) {
StatFilter statFilter = new StatFilter();
statFilter.configFromProperties(properties);
proxyFilters.add(statFilter);
}
if (!StringUtils.isEmpty(filters) && filters.contains("wall")) {
WallConfig wallConfig = DruidWallConfigUtil.toWallConfig(dataSourceProperty.getDruid().getWall(), druidConfig.getWall());
WallFilter wallFilter = new WallFilter();
wallFilter.setConfig(wallConfig);
proxyFilters.add(wallFilter);
}
if (!StringUtils.isEmpty(filters) && filters.contains("slf4j")) {
Slf4jLogFilter slf4jLogFilter = new Slf4jLogFilter();
// 由于properties上面被用了LogFilter不能使用configFromProperties方法这里只能一个个set了
DruidSlf4jConfig slf4jConfig = druidConfig.getSlf4j();
slf4jLogFilter.setStatementLogEnabled(slf4jConfig.getEnable());
slf4jLogFilter.setStatementExecutableSqlLogEnable(slf4jConfig.getStatementExecutableSqlLogEnable());
proxyFilters.add(slf4jLogFilter);
}
Boolean sharePreparedStatements =
config.getSharePreparedStatements() == null ? druidConfig.getSharePreparedStatements() : config.getSharePreparedStatements();
if (sharePreparedStatements != null && sharePreparedStatements.equals(true)) {
dataSource.setSharePreparedStatements(true);
}
Integer connectionErrorRetryAttempts =
config.getConnectionErrorRetryAttempts() == null ? druidConfig.getConnectionErrorRetryAttempts()
: config.getConnectionErrorRetryAttempts();
if (connectionErrorRetryAttempts != null && !connectionErrorRetryAttempts.equals(1)) {
dataSource.setConnectionErrorRetryAttempts(connectionErrorRetryAttempts);
}
Boolean breakAfterAcquireFailure =
config.getBreakAfterAcquireFailure() == null ? druidConfig.getBreakAfterAcquireFailure() : config.getBreakAfterAcquireFailure();
if (breakAfterAcquireFailure != null && breakAfterAcquireFailure.equals(true)) {
dataSource.setBreakAfterAcquireFailure(true);
}
if (this.applicationContext != null) {
for (String filterId : druidConfig.getProxyFilters()) {
proxyFilters.add(this.applicationContext.getBean(filterId, Filter.class));
}
}
dataSource.setProxyFilters(proxyFilters);
dataSource.configFromPropety(properties);
//连接参数单独设置
dataSource.setConnectProperties(config.getConnectionProperties());
//设置druid内置properties不支持的的参数
Boolean testOnReturn = config.getTestOnReturn() == null ? druidConfig.getTestOnReturn() : config.getTestOnReturn();
if (testOnReturn != null && testOnReturn.equals(true)) {
dataSource.setTestOnReturn(true);
}
Integer validationQueryTimeout =
config.getValidationQueryTimeout() == null ? druidConfig.getValidationQueryTimeout() : config.getValidationQueryTimeout();
if (validationQueryTimeout != null && !validationQueryTimeout.equals(-1)) {
dataSource.setValidationQueryTimeout(validationQueryTimeout);
}
Integer timeout = config.getRemoveAbandonedTimeoutMillis() == null ? druidConfig.getRemoveAbandonedTimeoutMillis()
: config.getRemoveAbandonedTimeoutMillis();
if (timeout != null) {
dataSource.setRemoveAbandonedTimeout(timeout);
}
Boolean sharePreparedStatements =
config.getSharePreparedStatements() == null ? druidConfig.getSharePreparedStatements() : config.getSharePreparedStatements();
if (sharePreparedStatements != null && sharePreparedStatements.equals(true)) {
dataSource.setSharePreparedStatements(true);
}
Integer connectionErrorRetryAttempts =
config.getConnectionErrorRetryAttempts() == null ? druidConfig.getConnectionErrorRetryAttempts()
: config.getConnectionErrorRetryAttempts();
if (connectionErrorRetryAttempts != null && !connectionErrorRetryAttempts.equals(1)) {
dataSource.setConnectionErrorRetryAttempts(connectionErrorRetryAttempts);
}
Boolean breakAfterAcquireFailure =
config.getBreakAfterAcquireFailure() == null ? druidConfig.getBreakAfterAcquireFailure() : config.getBreakAfterAcquireFailure();
if (breakAfterAcquireFailure != null && breakAfterAcquireFailure.equals(true)) {
dataSource.setBreakAfterAcquireFailure(true);
}
Boolean abandoned = config.getRemoveAbandoned() == null ? druidConfig.getRemoveAbandoned() : config.getRemoveAbandoned();
if (abandoned != null) {
dataSource.setRemoveAbandoned(abandoned);
}
Integer timeout = config.getRemoveAbandonedTimeoutMillis() == null ? druidConfig.getRemoveAbandonedTimeoutMillis()
: config.getRemoveAbandonedTimeoutMillis();
if (timeout != null) {
dataSource.setRemoveAbandonedTimeout(timeout);
}
Boolean logAbandoned = config.getLogAbandoned() == null ? druidConfig.getLogAbandoned() : config.getLogAbandoned();
if (logAbandoned != null) {
dataSource.setLogAbandoned(logAbandoned);
}
Boolean abandoned = config.getRemoveAbandoned() == null ? druidConfig.getRemoveAbandoned() : config.getRemoveAbandoned();
if (abandoned != null) {
dataSource.setRemoveAbandoned(abandoned);
}
Integer queryTimeOut = config.getQueryTimeout() == null ? druidConfig.getQueryTimeout() : config.getQueryTimeout();
if (queryTimeOut != null) {
dataSource.setQueryTimeout(queryTimeOut);
}
Boolean logAbandoned = config.getLogAbandoned() == null ? druidConfig.getLogAbandoned() : config.getLogAbandoned();
if (logAbandoned != null) {
dataSource.setLogAbandoned(logAbandoned);
}
Integer transactionQueryTimeout =
config.getTransactionQueryTimeout() == null ? druidConfig.getTransactionQueryTimeout() : config.getTransactionQueryTimeout();
if (transactionQueryTimeout != null) {
dataSource.setTransactionQueryTimeout(transactionQueryTimeout);
}
Integer queryTimeOut = config.getQueryTimeout() == null ? druidConfig.getQueryTimeout() : config.getQueryTimeout();
if (queryTimeOut != null) {
dataSource.setQueryTimeout(queryTimeOut);
}
try {
dataSource.init();
} catch (SQLException e) {
throw new ErrorCreateDataSourceException("druid create error", e);
Integer transactionQueryTimeout =
config.getTransactionQueryTimeout() == null ? druidConfig.getTransactionQueryTimeout() : config.getTransactionQueryTimeout();
if (transactionQueryTimeout != null) {
dataSource.setTransactionQueryTimeout(transactionQueryTimeout);
}
try {
dataSource.init();
} catch (SQLException e) {
throw new ErrorCreateDataSourceException("druid create error", e);
}
return dataSource;
}
return dataSource;
}
}

View File

@ -20,10 +20,11 @@ import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourcePrope
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.hikari.HikariCpConfig;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import lombok.AllArgsConstructor;
import lombok.Data;
import javax.sql.DataSource;
/**
* Hikari数据源创建器
*
@ -34,15 +35,15 @@ import lombok.Data;
@AllArgsConstructor
public class HikariDataSourceCreator {
private HikariCpConfig hikariCpConfig;
private HikariCpConfig hikariCpConfig;
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
HikariConfig config = dataSourceProperty.getHikari().toHikariConfig(hikariCpConfig);
config.setUsername(dataSourceProperty.getUsername());
config.setPassword(dataSourceProperty.getPassword());
config.setJdbcUrl(dataSourceProperty.getUrl());
config.setDriverClassName(dataSourceProperty.getDriverClassName());
config.setPoolName(dataSourceProperty.getPoolName());
return new HikariDataSource(config);
}
public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
HikariConfig config = dataSourceProperty.getHikari().toHikariConfig(hikariCpConfig);
config.setUsername(dataSourceProperty.getUsername());
config.setPassword(dataSourceProperty.getPassword());
config.setJdbcUrl(dataSourceProperty.getUrl());
config.setDriverClassName(dataSourceProperty.getDriverClassName());
config.setPoolName(dataSourceProperty.getPoolName());
return new HikariDataSource(config);
}
}

View File

@ -16,9 +16,10 @@
*/
package com.baomidou.dynamic.datasource.creator;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
import javax.sql.DataSource;
/**
* JNDI数据源创建器
*
@ -27,16 +28,16 @@ import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
*/
public class JndiDataSourceCreator {
private static final JndiDataSourceLookup LOOKUP = new JndiDataSourceLookup();
private static final JndiDataSourceLookup LOOKUP = new JndiDataSourceLookup();
/**
* 创建基础数据源
*
* @param name 数据源参数
* @return 数据源
*/
public DataSource createDataSource(String name) {
return LOOKUP.getDataSource(name);
}
/**
* 创建基础数据源
*
* @param name 数据源参数
* @return 数据源
*/
public DataSource createDataSource(String name) {
return LOOKUP.getDataSource(name);
}
}

View File

@ -24,11 +24,11 @@ package com.baomidou.dynamic.datasource.exception;
*/
public class ErrorCreateDataSourceException extends RuntimeException {
public ErrorCreateDataSourceException(String message) {
super(message);
}
public ErrorCreateDataSourceException(String message) {
super(message);
}
public ErrorCreateDataSourceException(String message, Throwable cause) {
super(message, cause);
}
public ErrorCreateDataSourceException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -27,7 +27,7 @@ import lombok.Data;
@Data
public class ExpressionMatcher implements Matcher {
private String expression;
private String expression;
private String ds;
private String ds;
}

View File

@ -27,8 +27,8 @@ import lombok.Data;
@Data
public class RegexMatcher implements Matcher {
private String pattern;
private String pattern;
private String ds;
private String ds;
}

View File

@ -20,21 +20,18 @@ import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSour
import com.baomidou.dynamic.datasource.support.DbHealthIndicator;
import com.baomidou.dynamic.datasource.support.DdConstants;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import java.util.Properties;
/**
* Master-slave Separation Plugin with mybatis
*
@ -42,61 +39,61 @@ import org.springframework.util.StringUtils;
* @since 2.5.1
*/
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
@Slf4j
public class MasterSlaveAutoRoutingPlugin implements Interceptor {
@Autowired
private DynamicDataSourceProperties properties;
@Autowired
private DynamicDataSourceProperties properties;
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
boolean empty = true;
try {
empty = StringUtils.isEmpty(DynamicDataSourceContextHolder.peek());
if (empty) {
DynamicDataSourceContextHolder.push(getDataSource(ms));
}
return invocation.proceed();
} finally {
if (empty) {
DynamicDataSourceContextHolder.clear();
}
}
}
/**
* 获取动态数据源名称重写注入 DbHealthIndicator 支持数据源健康状况判断选择
*
* @param mappedStatement mybatis MappedStatement
* @return 获取真实的数据源名称
*/
public String getDataSource(MappedStatement mappedStatement) {
String slave = DdConstants.SLAVE;
if (properties.isHealth()) {
/*
* 根据从库健康状况判断是否切到主库
*/
boolean health = DbHealthIndicator.getDbHealth(DdConstants.SLAVE);
if (!health) {
health = DbHealthIndicator.getDbHealth(DdConstants.MASTER);
if (health) {
slave = DdConstants.MASTER;
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
boolean empty = true;
try {
empty = StringUtils.isEmpty(DynamicDataSourceContextHolder.peek());
if (empty) {
DynamicDataSourceContextHolder.push(getDataSource(ms));
}
return invocation.proceed();
} finally {
if (empty) {
DynamicDataSourceContextHolder.clear();
}
}
}
}
return SqlCommandType.SELECT == mappedStatement.getSqlCommandType() ? slave : DdConstants.MASTER;
}
@Override
public Object plugin(Object target) {
return target instanceof Executor ? Plugin.wrap(target, this) : target;
}
/**
* 获取动态数据源名称重写注入 DbHealthIndicator 支持数据源健康状况判断选择
*
* @param mappedStatement mybatis MappedStatement
* @return 获取真实的数据源名称
*/
public String getDataSource(MappedStatement mappedStatement) {
String slave = DdConstants.SLAVE;
if (properties.isHealth()) {
/*
* 根据从库健康状况判断是否切到主库
*/
boolean health = DbHealthIndicator.getDbHealth(DdConstants.SLAVE);
if (!health) {
health = DbHealthIndicator.getDbHealth(DdConstants.MASTER);
if (health) {
slave = DdConstants.MASTER;
}
}
}
return SqlCommandType.SELECT == mappedStatement.getSqlCommandType() ? slave : DdConstants.MASTER;
}
@Override
public void setProperties(Properties properties) {
}
@Override
public Object plugin(Object target) {
return target instanceof Executor ? Plugin.wrap(target, this) : target;
}
@Override
public void setProperties(Properties properties) {
}
}

View File

@ -16,30 +16,31 @@
*/
package com.baomidou.dynamic.datasource.processor;
import javax.servlet.http.HttpServletRequest;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* @author TaoYu
* @since 2.5.0
*/
public class DsHeaderProcessor extends DsProcessor {
/**
* header prefix
*/
private static final String HEADER_PREFIX = "#header";
/**
* header prefix
*/
private static final String HEADER_PREFIX = "#header";
@Override
public boolean matches(String key) {
return key.startsWith(HEADER_PREFIX);
}
@Override
public boolean matches(String key) {
return key.startsWith(HEADER_PREFIX);
}
@Override
public String doDetermineDatasource(MethodInvocation invocation, String key) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return request.getHeader(key.substring(8));
}
@Override
public String doDetermineDatasource(MethodInvocation invocation, String key) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return request.getHeader(key.substring(8));
}
}

View File

@ -24,51 +24,51 @@ import org.aopalliance.intercept.MethodInvocation;
*/
public abstract class DsProcessor {
private DsProcessor nextProcessor;
private DsProcessor nextProcessor;
public void setNextProcessor(DsProcessor dsProcessor) {
this.nextProcessor = dsProcessor;
}
/**
* 抽象匹配条件 匹配才会走当前执行器否则走下一级执行器
*
* @param key DS注解里的内容
* @return 是否匹配
*/
public abstract boolean matches(String key);
/**
* 决定数据源
* <pre>
* 调用底层doDetermineDatasource
* 如果返回的是null则继续执行下一个否则直接返回
* </pre>
*
* @param invocation 方法执行信息
* @param key DS注解里的内容
* @return 数据源名称
*/
public String determineDatasource(MethodInvocation invocation, String key) {
if (matches(key)) {
String datasource = doDetermineDatasource(invocation, key);
if (datasource == null && nextProcessor != null) {
return nextProcessor.determineDatasource(invocation, key);
}
return datasource;
public void setNextProcessor(DsProcessor dsProcessor) {
this.nextProcessor = dsProcessor;
}
if (nextProcessor != null) {
return nextProcessor.determineDatasource(invocation, key);
}
return null;
}
/**
* 抽象最终决定数据源
*
* @param invocation 方法执行信息
* @param key DS注解里的内容
* @return 数据源名称
*/
public abstract String doDetermineDatasource(MethodInvocation invocation, String key);
/**
* 抽象匹配条件 匹配才会走当前执行器否则走下一级执行器
*
* @param key DS注解里的内容
* @return 是否匹配
*/
public abstract boolean matches(String key);
/**
* 决定数据源
* <pre>
* 调用底层doDetermineDatasource
* 如果返回的是null则继续执行下一个否则直接返回
* </pre>
*
* @param invocation 方法执行信息
* @param key DS注解里的内容
* @return 数据源名称
*/
public String determineDatasource(MethodInvocation invocation, String key) {
if (matches(key)) {
String datasource = doDetermineDatasource(invocation, key);
if (datasource == null && nextProcessor != null) {
return nextProcessor.determineDatasource(invocation, key);
}
return datasource;
}
if (nextProcessor != null) {
return nextProcessor.determineDatasource(invocation, key);
}
return null;
}
/**
* 抽象最终决定数据源
*
* @param invocation 方法执行信息
* @param key DS注解里的内容
* @return 数据源名称
*/
public abstract String doDetermineDatasource(MethodInvocation invocation, String key);
}

View File

@ -16,30 +16,31 @@
*/
package com.baomidou.dynamic.datasource.processor;
import javax.servlet.http.HttpServletRequest;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* @author TaoYu
* @since 2.5.0
*/
public class DsSessionProcessor extends DsProcessor {
/**
* session开头
*/
private static final String SESSION_PREFIX = "#session";
/**
* session开头
*/
private static final String SESSION_PREFIX = "#session";
@Override
public boolean matches(String key) {
return key.startsWith(SESSION_PREFIX);
}
@Override
public boolean matches(String key) {
return key.startsWith(SESSION_PREFIX);
}
@Override
public String doDetermineDatasource(MethodInvocation invocation, String key) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return request.getSession().getAttribute(key.substring(9)).toString();
}
@Override
public String doDetermineDatasource(MethodInvocation invocation, String key) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return request.getSession().getAttribute(key.substring(9)).toString();
}
}

View File

@ -16,7 +16,6 @@
*/
package com.baomidou.dynamic.datasource.processor;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
@ -26,44 +25,45 @@ import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import java.lang.reflect.Method;
/**
* @author TaoYu
* @since 2.5.0
*/
public class DsSpelExpressionProcessor extends DsProcessor {
/**
* 参数发现器
*/
private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
/**
* Express语法解析器
*/
private static final ExpressionParser PARSER = new SpelExpressionParser();
/**
* 参数发现器
*/
private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
/**
* Express语法解析器
*/
private static final ExpressionParser PARSER = new SpelExpressionParser();
/**
* 解析上下文的模板
* 对于默认不设置的情况下,从参数中取值的方式 #param1
* 设置指定模板 ParserContext.TEMPLATE_EXPRESSION 后的取值方式: #{#param1}
* issues: https://github.com/baomidou/dynamic-datasource-spring-boot-starter/issues/199
*/
private ParserContext parserContext = null;
@Override
public boolean matches(String key) {
return true;
}
@Override
public boolean matches(String key) {
return true;
}
/**
* 解析上下文的模板
* 对于默认不设置的情况下,从参数中取值的方式 #param1
* 设置指定模板 ParserContext.TEMPLATE_EXPRESSION 后的取值方式: #{#param1}
* issues: https://github.com/baomidou/dynamic-datasource-spring-boot-starter/issues/199
*/
private ParserContext parserContext = null;
@Override
public String doDetermineDatasource(MethodInvocation invocation, String key) {
Method method = invocation.getMethod();
Object[] arguments = invocation.getArguments();
EvaluationContext context = new MethodBasedEvaluationContext(null, method, arguments, NAME_DISCOVERER);
final Object value = PARSER.parseExpression(key, parserContext).getValue(context);
return value == null ? null : value.toString();
}
@Override
public String doDetermineDatasource(MethodInvocation invocation, String key) {
Method method = invocation.getMethod();
Object[] arguments = invocation.getArguments();
EvaluationContext context = new MethodBasedEvaluationContext(null, method, arguments, NAME_DISCOVERER);
final Object value = PARSER.parseExpression(key,parserContext).getValue(context);
return value == null ? null : value.toString();
}
public void setParserContext(ParserContext parserContext) {
this.parserContext = parserContext;
}
public void setParserContext(ParserContext parserContext) {
this.parserContext = parserContext;
}
}

View File

@ -18,31 +18,32 @@ package com.baomidou.dynamic.datasource.provider;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public abstract class AbstractDataSourceProvider implements DynamicDataSourceProvider {
@Autowired
private DataSourceCreator dataSourceCreator;
@Autowired
private DataSourceCreator dataSourceCreator;
protected Map<String, DataSource> createDataSourceMap(
Map<String, DataSourceProperty> dataSourcePropertiesMap) {
Map<String, DataSource> dataSourceMap = new HashMap<>(dataSourcePropertiesMap.size() * 2);
for (Map.Entry<String, DataSourceProperty> item : dataSourcePropertiesMap.entrySet()) {
DataSourceProperty dataSourceProperty = item.getValue();
String pollName = dataSourceProperty.getPoolName();
if (pollName == null || "".equals(pollName)) {
pollName = item.getKey();
}
dataSourceProperty.setPoolName(pollName);
dataSourceMap.put(pollName, dataSourceCreator.createDataSource(dataSourceProperty));
protected Map<String, DataSource> createDataSourceMap(
Map<String, DataSourceProperty> dataSourcePropertiesMap) {
Map<String, DataSource> dataSourceMap = new HashMap<>(dataSourcePropertiesMap.size() * 2);
for (Map.Entry<String, DataSourceProperty> item : dataSourcePropertiesMap.entrySet()) {
DataSourceProperty dataSourceProperty = item.getValue();
String pollName = dataSourceProperty.getPoolName();
if (pollName == null || "".equals(pollName)) {
pollName = item.getKey();
}
dataSourceProperty.setPoolName(pollName);
dataSourceMap.put(pollName, dataSourceCreator.createDataSource(dataSourceProperty));
}
return dataSourceMap;
}
return dataSourceMap;
}
}

View File

@ -17,14 +17,15 @@
package com.baomidou.dynamic.datasource.provider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.support.JdbcUtils;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.support.JdbcUtils;
/**
* JDBC数据源提供者(抽象)
@ -35,58 +36,58 @@ import org.springframework.jdbc.support.JdbcUtils;
@Slf4j
public abstract class AbstractJdbcDataSourceProvider extends AbstractDataSourceProvider implements DynamicDataSourceProvider {
/**
* JDBC driver
*/
private String driverClassName;
/**
* JDBC url 地址
*/
private String url;
/**
* JDBC 用户名
*/
private String username;
/**
* JDBC 密码
*/
private String password;
/**
* JDBC driver
*/
private String driverClassName;
/**
* JDBC url 地址
*/
private String url;
/**
* JDBC 用户名
*/
private String username;
/**
* JDBC 密码
*/
private String password;
public AbstractJdbcDataSourceProvider(String driverClassName, String url, String username, String password) {
this.driverClassName = driverClassName;
this.url = url;
this.username = username;
this.password = password;
}
@Override
public Map<String, DataSource> loadDataSources() {
Connection conn = null;
Statement stmt = null;
try {
Class.forName(driverClassName);
log.info("成功加载数据库驱动程序");
conn = DriverManager.getConnection(url, username, password);
log.info("成功获取数据库连接");
stmt = conn.createStatement();
Map<String, DataSourceProperty> dataSourcePropertiesMap = executeStmt(stmt);
return createDataSourceMap(dataSourcePropertiesMap);
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtils.closeConnection(conn);
JdbcUtils.closeStatement(stmt);
public AbstractJdbcDataSourceProvider(String driverClassName, String url, String username, String password) {
this.driverClassName = driverClassName;
this.url = url;
this.username = username;
this.password = password;
}
return null;
}
/**
* 执行语句获得数据源参数
*
* @param statement 语句
* @return 数据源参数
* @throws SQLException sql异常
*/
protected abstract Map<String, DataSourceProperty> executeStmt(Statement statement)
throws SQLException;
@Override
public Map<String, DataSource> loadDataSources() {
Connection conn = null;
Statement stmt = null;
try {
Class.forName(driverClassName);
log.info("成功加载数据库驱动程序");
conn = DriverManager.getConnection(url, username, password);
log.info("成功获取数据库连接");
stmt = conn.createStatement();
Map<String, DataSourceProperty> dataSourcePropertiesMap = executeStmt(stmt);
return createDataSourceMap(dataSourcePropertiesMap);
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtils.closeConnection(conn);
JdbcUtils.closeStatement(stmt);
}
return null;
}
/**
* 执行语句获得数据源参数
*
* @param statement 语句
* @return 数据源参数
* @throws SQLException sql异常
*/
protected abstract Map<String, DataSourceProperty> executeStmt(Statement statement)
throws SQLException;
}

View File

@ -16,8 +16,8 @@
*/
package com.baomidou.dynamic.datasource.provider;
import java.util.Map;
import javax.sql.DataSource;
import java.util.Map;
/**
* 多数据源加载接口默认的实现为从yml信息中加载所有数据源 你可以自己实现从其他地方加载所有数据源
@ -29,10 +29,10 @@ import javax.sql.DataSource;
*/
public interface DynamicDataSourceProvider {
/**
* 加载所有数据源
*
* @return 所有数据源key为数据源名称
*/
Map<String, DataSource> loadDataSources();
/**
* 加载所有数据源
*
* @return 所有数据源key为数据源名称
*/
Map<String, DataSource> loadDataSources();
}

View File

@ -17,11 +17,12 @@
package com.baomidou.dynamic.datasource.provider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import java.util.Map;
import javax.sql.DataSource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import javax.sql.DataSource;
import java.util.Map;
/**
* YML数据源提供者
*
@ -32,13 +33,13 @@ import lombok.extern.slf4j.Slf4j;
@AllArgsConstructor
public class YmlDynamicDataSourceProvider extends AbstractDataSourceProvider implements DynamicDataSourceProvider {
/**
* 所有数据源
*/
private Map<String, DataSourceProperty> dataSourcePropertiesMap;
/**
* 所有数据源
*/
private Map<String, DataSourceProperty> dataSourcePropertiesMap;
@Override
public Map<String, DataSource> loadDataSources() {
return createDataSourceMap(dataSourcePropertiesMap);
}
@Override
public Map<String, DataSource> loadDataSources() {
return createDataSourceMap(dataSourcePropertiesMap);
}
}

View File

@ -19,15 +19,16 @@ package com.baomidou.dynamic.datasource.spring.boot.autoconfigure;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidConfig;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.hikari.HikariCpConfig;
import com.baomidou.dynamic.datasource.toolkit.CryptoUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.sql.DataSource;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.util.StringUtils;
import javax.sql.DataSource;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author TaoYu
* @since 1.2.0
@ -37,97 +38,97 @@ import org.springframework.util.StringUtils;
@Accessors(chain = true)
public class DataSourceProperty {
/**
* 加密正则
*/
private static final Pattern ENC_PATTERN = Pattern.compile("^ENC\\((.*)\\)$");
/**
* 加密正则
*/
private static final Pattern ENC_PATTERN = Pattern.compile("^ENC\\((.*)\\)$");
/**
* 连接池名称(只是一个名称标识)</br> 默认是配置文件上的名称
*/
private String poolName;
/**
* 连接池类型如果不设置自动查找 Druid > HikariCp
*/
private Class<? extends DataSource> type;
/**
* JDBC driver
*/
private String driverClassName;
/**
* JDBC url 地址
*/
private String url;
/**
* JDBC 用户名
*/
private String username;
/**
* JDBC 密码
*/
private String password;
/**
* jndi数据源名称(设置即表示启用)
*/
private String jndiName;
/**
* 自动运行的建表脚本
*/
private String schema;
/**
* 自动运行的数据脚本
*/
private String data;
/**
* 错误是否继续 默认 true
*/
private boolean continueOnError = true;
/**
* 分隔符 默认 ;
*/
private String separator = ";";
/**
* Druid参数配置
*/
@NestedConfigurationProperty
private DruidConfig druid = new DruidConfig();
/**
* HikariCp参数配置
*/
@NestedConfigurationProperty
private HikariCpConfig hikari = new HikariCpConfig();
/**
* 连接池名称(只是一个名称标识)</br> 默认是配置文件上的名称
*/
private String poolName;
/**
* 连接池类型如果不设置自动查找 Druid > HikariCp
*/
private Class<? extends DataSource> type;
/**
* JDBC driver
*/
private String driverClassName;
/**
* JDBC url 地址
*/
private String url;
/**
* JDBC 用户名
*/
private String username;
/**
* JDBC 密码
*/
private String password;
/**
* jndi数据源名称(设置即表示启用)
*/
private String jndiName;
/**
* 自动运行的建表脚本
*/
private String schema;
/**
* 自动运行的数据脚本
*/
private String data;
/**
* 错误是否继续 默认 true
*/
private boolean continueOnError = true;
/**
* 分隔符 默认 ;
*/
private String separator = ";";
/**
* Druid参数配置
*/
@NestedConfigurationProperty
private DruidConfig druid = new DruidConfig();
/**
* HikariCp参数配置
*/
@NestedConfigurationProperty
private HikariCpConfig hikari = new HikariCpConfig();
/**
* 解密公匙(如果未设置默认使用全局的)
*/
private String publicKey;
/**
* 解密公匙(如果未设置默认使用全局的)
*/
private String publicKey;
public String getUrl() {
return decrypt(url);
}
public String getUsername() {
return decrypt(username);
}
public String getPassword() {
return decrypt(password);
}
/**
* 字符串解密
*/
private String decrypt(String cipherText) {
if (StringUtils.hasText(cipherText)) {
Matcher matcher = ENC_PATTERN.matcher(cipherText);
if (matcher.find()) {
try {
return CryptoUtils.decrypt(publicKey, matcher.group(1));
} catch (Exception e) {
log.error("DynamicDataSourceProperties.decrypt error ", e);
}
}
public String getUrl() {
return decrypt(url);
}
public String getUsername() {
return decrypt(username);
}
public String getPassword() {
return decrypt(password);
}
/**
* 字符串解密
*/
private String decrypt(String cipherText) {
if (StringUtils.hasText(cipherText)) {
Matcher matcher = ENC_PATTERN.matcher(cipherText);
if (matcher.find()) {
try {
return CryptoUtils.decrypt(publicKey, matcher.group(1));
} catch (Exception e) {
log.error("DynamicDataSourceProperties.decrypt error ", e);
}
}
}
return cipherText;
}
return cipherText;
}
}

View File

@ -29,8 +29,6 @@ import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.provider.YmlDynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidDynamicDataSourceConfiguration;
import com.baomidou.dynamic.datasource.strategy.DynamicDataSourceStrategy;
import java.util.Map;
import javax.sql.DataSource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
@ -43,7 +41,9 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.expression.ParserContext;
import javax.sql.DataSource;
import java.util.Map;
/**
* 动态数据源核心自动配置类
@ -63,55 +63,55 @@ import org.springframework.expression.ParserContext;
@ConditionalOnProperty(prefix = DynamicDataSourceProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
public class DynamicDataSourceAutoConfiguration {
private final DynamicDataSourceProperties properties;
private final DynamicDataSourceProperties properties;
@Bean
@ConditionalOnMissingBean
public DynamicDataSourceProvider dynamicDataSourceProvider() {
Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
return new YmlDynamicDataSourceProvider(datasourceMap);
}
@Bean
@ConditionalOnMissingBean
public DynamicDataSourceProvider dynamicDataSourceProvider() {
Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
return new YmlDynamicDataSourceProvider(datasourceMap);
}
@Bean
@ConditionalOnMissingBean
public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
dataSource.setPrimary(properties.getPrimary());
dataSource.setStrict(properties.getStrict());
dataSource.setStrategy(properties.getStrategy());
dataSource.setProvider(dynamicDataSourceProvider);
dataSource.setP6spy(properties.getP6spy());
dataSource.setSeata(properties.getSeata());
return dataSource;
}
@Bean
@ConditionalOnMissingBean
public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
dataSource.setPrimary(properties.getPrimary());
dataSource.setStrict(properties.getStrict());
dataSource.setStrategy(properties.getStrategy());
dataSource.setProvider(dynamicDataSourceProvider);
dataSource.setP6spy(properties.getP6spy());
dataSource.setSeata(properties.getSeata());
return dataSource;
}
@Bean
@ConditionalOnMissingBean
public DynamicDataSourceAnnotationAdvisor dynamicDatasourceAnnotationAdvisor(DsProcessor dsProcessor) {
DynamicDataSourceAnnotationInterceptor interceptor = new DynamicDataSourceAnnotationInterceptor();
interceptor.setDsProcessor(dsProcessor);
DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(interceptor);
advisor.setOrder(properties.getOrder());
return advisor;
}
@Bean
@ConditionalOnMissingBean
public DynamicDataSourceAnnotationAdvisor dynamicDatasourceAnnotationAdvisor(DsProcessor dsProcessor) {
DynamicDataSourceAnnotationInterceptor interceptor = new DynamicDataSourceAnnotationInterceptor();
interceptor.setDsProcessor(dsProcessor);
DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(interceptor);
advisor.setOrder(properties.getOrder());
return advisor;
}
@Bean
@ConditionalOnMissingBean
public DsProcessor dsProcessor() {
DsHeaderProcessor headerProcessor = new DsHeaderProcessor();
DsSessionProcessor sessionProcessor = new DsSessionProcessor();
DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor();
headerProcessor.setNextProcessor(sessionProcessor);
sessionProcessor.setNextProcessor(spelExpressionProcessor);
return headerProcessor;
}
@Bean
@ConditionalOnMissingBean
public DsProcessor dsProcessor() {
DsHeaderProcessor headerProcessor = new DsHeaderProcessor();
DsSessionProcessor sessionProcessor = new DsSessionProcessor();
DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor();
headerProcessor.setNextProcessor(sessionProcessor);
sessionProcessor.setNextProcessor(spelExpressionProcessor);
return headerProcessor;
}
@Bean
@ConditionalOnBean(DynamicDataSourceConfigure.class)
public DynamicDataSourceAdvisor dynamicAdvisor(DynamicDataSourceConfigure dynamicDataSourceConfigure, DsProcessor dsProcessor) {
DynamicDataSourceAdvisor advisor = new DynamicDataSourceAdvisor(dynamicDataSourceConfigure.getMatchers());
advisor.setDsProcessor(dsProcessor);
advisor.setOrder(Ordered.HIGHEST_PRECEDENCE);
return advisor;
}
@Bean
@ConditionalOnBean(DynamicDataSourceConfigure.class)
public DynamicDataSourceAdvisor dynamicAdvisor(DynamicDataSourceConfigure dynamicDataSourceConfigure, DsProcessor dsProcessor) {
DynamicDataSourceAdvisor advisor = new DynamicDataSourceAdvisor(dynamicDataSourceConfigure.getMatchers());
advisor.setDsProcessor(dsProcessor);
advisor.setOrder(Ordered.HIGHEST_PRECEDENCE);
return advisor;
}
}

View File

@ -16,11 +16,7 @@
*/
package com.baomidou.dynamic.datasource.spring.boot.autoconfigure;
import com.baomidou.dynamic.datasource.creator.BasicDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.creator.DruidDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.HikariDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.JndiDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -34,41 +30,41 @@ import org.springframework.context.annotation.Configuration;
@EnableConfigurationProperties(DynamicDataSourceProperties.class)
public class DynamicDataSourceCreatorAutoConfiguration {
private final DynamicDataSourceProperties properties;
private final DynamicDataSourceProperties properties;
@Bean
@ConditionalOnMissingBean
public DataSourceCreator dataSourceCreator() {
DataSourceCreator dataSourceCreator = new DataSourceCreator();
dataSourceCreator.setBasicDataSourceCreator(basicDataSourceCreator());
dataSourceCreator.setJndiDataSourceCreator(jndiDataSourceCreator());
dataSourceCreator.setDruidDataSourceCreator(druidDataSourceCreator());
dataSourceCreator.setHikariDataSourceCreator(hikariDataSourceCreator());
dataSourceCreator.setGlobalPublicKey(properties.getPublicKey());
return dataSourceCreator;
}
@Bean
@ConditionalOnMissingBean
public DataSourceCreator dataSourceCreator() {
DataSourceCreator dataSourceCreator = new DataSourceCreator();
dataSourceCreator.setBasicDataSourceCreator(basicDataSourceCreator());
dataSourceCreator.setJndiDataSourceCreator(jndiDataSourceCreator());
dataSourceCreator.setDruidDataSourceCreator(druidDataSourceCreator());
dataSourceCreator.setHikariDataSourceCreator(hikariDataSourceCreator());
dataSourceCreator.setGlobalPublicKey(properties.getPublicKey());
return dataSourceCreator;
}
@Bean
@ConditionalOnMissingBean
public BasicDataSourceCreator basicDataSourceCreator() {
return new BasicDataSourceCreator();
}
@Bean
@ConditionalOnMissingBean
public BasicDataSourceCreator basicDataSourceCreator() {
return new BasicDataSourceCreator();
}
@Bean
@ConditionalOnMissingBean
public JndiDataSourceCreator jndiDataSourceCreator() {
return new JndiDataSourceCreator();
}
@Bean
@ConditionalOnMissingBean
public JndiDataSourceCreator jndiDataSourceCreator() {
return new JndiDataSourceCreator();
}
@Bean
@ConditionalOnMissingBean
public DruidDataSourceCreator druidDataSourceCreator() {
return new DruidDataSourceCreator(properties.getDruid());
}
@Bean
@ConditionalOnMissingBean
public DruidDataSourceCreator druidDataSourceCreator() {
return new DruidDataSourceCreator(properties.getDruid());
}
@Bean
@ConditionalOnMissingBean
public HikariDataSourceCreator hikariDataSourceCreator() {
return new HikariDataSourceCreator(properties.getHikari());
}
@Bean
@ConditionalOnMissingBean
public HikariDataSourceCreator hikariDataSourceCreator() {
return new HikariDataSourceCreator(properties.getHikari());
}
}

View File

@ -21,8 +21,6 @@ import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.hikari.HikariCp
import com.baomidou.dynamic.datasource.strategy.DynamicDataSourceStrategy;
import com.baomidou.dynamic.datasource.strategy.LoadBalanceDynamicDataSourceStrategy;
import com.baomidou.dynamic.datasource.toolkit.CryptoUtils;
import java.util.LinkedHashMap;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@ -31,6 +29,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.core.Ordered;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* DynamicDataSourceProperties
*
@ -44,54 +45,54 @@ import org.springframework.core.Ordered;
@ConfigurationProperties(prefix = DynamicDataSourceProperties.PREFIX)
public class DynamicDataSourceProperties {
public static final String PREFIX = "spring.datasource.dynamic";
public static final String HEALTH = PREFIX + ".health";
public static final String PREFIX = "spring.datasource.dynamic";
public static final String HEALTH = PREFIX + ".health";
/**
* 必须设置默认的库,默认master
*/
private String primary = "master";
/**
* 是否启用严格模式,默认不启动. 严格模式下未匹配到数据源直接报错, 非严格模式下则使用默认数据源primary所设置的数据源
*/
private Boolean strict = false;
/**
* 是否使用p6spy输出默认不输出
*/
private Boolean p6spy = false;
/**
* 是否使用seata,默认不使用
*/
private Boolean seata = false;
/**
* 是否使用 spring actuator 监控检查默认不检查
*/
private boolean health = false;
/**
* 每一个数据源
*/
private Map<String, DataSourceProperty> datasource = new LinkedHashMap<>();
/**
* 多数据源选择算法clazz默认负载均衡算法
*/
private Class<? extends DynamicDataSourceStrategy> strategy = LoadBalanceDynamicDataSourceStrategy.class;
/**
* aop切面顺序默认优先级最高
*/
private Integer order = Ordered.HIGHEST_PRECEDENCE;
/**
* Druid全局参数配置
*/
@NestedConfigurationProperty
private DruidConfig druid = new DruidConfig();
/**
* HikariCp全局参数配置
*/
@NestedConfigurationProperty
private HikariCpConfig hikari = new HikariCpConfig();
/**
* 必须设置默认的库,默认master
*/
private String primary = "master";
/**
* 是否启用严格模式,默认不启动. 严格模式下未匹配到数据源直接报错, 非严格模式下则使用默认数据源primary所设置的数据源
*/
private Boolean strict = false;
/**
* 是否使用p6spy输出默认不输出
*/
private Boolean p6spy = false;
/**
* 是否使用seata,默认不使用
*/
private Boolean seata = false;
/**
* 是否使用 spring actuator 监控检查默认不检查
*/
private boolean health = false;
/**
* 每一个数据源
*/
private Map<String, DataSourceProperty> datasource = new LinkedHashMap<>();
/**
* 多数据源选择算法clazz默认负载均衡算法
*/
private Class<? extends DynamicDataSourceStrategy> strategy = LoadBalanceDynamicDataSourceStrategy.class;
/**
* aop切面顺序默认优先级最高
*/
private Integer order = Ordered.HIGHEST_PRECEDENCE;
/**
* Druid全局参数配置
*/
@NestedConfigurationProperty
private DruidConfig druid = new DruidConfig();
/**
* HikariCp全局参数配置
*/
@NestedConfigurationProperty
private HikariCpConfig hikari = new HikariCpConfig();
/**
* 全局默认publicKey
*/
private String publicKey = CryptoUtils.DEFAULT_PUBLIC_KEY_STRING;
/**
* 全局默认publicKey
*/
private String publicKey = CryptoUtils.DEFAULT_PUBLIC_KEY_STRING;
}

View File

@ -41,259 +41,259 @@ import static com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.Dr
@Slf4j
public class DruidConfig {
private Integer initialSize;
private Integer maxActive;
private Integer minIdle;
private Integer maxWait;
private Long timeBetweenEvictionRunsMillis;
private Long timeBetweenLogStatsMillis;
private Integer statSqlMaxSize;
private Long minEvictableIdleTimeMillis;
private Long maxEvictableIdleTimeMillis;
private Boolean testWhileIdle;
private Boolean testOnBorrow;
private Boolean testOnReturn;
private String validationQuery;
private Integer validationQueryTimeout;
private Boolean useGlobalDataSourceStat;
private Boolean asyncInit;
private String filters;
private Boolean clearFiltersEnable;
private Boolean resetStatEnable;
private Integer notFullTimeoutRetryCount;
private Integer maxWaitThreadCount;
private Boolean failFast;
private Long phyTimeoutMillis;
private Boolean keepAlive;
private Boolean poolPreparedStatements;
private Boolean initVariants;
private Boolean initGlobalVariants;
private Boolean useUnfairLock;
private Boolean killWhenSocketReadTimeout;
private Properties connectionProperties;
private Integer maxPoolPreparedStatementPerConnectionSize;
private String initConnectionSqls;
private Boolean sharePreparedStatements;
private Integer connectionErrorRetryAttempts;
private Boolean breakAfterAcquireFailure;
private Boolean removeAbandoned;
private Integer removeAbandonedTimeoutMillis;
private Boolean logAbandoned;
private Integer queryTimeout;
private Integer transactionQueryTimeout;
private String publicKey;
private Integer initialSize;
private Integer maxActive;
private Integer minIdle;
private Integer maxWait;
private Long timeBetweenEvictionRunsMillis;
private Long timeBetweenLogStatsMillis;
private Integer statSqlMaxSize;
private Long minEvictableIdleTimeMillis;
private Long maxEvictableIdleTimeMillis;
private Boolean testWhileIdle;
private Boolean testOnBorrow;
private Boolean testOnReturn;
private String validationQuery;
private Integer validationQueryTimeout;
private Boolean useGlobalDataSourceStat;
private Boolean asyncInit;
private String filters;
private Boolean clearFiltersEnable;
private Boolean resetStatEnable;
private Integer notFullTimeoutRetryCount;
private Integer maxWaitThreadCount;
private Boolean failFast;
private Long phyTimeoutMillis;
private Boolean keepAlive;
private Boolean poolPreparedStatements;
private Boolean initVariants;
private Boolean initGlobalVariants;
private Boolean useUnfairLock;
private Boolean killWhenSocketReadTimeout;
private Properties connectionProperties;
private Integer maxPoolPreparedStatementPerConnectionSize;
private String initConnectionSqls;
private Boolean sharePreparedStatements;
private Integer connectionErrorRetryAttempts;
private Boolean breakAfterAcquireFailure;
private Boolean removeAbandoned;
private Integer removeAbandonedTimeoutMillis;
private Boolean logAbandoned;
private Integer queryTimeout;
private Integer transactionQueryTimeout;
private String publicKey;
@NestedConfigurationProperty
private DruidWallConfig wall = new DruidWallConfig();
@NestedConfigurationProperty
private DruidWallConfig wall = new DruidWallConfig();
@NestedConfigurationProperty
private DruidStatConfig stat = new DruidStatConfig();
@NestedConfigurationProperty
private DruidStatConfig stat = new DruidStatConfig();
@NestedConfigurationProperty
private DruidSlf4jConfig slf4j = new DruidSlf4jConfig();
@NestedConfigurationProperty
private DruidSlf4jConfig slf4j = new DruidSlf4jConfig();
private List<String> proxyFilters = new ArrayList<>();
private List<String> proxyFilters = new ArrayList<>();
/**
* 根据全局配置和本地配置结合转换为Properties
*
* @param g 全局配置
* @return Druid配置
*/
public Properties toProperties(DruidConfig g) {
Properties properties = new Properties();
Integer initialSize = this.initialSize == null ? g.getInitialSize() : this.initialSize;
if (initialSize != null && !initialSize.equals(DEFAULT_INITIAL_SIZE)) {
properties.setProperty(INITIAL_SIZE, String.valueOf(initialSize));
/**
* 根据全局配置和本地配置结合转换为Properties
*
* @param g 全局配置
* @return Druid配置
*/
public Properties toProperties(DruidConfig g) {
Properties properties = new Properties();
Integer initialSize = this.initialSize == null ? g.getInitialSize() : this.initialSize;
if (initialSize != null && !initialSize.equals(DEFAULT_INITIAL_SIZE)) {
properties.setProperty(INITIAL_SIZE, String.valueOf(initialSize));
}
Integer maxActive = this.maxActive == null ? g.getMaxActive() : this.maxActive;
if (maxActive != null && !maxActive.equals(DEFAULT_MAX_WAIT)) {
properties.setProperty(MAX_ACTIVE, String.valueOf(maxActive));
}
Integer minIdle = this.minIdle == null ? g.getMinIdle() : this.minIdle;
if (minIdle != null && !minIdle.equals(DEFAULT_MIN_IDLE)) {
properties.setProperty(MIN_IDLE, String.valueOf(minIdle));
}
Integer maxWait = this.maxWait == null ? g.getMaxWait() : this.maxWait;
if (maxWait != null && !maxWait.equals(DEFAULT_MAX_WAIT)) {
properties.setProperty(MAX_WAIT, String.valueOf(maxWait));
}
Long timeBetweenEvictionRunsMillis =
this.timeBetweenEvictionRunsMillis == null ? g.getTimeBetweenEvictionRunsMillis() : this.timeBetweenEvictionRunsMillis;
if (timeBetweenEvictionRunsMillis != null && !timeBetweenEvictionRunsMillis.equals(DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS)) {
properties.setProperty(TIME_BETWEEN_EVICTION_RUNS_MILLIS, String.valueOf(timeBetweenEvictionRunsMillis));
}
Long timeBetweenLogStatsMillis =
this.timeBetweenLogStatsMillis == null ? g.getTimeBetweenLogStatsMillis() : this.timeBetweenLogStatsMillis;
if (timeBetweenLogStatsMillis != null && timeBetweenLogStatsMillis > 0) {
properties.setProperty(TIME_BETWEEN_LOG_STATS_MILLIS, String.valueOf(timeBetweenLogStatsMillis));
}
Long minEvictableIdleTimeMillis =
this.minEvictableIdleTimeMillis == null ? g.getMinEvictableIdleTimeMillis() : this.minEvictableIdleTimeMillis;
if (minEvictableIdleTimeMillis != null && !minEvictableIdleTimeMillis.equals(DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS)) {
properties.setProperty(MIN_EVICTABLE_IDLE_TIME_MILLIS, String.valueOf(minEvictableIdleTimeMillis));
}
Long maxEvictableIdleTimeMillis =
this.maxEvictableIdleTimeMillis == null ? g.getMaxEvictableIdleTimeMillis() : this.maxEvictableIdleTimeMillis;
if (maxEvictableIdleTimeMillis != null && !maxEvictableIdleTimeMillis.equals(DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS)) {
properties.setProperty(MAX_EVICTABLE_IDLE_TIME_MILLIS, String.valueOf(maxEvictableIdleTimeMillis));
}
Boolean testWhileIdle = this.testWhileIdle == null ? g.getTestWhileIdle() : this.testWhileIdle;
if (testWhileIdle != null && !testWhileIdle.equals(DEFAULT_WHILE_IDLE)) {
properties.setProperty(TEST_WHILE_IDLE, "false");
}
Boolean testOnBorrow = this.testOnBorrow == null ? g.getTestOnBorrow() : this.testOnBorrow;
if (testOnBorrow != null && !testOnBorrow.equals(DEFAULT_TEST_ON_BORROW)) {
properties.setProperty(TEST_ON_BORROW, "true");
}
String validationQuery = this.validationQuery == null ? g.getValidationQuery() : this.validationQuery;
if (validationQuery != null && validationQuery.length() > 0) {
properties.setProperty(VALIDATION_QUERY, validationQuery);
}
Boolean useGlobalDataSourceStat = this.useGlobalDataSourceStat == null ? g.getUseGlobalDataSourceStat() : this.useGlobalDataSourceStat;
if (useGlobalDataSourceStat != null && useGlobalDataSourceStat.equals(Boolean.TRUE)) {
properties.setProperty(USE_GLOBAL_DATA_SOURCE_STAT, "true");
}
Boolean asyncInit = this.asyncInit == null ? g.getAsyncInit() : this.asyncInit;
if (asyncInit != null && asyncInit.equals(Boolean.TRUE)) {
properties.setProperty(ASYNC_INIT, "true");
}
//filters单独处理默认了stat,wall
String filters = this.filters == null ? g.getFilters() : this.filters;
if (filters == null) {
filters = "stat,wall";
}
if (publicKey != null && publicKey.length() > 0 && !filters.contains("config")) {
filters += ",config";
}
properties.setProperty(FILTERS, filters);
Boolean clearFiltersEnable = this.clearFiltersEnable == null ? g.getClearFiltersEnable() : this.clearFiltersEnable;
if (clearFiltersEnable != null && clearFiltersEnable.equals(Boolean.FALSE)) {
properties.setProperty(CLEAR_FILTERS_ENABLE, "false");
}
Boolean resetStatEnable = this.resetStatEnable == null ? g.getResetStatEnable() : this.resetStatEnable;
if (resetStatEnable != null && resetStatEnable.equals(Boolean.FALSE)) {
properties.setProperty(RESET_STAT_ENABLE, "false");
}
Integer notFullTimeoutRetryCount =
this.notFullTimeoutRetryCount == null ? g.getNotFullTimeoutRetryCount() : this.notFullTimeoutRetryCount;
if (notFullTimeoutRetryCount != null && !notFullTimeoutRetryCount.equals(0)) {
properties.setProperty(NOT_FULL_TIMEOUT_RETRY_COUNT, String.valueOf(notFullTimeoutRetryCount));
}
Integer maxWaitThreadCount = this.maxWaitThreadCount == null ? g.getMaxWaitThreadCount() : this.maxWaitThreadCount;
if (maxWaitThreadCount != null && !maxWaitThreadCount.equals(-1)) {
properties.setProperty(MAX_WAIT_THREAD_COUNT, String.valueOf(maxWaitThreadCount));
}
Boolean failFast = this.failFast == null ? g.getFailFast() : this.failFast;
if (failFast != null && failFast.equals(Boolean.TRUE)) {
properties.setProperty(FAIL_FAST, "true");
}
Long phyTimeoutMillis = this.phyTimeoutMillis == null ? g.getPhyTimeoutMillis() : this.phyTimeoutMillis;
if (phyTimeoutMillis != null && !phyTimeoutMillis.equals(DEFAULT_PHY_TIMEOUT_MILLIS)) {
properties.setProperty(PHY_TIMEOUT_MILLIS, String.valueOf(phyTimeoutMillis));
}
Boolean keepAlive = this.keepAlive == null ? g.getKeepAlive() : this.keepAlive;
if (keepAlive != null && keepAlive.equals(Boolean.TRUE)) {
properties.setProperty(KEEP_ALIVE, "true");
}
Boolean poolPreparedStatements = this.poolPreparedStatements == null ? g.getPoolPreparedStatements() : this.poolPreparedStatements;
if (poolPreparedStatements != null && poolPreparedStatements.equals(Boolean.TRUE)) {
properties.setProperty(POOL_PREPARED_STATEMENTS, "true");
}
Boolean initVariants = this.initVariants == null ? g.getInitVariants() : this.initVariants;
if (initVariants != null && initVariants.equals(Boolean.TRUE)) {
properties.setProperty(INIT_VARIANTS, "true");
}
Boolean initGlobalVariants = this.initGlobalVariants == null ? g.getInitGlobalVariants() : this.initGlobalVariants;
if (initGlobalVariants != null && initGlobalVariants.equals(Boolean.TRUE)) {
properties.setProperty(INIT_GLOBAL_VARIANTS, "true");
}
Boolean useUnfairLock = this.useUnfairLock == null ? g.getUseUnfairLock() : this.useUnfairLock;
if (useUnfairLock != null) {
properties.setProperty(USE_UNFAIR_LOCK, String.valueOf(useUnfairLock));
}
Boolean killWhenSocketReadTimeout =
this.killWhenSocketReadTimeout == null ? g.getKillWhenSocketReadTimeout() : this.killWhenSocketReadTimeout;
if (killWhenSocketReadTimeout != null && killWhenSocketReadTimeout.equals(Boolean.TRUE)) {
properties.setProperty(KILL_WHEN_SOCKET_READ_TIMEOUT, "true");
}
Properties connectProperties = connectionProperties == null ? g.getConnectionProperties() : connectionProperties;
if (publicKey != null && publicKey.length() > 0) {
if (connectProperties == null) {
connectProperties = new Properties();
}
log.info("dynamic-datasource detect druid publicKey,It is highly recommended that you use the built-in encryption method");
connectProperties.setProperty("config.decrypt", "true");
connectProperties.setProperty("config.decrypt.key", publicKey);
}
this.connectionProperties = connectProperties;
Integer maxPoolPreparedStatementPerConnectionSize =
this.maxPoolPreparedStatementPerConnectionSize == null ? g.getMaxPoolPreparedStatementPerConnectionSize()
: this.maxPoolPreparedStatementPerConnectionSize;
if (maxPoolPreparedStatementPerConnectionSize != null && !maxPoolPreparedStatementPerConnectionSize.equals(10)) {
properties.setProperty(MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE, String.valueOf(maxPoolPreparedStatementPerConnectionSize));
}
String initConnectionSqls = this.initConnectionSqls == null ? g.getInitConnectionSqls() : this.initConnectionSqls;
if (initConnectionSqls != null && initConnectionSqls.length() > 0) {
properties.setProperty(INIT_CONNECTION_SQLS, initConnectionSqls);
}
//stat配置参数
Integer statSqlMaxSize = this.statSqlMaxSize == null ? g.getStatSqlMaxSize() : this.statSqlMaxSize;
if (statSqlMaxSize != null) {
properties.setProperty(STAT_SQL_MAX_SIZE, String.valueOf(statSqlMaxSize));
}
Boolean logSlowSql = stat.getLogSlowSql() == null ? g.stat.getLogSlowSql() : stat.getLogSlowSql();
if (logSlowSql != null && logSlowSql) {
properties.setProperty(STAT_LOG_SLOW_SQL, "true");
}
Long slowSqlMillis = stat.getSlowSqlMillis() == null ? g.stat.getSlowSqlMillis() : stat.getSlowSqlMillis();
if (slowSqlMillis != null) {
properties.setProperty(STAT_SLOW_SQL_MILLIS, slowSqlMillis.toString());
}
Boolean mergeSql = stat.getMergeSql() == null ? g.stat.getMergeSql() : stat.getMergeSql();
if (mergeSql != null && mergeSql) {
properties.setProperty(STAT_MERGE_SQL, "true");
}
return properties;
}
Integer maxActive = this.maxActive == null ? g.getMaxActive() : this.maxActive;
if (maxActive != null && !maxActive.equals(DEFAULT_MAX_WAIT)) {
properties.setProperty(MAX_ACTIVE, String.valueOf(maxActive));
public List<String> getProxyFilters() {
return proxyFilters;
}
Integer minIdle = this.minIdle == null ? g.getMinIdle() : this.minIdle;
if (minIdle != null && !minIdle.equals(DEFAULT_MIN_IDLE)) {
properties.setProperty(MIN_IDLE, String.valueOf(minIdle));
public void setProxyFilters(List<String> proxyFilters) {
this.proxyFilters = proxyFilters;
}
Integer maxWait = this.maxWait == null ? g.getMaxWait() : this.maxWait;
if (maxWait != null && !maxWait.equals(DEFAULT_MAX_WAIT)) {
properties.setProperty(MAX_WAIT, String.valueOf(maxWait));
}
Long timeBetweenEvictionRunsMillis =
this.timeBetweenEvictionRunsMillis == null ? g.getTimeBetweenEvictionRunsMillis() : this.timeBetweenEvictionRunsMillis;
if (timeBetweenEvictionRunsMillis != null && !timeBetweenEvictionRunsMillis.equals(DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS)) {
properties.setProperty(TIME_BETWEEN_EVICTION_RUNS_MILLIS, String.valueOf(timeBetweenEvictionRunsMillis));
}
Long timeBetweenLogStatsMillis =
this.timeBetweenLogStatsMillis == null ? g.getTimeBetweenLogStatsMillis() : this.timeBetweenLogStatsMillis;
if (timeBetweenLogStatsMillis != null && timeBetweenLogStatsMillis > 0) {
properties.setProperty(TIME_BETWEEN_LOG_STATS_MILLIS, String.valueOf(timeBetweenLogStatsMillis));
}
Long minEvictableIdleTimeMillis =
this.minEvictableIdleTimeMillis == null ? g.getMinEvictableIdleTimeMillis() : this.minEvictableIdleTimeMillis;
if (minEvictableIdleTimeMillis != null && !minEvictableIdleTimeMillis.equals(DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS)) {
properties.setProperty(MIN_EVICTABLE_IDLE_TIME_MILLIS, String.valueOf(minEvictableIdleTimeMillis));
}
Long maxEvictableIdleTimeMillis =
this.maxEvictableIdleTimeMillis == null ? g.getMaxEvictableIdleTimeMillis() : this.maxEvictableIdleTimeMillis;
if (maxEvictableIdleTimeMillis != null && !maxEvictableIdleTimeMillis.equals(DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS)) {
properties.setProperty(MAX_EVICTABLE_IDLE_TIME_MILLIS, String.valueOf(maxEvictableIdleTimeMillis));
}
Boolean testWhileIdle = this.testWhileIdle == null ? g.getTestWhileIdle() : this.testWhileIdle;
if (testWhileIdle != null && !testWhileIdle.equals(DEFAULT_WHILE_IDLE)) {
properties.setProperty(TEST_WHILE_IDLE, "false");
}
Boolean testOnBorrow = this.testOnBorrow == null ? g.getTestOnBorrow() : this.testOnBorrow;
if (testOnBorrow != null && !testOnBorrow.equals(DEFAULT_TEST_ON_BORROW)) {
properties.setProperty(TEST_ON_BORROW, "true");
}
String validationQuery = this.validationQuery == null ? g.getValidationQuery() : this.validationQuery;
if (validationQuery != null && validationQuery.length() > 0) {
properties.setProperty(VALIDATION_QUERY, validationQuery);
}
Boolean useGlobalDataSourceStat = this.useGlobalDataSourceStat == null ? g.getUseGlobalDataSourceStat() : this.useGlobalDataSourceStat;
if (useGlobalDataSourceStat != null && useGlobalDataSourceStat.equals(Boolean.TRUE)) {
properties.setProperty(USE_GLOBAL_DATA_SOURCE_STAT, "true");
}
Boolean asyncInit = this.asyncInit == null ? g.getAsyncInit() : this.asyncInit;
if (asyncInit != null && asyncInit.equals(Boolean.TRUE)) {
properties.setProperty(ASYNC_INIT, "true");
}
//filters单独处理默认了stat,wall
String filters = this.filters == null ? g.getFilters() : this.filters;
if (filters == null) {
filters = "stat,wall";
}
if (publicKey != null && publicKey.length() > 0 && !filters.contains("config")) {
filters += ",config";
}
properties.setProperty(FILTERS, filters);
Boolean clearFiltersEnable = this.clearFiltersEnable == null ? g.getClearFiltersEnable() : this.clearFiltersEnable;
if (clearFiltersEnable != null && clearFiltersEnable.equals(Boolean.FALSE)) {
properties.setProperty(CLEAR_FILTERS_ENABLE, "false");
}
Boolean resetStatEnable = this.resetStatEnable == null ? g.getResetStatEnable() : this.resetStatEnable;
if (resetStatEnable != null && resetStatEnable.equals(Boolean.FALSE)) {
properties.setProperty(RESET_STAT_ENABLE, "false");
}
Integer notFullTimeoutRetryCount =
this.notFullTimeoutRetryCount == null ? g.getNotFullTimeoutRetryCount() : this.notFullTimeoutRetryCount;
if (notFullTimeoutRetryCount != null && !notFullTimeoutRetryCount.equals(0)) {
properties.setProperty(NOT_FULL_TIMEOUT_RETRY_COUNT, String.valueOf(notFullTimeoutRetryCount));
}
Integer maxWaitThreadCount = this.maxWaitThreadCount == null ? g.getMaxWaitThreadCount() : this.maxWaitThreadCount;
if (maxWaitThreadCount != null && !maxWaitThreadCount.equals(-1)) {
properties.setProperty(MAX_WAIT_THREAD_COUNT, String.valueOf(maxWaitThreadCount));
}
Boolean failFast = this.failFast == null ? g.getFailFast() : this.failFast;
if (failFast != null && failFast.equals(Boolean.TRUE)) {
properties.setProperty(FAIL_FAST, "true");
}
Long phyTimeoutMillis = this.phyTimeoutMillis == null ? g.getPhyTimeoutMillis() : this.phyTimeoutMillis;
if (phyTimeoutMillis != null && !phyTimeoutMillis.equals(DEFAULT_PHY_TIMEOUT_MILLIS)) {
properties.setProperty(PHY_TIMEOUT_MILLIS, String.valueOf(phyTimeoutMillis));
}
Boolean keepAlive = this.keepAlive == null ? g.getKeepAlive() : this.keepAlive;
if (keepAlive != null && keepAlive.equals(Boolean.TRUE)) {
properties.setProperty(KEEP_ALIVE, "true");
}
Boolean poolPreparedStatements = this.poolPreparedStatements == null ? g.getPoolPreparedStatements() : this.poolPreparedStatements;
if (poolPreparedStatements != null && poolPreparedStatements.equals(Boolean.TRUE)) {
properties.setProperty(POOL_PREPARED_STATEMENTS, "true");
}
Boolean initVariants = this.initVariants == null ? g.getInitVariants() : this.initVariants;
if (initVariants != null && initVariants.equals(Boolean.TRUE)) {
properties.setProperty(INIT_VARIANTS, "true");
}
Boolean initGlobalVariants = this.initGlobalVariants == null ? g.getInitGlobalVariants() : this.initGlobalVariants;
if (initGlobalVariants != null && initGlobalVariants.equals(Boolean.TRUE)) {
properties.setProperty(INIT_GLOBAL_VARIANTS, "true");
}
Boolean useUnfairLock = this.useUnfairLock == null ? g.getUseUnfairLock() : this.useUnfairLock;
if (useUnfairLock != null) {
properties.setProperty(USE_UNFAIR_LOCK, String.valueOf(useUnfairLock));
}
Boolean killWhenSocketReadTimeout =
this.killWhenSocketReadTimeout == null ? g.getKillWhenSocketReadTimeout() : this.killWhenSocketReadTimeout;
if (killWhenSocketReadTimeout != null && killWhenSocketReadTimeout.equals(Boolean.TRUE)) {
properties.setProperty(KILL_WHEN_SOCKET_READ_TIMEOUT, "true");
}
Properties connectProperties = connectionProperties == null ? g.getConnectionProperties() : connectionProperties;
if (publicKey != null && publicKey.length() > 0) {
if (connectProperties == null) {
connectProperties = new Properties();
}
log.info("dynamic-datasource detect druid publicKey,It is highly recommended that you use the built-in encryption method");
connectProperties.setProperty("config.decrypt", "true");
connectProperties.setProperty("config.decrypt.key", publicKey);
}
this.connectionProperties = connectProperties;
Integer maxPoolPreparedStatementPerConnectionSize =
this.maxPoolPreparedStatementPerConnectionSize == null ? g.getMaxPoolPreparedStatementPerConnectionSize()
: this.maxPoolPreparedStatementPerConnectionSize;
if (maxPoolPreparedStatementPerConnectionSize != null && !maxPoolPreparedStatementPerConnectionSize.equals(10)) {
properties.setProperty(MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE, String.valueOf(maxPoolPreparedStatementPerConnectionSize));
}
String initConnectionSqls = this.initConnectionSqls == null ? g.getInitConnectionSqls() : this.initConnectionSqls;
if (initConnectionSqls != null && initConnectionSqls.length() > 0) {
properties.setProperty(INIT_CONNECTION_SQLS, initConnectionSqls);
}
//stat配置参数
Integer statSqlMaxSize = this.statSqlMaxSize == null ? g.getStatSqlMaxSize() : this.statSqlMaxSize;
if (statSqlMaxSize != null) {
properties.setProperty(STAT_SQL_MAX_SIZE, String.valueOf(statSqlMaxSize));
}
Boolean logSlowSql = stat.getLogSlowSql() == null ? g.stat.getLogSlowSql() : stat.getLogSlowSql();
if (logSlowSql != null && logSlowSql) {
properties.setProperty(STAT_LOG_SLOW_SQL, "true");
}
Long slowSqlMillis = stat.getSlowSqlMillis() == null ? g.stat.getSlowSqlMillis() : stat.getSlowSqlMillis();
if (slowSqlMillis != null) {
properties.setProperty(STAT_SLOW_SQL_MILLIS, slowSqlMillis.toString());
}
Boolean mergeSql = stat.getMergeSql() == null ? g.stat.getMergeSql() : stat.getMergeSql();
if (mergeSql != null && mergeSql) {
properties.setProperty(STAT_MERGE_SQL, "true");
}
return properties;
}
public List<String> getProxyFilters() {
return proxyFilters;
}
public void setProxyFilters(List<String> proxyFilters) {
this.proxyFilters = proxyFilters;
}
}

Some files were not shown because too many files have changed in this diff Show More