download:开课吧 -WEB 全栈架构师进阶指南(30 期)
大道至简, 一个注解实现数据库配置
明天来试试使用一个注解实现数据库配置. 最终成果:
开始
SpringBoot 这个框架还是挺厉害的, 或者有些人认为 SpringBoot 不算一个框架, 它只是 Spring 的增强工具.
当然 Spring 对于 Java 而言有着不可动摇的地位.
就像我之前说的:
天不生 Spring,Java 万古如长夜.
可是 SpringBoot 的重要性也不能熟视无睹.
明天就基于 SpringBoot 来实现使用一个注解来实现数据库配置.
EnableXXX
在 SpringBoot 中, 可能自定义这样一个注解 @EnableXXX, 就是启用某种功能.
在 @EnableXXX 这个注解上使用 @Import 这个注解, 就可能把配置类, 或者什么其余需要 Spring 治理的货色, 注入到 Spring 容器.
就像上面这样, 在启动类上使用这个注解, MybatisExtraConfig.class 这个类就会注入到 Spring 容器中. 相当于这个类就由 Spring 帮你治理了, 你可能在这个类里使用 @Autowired, 或者获取容器等, 而且 MybatisExtraConfig 这个类上不需要使用 @Component 等注解.
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MybatisExtraConfig.class)
public @interface EnableMpExtra {
}
复制代码
其实不使用 @EnableXXX 也可能. 在 resources 目录下新建一个文件夹 META-INF, 而后再新建一个文件 spring.factories, 而后在 spring.factories 中设置 org.springframework.boot.autoconfigure.EnableAutoConfiguration= 等于你的配置类. 这样不使用注解, 在包被引入的时候, 就会主动加载配置类.
动静抉择数据库 ImportSelector
咱们也可能在 @EnableXXX 注解里加一些值, 在启动类上使用的时候, 设置这些值, 最终咱们取到这些值. 这些值就是连接数据库的各种参数,
要获取这些值, 就少不了 ImportSelector.
最初注解是这样的
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DBSelector.class)
public @interface EnableDbStarter {
DbType type() default DbType.MySQL;
String url() default "localhost";
String port() default "3306";
String dbName();
String username() default "root";
String password();
String basePackage();
}
复制代码
DBSelector
public class DBSelector implements ImportSelector {
public static String url;
public static String port;
public static String dbName;
public static String username;
public static String password;
public static String basePackage;
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableDbStarter.class.getName()));
DbType type = attributes.getEnum("type");
url = attributes.getString("url");
port = attributes.getString("port");
dbName = attributes.getString("dbName");
username = attributes.getString("username");
password = attributes.getString("password");
basePackage = attributes.getString("basePackage");
switch (type) {
case Oracle:
return new String[]{OracleConfig.class.getName()};
case MariaDB:
return new String[]{MariaDBConfig.class.getName()};
case SqlServer:
return new String[]{SqlServerConfig.class.getName()};
case PostgreSQL:
return new String[]{PostgreSQLConfig.class.getName()};
case MySQL:
default:
return new String[]{MySqlConfig.class.getName()};
}
}
}
复制代码
这个可能根据枚举值, 来抉择对应的数据库配置. 因为其余数据库临时不需要, 就只写了一个 MySQL 的.
枚举类
public enum DbType {
MySQL,
Oracle,
PostgreSQL,
SqlServer,
MariaDB
}
复制代码
MySql 配置类
这个类下面是没有 @Configuration 这个注解的, 可是因为咱们在 DBSelector 中 return 了这个类, 所以这个类也可能被 Spring 治理的. 可能看到这个类中使用了 @Bean 这个注解, 是可能失常使用的.
public class MySqlConfig {
@Bean("dataSource")
public DataSource dataSource() {
try {DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://" + DBSelector.url + ":" + DBSelector.port + "/" + DBSelector.dbName + "?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai");
dataSource.setUsername(DBSelector.username);
dataSource.setPassword(DBSelector.password);
dataSource.setInitialSize(1);
dataSource.setMaxActive(20);
dataSource.setMinIdle(1);
dataSource.setMaxWait(60_000);
dataSource.setPoolPreparedStatements(true);
dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
dataSource.setTimeBetweenEvictionRunsMillis(60_000);
dataSource.setMinEvictableIdleTimeMillis(300_000);
dataSource.setValidationQuery("SELECT 1");
return dataSource;
} catch (Throwable throwable) {throw new RuntimeException();
}
}
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setVfs(SpringBootVFS.class);
factoryBean.setTypeAliasesPackage(DBSelector.basePackage);
Resource[] mapperResources = new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml");
factoryBean.setMapperLocations(mapperResources);
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
configuration.setJdbcTypeForNull(JdbcType.NULL);
configuration.setMapUnderscoreToCamelCase(true);
configuration.addInterceptor(new SqlExplainInterceptor());
// 分页
configuration.addInterceptor(new PaginationInterceptor());
configuration.setUseGeneratedKeys(true);
factoryBean.setConfiguration(configuration);
return factoryBean.getObject();}
@Bean(name = "sqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean(name = "transactionManager")
public PlatformTransactionManager platformTransactionManager(@Qualifier("dataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "transactionTemplate")
public TransactionTemplate transactionTemplate(@Qualifier("transactionManager") PlatformTransactionManager transactionManager) {return new TransactionTemplate(transactionManager);
}
}
复制代码
其余数据库的配置类就是一个空类. 就像上面这样, 不细说了.
public class OracleConfig {
}
复制代码
使用方法
第一种
简略点就是, 还是在这个我的项目下, 创建 Controller,Service,Mapper,Domain, 而后新建启动类, 而后在启动类上使用 @EnableDbStarter 这个注解. 就是在以后我的项目中测试. 不推荐这种方法, 因为看不出来成果.
第二种
可能把这个我的项目打成 Jar 包, 在其余我的项目引入. 成果比较直观一点, 当然如果有 maven 私服, 可能把这个我的项目发到私服, 而后再其余我的项目使用.
我就是发到了私服, 而后在其余我的项目中引用.
引入依赖, 可能看到依赖也少了很多, 不必再引入 mysql-connector 和 druid 的.
在启动类上使用, 在注解上设置数据库相干的信息, 因为注解有些值有默认值, 就可能少写一点啦.
basePackage 是给 Mybatis 用来扫描别名的.
整个我的项目结构如下, 没有其余配置.
启动看一下
启动胜利.
请求一下
数据库
.
到这里, 使用一个注解就实现了数据库的配置.
感兴趣的小伙伴可能试试其余的, 比如 Swagger 配置,Redis 配置,Dubbo 配置等等, 最终简化为一个注解就可能实现, 最初必定很有成就感.