实现一个自己的spring-boot-starter,基于SQL生成HTTP接口
上一篇博文介绍了Spring Boot Starter,这次我们就实现一个自己的starter模块,引入了该模块,项目就自然具有了通过配置SQL自动生成HTTP接口的能力。
完整代码可以到github下载:https://github.com/chengpei/sqlapi-spring-boot-starter
需求来源
我们在做一些大屏类项目时往往会需要对接一些第三方的数据,提供一些HTTP接口给大屏的前端用于查询数据展示,而这些第三方的数据表可能命名不规范,数据格式不规范,如果基于别人的表生成代码写接口,可能会经常性的修改变动,所以这里最好的解决方案我认为是直接在数据库里配置sql,基于sql生成HTTP接口给前端使用,这样后续变动只需要修改配置的sql,不需要频繁更新代码。
这里我首先想到的是使用开源的解决方案,找了几个但是我觉得太重了,而且我们项目的接口也并不是全部通过sql都能解决的,有些需要对接第三方接口,所以决定自己实现一个简单版的SQL生成HTTP接口的模块,通过SpringBootStarter的方式引入,这样以后哪个项目有这样的需求直接引入即可。
功能介绍
项目中引入该模块后,启动你的项目代码,如果你的项目配置了MySql数据库及Spring-jdbc依赖,则模块会自动创建一张表t_api_generate_config
,并初始化一条数据,启动完成后,项目会具有如下两个接口:
- http://localhost:8085/pageQuery/test?current=1&size=10
- http://localhost:8085/queryOne/test
接口最后的这个/test是接口后缀,是表t_api_generate_config
的字段api_postfix
的配置
第一个接口是分页接口,可以执行表里statement_content
配置的sql分页返回
第二个接口是单条数据查询接口,要求表里statement_content
配置的sql只能返回一条数据,查询效果如下:
同时sql配置支持动态参数,基于freemarker标签配置动态条件,例如statement_content
里配置如下SQL:
select * from t_api_generate_config a where 1=1
<#if apiPostfix?? && apiPostfix != "">
and a.api_postfix = '${apiPostfix}'
</#if>
这样就可以如下方式传参:
http://localhost:8085/pageQuery/test2?current=1&size=10&apiPostfix=test
和分页参数一样放在GET请求地址后即可
sqlapi-spring-boot-starter
这里首先给模块起一个名字,springboot官方似乎并不推荐使用spring-boot-starter-xxxx的命名方式来命名我们自己的starter模块,所以很多第三方的starter模块一般采用类似xxxx-spring-boot-starter格式来命名我们自己的starter模块,例如:dubbo-spring-boot-starter、grpc-spring-boot-starter等等,所以我们这个基于sql生成http接口的模块就叫sqlapi-spring-boot-starter吧
SqlapiAutoConfiguration
模块中最重要的一个类当然是SqlapiAutoConfiguration
,他是自动配置的入口
@Configuration
@ConditionalOnClass({JdbcTemplate.class})
@EnableConfigurationProperties(SqlapiProperties.class)
@ComponentScans(@ComponentScan("top.chengpei.sqlapi.modules"))
@AutoConfigureAfter({JdbcTemplateAutoConfiguration.class})
public class SqlapiAutoConfiguration implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(SqlapiAutoConfiguration.class);
private JdbcTemplate jdbcTemplate;
public SqlapiAutoConfiguration(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void afterPropertiesSet() {
Long count = jdbcTemplate.queryForObject("SELECT COUNT(1) FROM information_schema.TABLES WHERE table_name='t_api_generate_config'", Long.class);
if (count > 0) {
return;
}
logger.info("接口生成表初始化。。。");
String createTableSql = "create table t_api_generate_config\n" +
"(\n" +
" api_postfix varchar(200) not null comment '接口后缀'\n" +
" primary key,\n" +
" api_name varchar(100) not null comment '接口名称',\n" +
" statement_content text not null comment 'sql语句'\n" +
")";
String initDataSql = "INSERT INTO t_api_generate_config (api_postfix, api_name, statement_content) VALUES ('test', '测试接口', 'select * from t_api_generate_config')";
logger.info("创建表:");
logger.info(createTableSql);
jdbcTemplate.execute(createTableSql);
logger.info("初始化数据:");
logger.info(initDataSql);
jdbcTemplate.execute(initDataSql);
logger.info("接口生成表初始化完成。。。");
}
}
这里比较重要的几个注解
- @ConditionalOnClass({JdbcTemplate.class}): 因为我们要执行sql,这里使用的是JdbcTemplate,所以需要环境中有这个类
- @AutoConfigureAfter({JdbcTemplateAutoConfiguration.class}):并且当前自动配置需要在JdbcTemplate配置好以后,因为要初始化表
- @ComponentScans(@ComponentScan(“top.chengpei.sqlapi.modules”)):增加要扫描的包,里面有Controller提供HTTP接口
下面的代码主要是初始化SQL配置表,这里只支持了MySql
spring.factories
有了自动配置类以后,还需要创建一个文件用于SpringFactoriesLoader
加载,文件中加入以下代码即可:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
top.chengpei.sqlapi.autoconfigure.SqlapiAutoConfiguration
接口代码
以上代码配置添加好后,就可以写接口了,需要放在top.chengpei.sqlapi.modules
包下,因为上面的自动配置类中指定的扫描该包,查询接口就不细说了,看看代码就好,这里也只支持了MySql,如果有兴趣的话可以在配置类top.chengpei.sqlapi.autoconfigure.SqlapiProperties
里加上方言的配置,然后修改代码做不同数据库方言的支持。
完整代码可以到github下载:https://github.com/chengpei/sqlapi-spring-boot-starter