springboot-自己开发start
步骤
命名规范
- 第三方在建立自己的 Starter 的时候命名规则统一用xxx-spring-boot-starter,
- 官方提供的 Starter 统一命名方式为spring-boot-starter-xxx。
步骤
- 新建一个Maven项目,在pom.xml文件中定义好所需依赖;
- 新建配置类,写好配置项和默认值,使用
@ConfigurationProperties
指明配置项前缀; - 新建自动装配类,使用
@Configuration
和@Bean
来进行自动装配; - 新建
spring.factories
文件,用于指定自动装配类的路径; - 将starter安装到maven仓库,让其他项目能够引用;
- 需要提示功能的话,还必须有
spring-configuration-metadata.json
,通过依赖spring-boot-configuration-processor
生成的,发布后一定要删除该依赖,否则会出双份的提示信息。
1、创建项目,写好依赖
- 删除test依赖和包
spring-boot-configuration-processor
最后是要删除的。主要用于生成spring-configuration-metadata.json
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2、属性配置类
- 写好配置项和默认值。并使用
@ConfigurationProperties
指明配置项前缀,用于加载配置文件对应的前缀配置项: - 建议写doc文档,这样在配置时会有提示
- 如果仅仅添加
@ConfigurationProperties
,会有报错提示,因为有这个注解,他必须是一个可被管控的bean
,先不用管,在IpAutoConfiguration
中引入@Import(IpProperties.class)
就不会再报错了 @Component("ipProperties")
可以不用写,但是服务类上使用了别名,这里主要的目的是定义IpProperties
的别名
public enum IpModeEnum {
/**
* 极简信息
*/
SIMPLE("simple"),
/**
* 详细信息
*/
DETAIL("detail");
private final String value;
IpModeEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
@Component("ipProperties")
@ConfigurationProperties(prefix = "tools.ip")
public class IpProperties {
/**
* 日志显示周期
*/
private Integer cycle = 5;
/**
* 是否周期内重置数据
*/
private boolean cycleReset = false;
/**
* 日志输出模式 detail:详细模式 simple:极简模式
*/
private String model = IpModeEnum.DETAIL.getValue();
public IpProperties() {
}
public IpProperties(Integer cycle, boolean cycleReset, String model) {
this.cycle = cycle;
this.cycleReset = cycleReset;
this.model = model;
}
/**
* 获取
* @return cycle
*/
public Integer getCycle() {
return cycle;
}
/**
* 设置
* @param cycle
*/
public void setCycle(Integer cycle) {
this.cycle = cycle;
}
/**
* 获取
* @return cycleReset
*/
public boolean isCycleReset() {
return cycleReset;
}
/**
* 设置
* @param cycleReset
*/
public void setCycleReset(boolean cycleReset) {
this.cycleReset = cycleReset;
}
/**
* 获取
* @return model
*/
public String getModel() {
return model;
}
/**
* 设置
* @param model
*/
public void setModel(String model) {
this.model = model;
}
public String toString() {
return "IpProperties{cycle = " + cycle + ", cycleReset = " + cycleReset + ", model = " + model + "}";
}
}
3、服务类
public class IpCountService {
/**
* 统计的集合
*/
private final Map<String,Integer> ipCountMap = new HashMap<>();
/**
* 当前的request对象的注入工作由使用当前starter的工程提供自动装配
*/
@Resource
private HttpServletRequest httpServletRequest;
@Autowired
private IpProperties ipProperties;
/**
* 每次调用当前操作,就记录当前访问的IP,然后累加访问次数,并把数据放到map中
*/
public void count(){
//1.获取当前操作的IP地址
String ip = httpServletRequest.getRemoteAddr();
//2.根据IP地址从Map取值,并递增
ipCountMap.merge(ip, 1, Integer::sum);
}
@Scheduled(cron = "0/#{ipProperties.cycle} * * * * ?")
public void print(){
if(ipProperties.getMode().equals(LogModeEnum.DETAIL.getValue())){
System.out.println(" IP访问监控");
System.out.println("+-----ip-address-----+--num--+");
for (Map.Entry<String, Integer> entry : ipCountMap.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.printf("|%18s |%5d |%n",key,value);
}
System.out.println("+--------------------+-------+");
}else if(ipProperties.getMode().equals(LogModeEnum.SIMPLE.getValue())){
System.out.println(" IP访问监控");
System.out.println("+-----ip-address-----+");
for (String key: ipCountMap.keySet()) {
System.out.printf("|%18s |%n",key);
}
System.out.println("+--------------------+");
}
if(ipProperties.isCycleReset()){
ipCountMap.clear();
}
}
}
3、自动配置类
EnableScheduling
:开启定时任务
@EnableScheduling
@Import(IpProperties.class)
public class IpAutoConfiguration {
@Bean
public IpCountService ipCountService(){
return new IpCountService();
}
}
4、拦截器
public class IpCountInterceptor implements HandlerInterceptor {
@Autowired
private IpCountService ipCountService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
ipCountService.count();
return true;
}
}
@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(ipCountInterceptor()).addPathPatterns("/**");
}
@Bean
public IpCountInterceptor ipCountInterceptor(){
return new IpCountInterceptor();
}
}
5、新建spring.factories
文件,用于指定自动装配类的路径;
- 路径:
src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.tjhis.ipconfig.config.IpAutoConfiguration
6、新建spring-configuration-metadata.json
文件,用于在配置时自动提示;
{
"groups": [
{
"name": "tools.ip",
"type": "cn.tjhis.ipconfig.config.IpProperties",
"sourceType": "cn.tjhis.ipconfig.config.IpProperties"
}
],
"properties": [
{
"name": "tools.ip.cycle",
"type": "java.lang.Integer",
"description": "日志显示周期",
"sourceType": "cn.tjhis.ipconfig.config.IpProperties",
"defaultValue": 5
},
{
"name": "tools.ip.cycle-reset",
"type": "java.lang.Boolean",
"description": "是否周期内重置数据",
"sourceType": "cn.tjhis.ipconfig.config.IpProperties",
"defaultValue": false
},
{
"name": "tools.ip.mode",
"type": "java.lang.String",
"description": "日志输出模式 detail:详细模式 simple:极简模式",
"sourceType": "cn.tjhis.ipconfig.config.IpProperties"
}
],
"hints": [
{
"name": "tools.ip.mode",
"values": [
{
"value": "detail",
"description": "详细模式."
},
{
"value": "simple",
"description": "极简模式."
}
]
}
]
}
6、把其安装到maven仓库,这样其他工程就可以引用了
- clean
- install
7、在另一个web工程中引入
<dependency>
<groupId>cn.tjhis</groupId>
<artifactId>ipCount-spring-boot-starter</artifactId>
<version>1.0.1</version>
</dependency>
世界上没有什么事情是跑步解决不了的,如果有,那就再跑一会!