开发之前可以先看看第三方starter的格式,命名方式都是 第三方名称-spring-boot-starter
可以参考druid的开发模式,一个模块开发完,其实也可以分模块开发
创建一个springboot模块,模块名称就是starter名称,例如我这里的模块名称为ip_spring_boot_starter
项目整体结构,注意包名要和目标工程不一致,不然导入后,目标工程扫包会扫到一起,出现其他错误,IpProperties都自动装配上,报错出现不唯一的bean。
pom文件导入业务开发所需要的依赖坐标
比如,我这次设计的业务是记录系统访客独立id访问次数,把开发的业务写到service中,业务开发根据目标工程的需要来编写,因人而异,这里不多说明。
比如,目标项目的方法需要实现该业务,就需要在方法中加入bean.业务方法()来调用,如果很多方法都需要实现该业务,不可能去每个方法里都加上这么一句代码。这里用拦截器实现,详情如下
这里我们拦截器的功能是定义好了,但是spring并没加载它,拦截器没有起作用,下面需要注册这个拦截器,在SpringMvcConfig中,做如下配置
知识点:加上注解@Configuration的配置类,@Bean创建的是代理对象,直接拿容器中已注入的bean,调用时不会再new一个新的bean
①输出频率:多久输出一次(默认10秒输出一次)
②数据特征:累计数据 / 阶段数据(默认为累计数据)
③数据格式:详细模式 / 极简模式 (默认为详细模式)
目标工程的yml配置文件中设置
ipProperties类上加上注解
至此ipProperties是获取到了配置的属性数据,但是还没有用到业务方法中,等于说给的属性值没起作用,接下来就要把ipProperties的配置属性值加到业务方法里,详细如下
业务工程的pom文件加入配置处理器的坐标
但是注意,要实现有提示功能,需要这个坐标,但是给目标工程使用时,install的时候,需要把这个坐标注释掉,因为这样jar包里有一组提示,文件里有一组提示,会出现两组提示
简单点吧,就是开发提示功能时导入这个坐标,开发完成后,install的时候,注释掉这个坐标就行了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
配置文件中的提示信息都来自ipProperties类里写的注释,但是我们还想实现这种写到最后有可选模式,就需要在spring-configuration-metadata.json中添加点东西了,hints里默认是没有值的,我们需要添加可选的代码。
添加内容
"hints": [
{
"name": "tools.ip.model",
"values": [
{
"value": "detail",
"description": "详细模式."
},
{
"value": "simple",
"description": "极简模式."
}
]
这里照搬druid的自动配置文件,改一下即可,autoconfig包创建一个自动配置类,在自动配置类中加载业务类,将它定义成bean,可以直接@Import导入也可以使用@Bean。
自动配置类
最后效果是加载该业务模块时,会加载spring.factories文件,加载spring.factories时会根据spring.factories里的全路径类名加载autoconfig包下的自动配置类,加载自动配置类会加载类中定义的bean,即在目标工程导入了业务的bean实现业务功能。
1.先把业务工程install安装到仓库中(右侧maven,点击业务工程,install),这样目标工程才能从仓库中导入
注意:业务工程的每次功能,代码的更新就要clean再install,保证仓库里的是最新版,这样目标工程也能同步上。
2.目标工程的pom文件导入坐标,例如下
<!-- 自定义starter-->
<dependency>
<groupId>com</groupId>
<artifactId>ip_spring_boot_starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
若想在目标工程中使用业务模块的功能,除了导入坐标,还需要在使用业务模块的位置,进行自动配置,例如下
@Autowired
private IpCountService ipCountService;//自动配置
@GetMapping("{currentPage}/{pageSize}")
public Result getPage(@PathVariable int currentPage,@PathVariable int pageSize,Book book){
ipCountService.count();//调用自定义模块业务方法
IPage<Book> iPage = bookService.getPage(currentPage, pageSize,book);
//如果当前页码值大于了总页码值,那么重新执行查询操作,使用最大页码值作为当前页码值
//适用场景: 就是第3页只有一条数据,删除自动刷新后,当前页仍然是3页,但最大页码已经变成2页了,可以f12详细看看
if (currentPage> iPage.getPages()){
iPage=bookService.getPage((int)iPage.getPages(),pageSize,book);
}
Integer code=iPage!=null?Code.GET_OK:Code.GET_ERR;
String msg=iPage!=null?"success":"查询失败,请稍后再试";
return new Result(code,iPage,msg);
}
该业务实现的就是每次分页查询时,获取访问页面的ip及访问次数