之前学习springboot自动装配时,了解了如何自己写一个spring-boot-starter进行引入其它项目里,以此来记录,加深记忆,
ip计数器原理: 当别人访问自己的网页时,得到ip地址然后进行记录,若多次访问 则进行+1操作,并打印在控制台
如何自己动手搭建一个xx-spring-boot-starter
如何搭建一个技术starter呢?下面就是一些具体操作,一般自己搭建的starter都是以 xx技术-spring-boot-starter 的形式命名
创建一个springboot项目
首先创建一个spring boot项目 对项目名字和maven坐标进行修改,例如搭一个叫做 ip-count-spring-boot-starter项目
做好命名规范
点击next 后继续点击 把项目创建好后,开始搭基本框架
配置属性类
这里我们设置三个属性
第一个:cycle:多少时间打印一次
第二个:reset属性代表是否每次周期性打印时,是否清空里面存储的值,重新计数
第三个:modle 分为,极简模式(只显示ip地址)和详细模式(显示ip地址和次数)
package com.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 设置属性
*
* @author 幕自由人
* @date 2022/04/30
*/
@Component("ipProperties")
@ConfigurationProperties(prefix = "tools")
public class IpProperties {
/**
* 周期数,多少秒打印一次
*/
private Long cycle=5L;
/**
* 每次周期是否重置ip信息
*/
private Boolean reset=false;
/**
* 打印模式,默认详细
*/
private String model=LogModel.DETAIL.value;
public Long getCycle() {
return cycle;
}
public void setCycle(Long cycle) {
this.cycle = cycle;
}
public Boolean getReset() {
return reset;
}
public void setReset(Boolean reset) {
this.reset = reset;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
/**
* 日志模式
*
* @author 幕自由人
* @date 2022/04/30
* 利用枚举设置信息
*/
public enum LogModel {
DETAIL("dateil"),
SIMPLE("simple");
private String value;
LogModel(String value){
this.value=value;
}
public String getValue() {
return value;
}
}
}
根据属性类编写逻辑代码
需求是:别人访问地址后获取他的ip地址进行保存后并且对着ip的访问次数也+1操作
利用Map集合进行存储:key是IP地址,value是 该ip访问的次数
count()方法:
/**
* 计数功能的实现
*/
public void count(){
// 利用hashmap存储
//key存在+1 不存在 设置为1
String ipaddress=request.getRemoteAddr();
if (ipCountMap.containsKey(ipaddress)){
ipCountMap.put(ipaddress,ipCountMap.get(ipaddress)+1);
}else {
ipCountMap.put(ipaddress,1);
}
}
print打印方法()
/**
* 把存储在map里面的东西根据设置的属性条件打印出来打印查出来
* 通过bean的注入形式把 cycle属性注入到cron表达式中
*/
@Scheduled(cron = "0/#{ipProperties.cycle} * * * * ?")
public void print(){
// 判断是否是详细模式
if (ipProperties.getModel().equals(IpProperties.LogModel.DETAIL.getValue())){
System.out.println(" ip访问监控");
System.out.println("+----ipaddress----+---num---+");
Set<String> strings = ipCountMap.keySet();
for (String string : strings) {
Integer integer = ipCountMap.get(string);
System.out.println(String.format("|%15s |%5d |", string, integer));
}
System.out.println("+-----------------+---------+");
}//判断是否是简单模式
else if(ipProperties.getModel().equals(IpProperties.LogModel.SIMPLE.getValue())){
System.out.println(" ip访问监控");
System.out.println("+----ipaddress----+");
Set<String> strings = ipCountMap.keySet();
for (String string : strings) {
System.out.println(String.format("|%15s |", string));
}
System.out.println("+-----------------+");
}
// 判断是否是周期性更新
if (ipProperties.getReset()){
ipCountMap.clear();
}
}
完整的业务逻辑代码:
package com.service;
import com.properties.IpProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class IpCountService {
// 通过调用该技术的项目进行注入
@Autowired
private HttpServletRequest request;
private Map<String, Integer> ipCountMap=new HashMap<>();
/**
* 计数功能的实现
*/
public void count(){
// 利用hashmap存储
//key存在+1 不存在 设置为1
String ipaddress=request.getRemoteAddr();
if (ipCountMap.containsKey(ipaddress)){
ipCountMap.put(ipaddress,ipCountMap.get(ipaddress)+1);
}else {
ipCountMap.put(ipaddress,1);
}
}
@Autowired
private IpProperties ipProperties;
/**
* 把存储在map里面的东西根据设置的属性条件打印出来打印查出来
* 通过bean的注入形式把 cycle属性注入到cron表达式中
*/
@Scheduled(cron = "0/#{ipProperties.cycle} * * * * ?")
public void print(){
// 判断是否是详细模式
if (ipProperties.getModel().equals(IpProperties.LogModel.DETAIL.getValue())){
System.out.println(" ip访问监控");
System.out.println("+----ipaddress----+---num---+");
Set<String> strings = ipCountMap.keySet();
for (String string : strings) {
Integer integer = ipCountMap.get(string);
System.out.println(String.format("|%15s |%5d |", string, integer));
}
System.out.println("+-----------------+---------+");
}//判断是否是简单模式
else if(ipProperties.getModel().equals(IpProperties.LogModel.SIMPLE.getValue())){
System.out.println(" ip访问监控");
System.out.println("+----ipaddress----+");
Set<String> strings = ipCountMap.keySet();
for (String string : strings) {
System.out.println(String.format("|%15s |", string));
}
System.out.println("+-----------------+");
}
// 判断是否是周期性更新
if (ipProperties.getReset()){
ipCountMap.clear();
}
}
}
编写spring.factories和自动配置类引入业务类
第一步编写自动装配类,什么都不用做映入类 和开启定时器就行了
/**
* ip自动装配类
*
* @author 幕自由人
* @date 2022/04/30
*/
@Configuration
//引入类
@Import(IpCountService.class)
//开启定时器
@EnableScheduling
public class IpAutoConfig {
}
第二步在resource下创建META-INF文件夹创建spring.factories
#自动加载的类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.autoconfig.IpAutoConfig
编写拦截器
package com.interceptor;
import com.service.IpCountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* ip数拦截器
*配置拦截器,设置对那些地址进行拦截
* @author 幕自由人
* @date 2022/04/30
*/
public class IpCountInterceptor implements HandlerInterceptor {
// 属性注入
@Autowired
private IpCountService ipCountService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
ipCountService.count();
return HandlerInterceptor.super.preHandle(request, response, handler);
}
}
添加拦截器
package com.config;
import com.interceptor.IpCountInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器,设置拦截路径
registry.addInterceptor(interceptor()).addPathPatterns("/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
// 把拦截器实例化bean
@Bean
public IpCountInterceptor interceptor(){
return new IpCountInterceptor();
}
}
设置属性提示语
第一步导包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
导完包后编译一下 然后把在注释掉(目的是防止重复提示)
找到编译文件下的json文件:
打开application.yml设置属性时,就会有提示语了
设置属性提示选择
打开之前的json文件 找到最底部的属性:
{
"groups": [
{
"name": "tools",
"type": "com.properties.IpProperties",
"sourceType": "com.properties.IpProperties"
}
],
"properties": [
{
"name": "tools.cycle",
"type": "java.lang.Long",
"description": "周期数,多少秒打印一次",
"sourceType": "com.properties.IpProperties",
"defaultValue": 5
},
{
"name": "tools.model",
"type": "java.lang.String",
"description": "打印模式,默认详细",
"sourceType": "com.properties.IpProperties"
},
{
"name": "tools.reset",
"type": "java.lang.Boolean",
"description": "每次周期是否重置ip信息",
"sourceType": "com.properties.IpProperties",
"defaultValue": false
}
],
"hints": []
}
修改成:
{
"groups": [
{
"name": "tools",
"type": "com.properties.IpProperties",
"sourceType": "com.properties.IpProperties"
}
],
"properties": [
{
"name": "tools.cycle",
"type": "java.lang.Long",
"description": "周期数,多少秒打印一次",
"sourceType": "com.properties.IpProperties",
"defaultValue": 5
},
{
"name": "tools.model",
"type": "java.lang.String",
"description": "打印模式,默认详细",
"sourceType": "com.properties.IpProperties"
},
{
"name": "tools.reset",
"type": "java.lang.Boolean",
"description": "每次周期是否重置ip信息",
"sourceType": "com.properties.IpProperties",
"defaultValue": false
}
],
"hints": [{
"name": "tools.model",
"values":[{
"value": "simple",
"description": "极简模式"
},{
"value": "detail",
"description": "详细模式"
}]
}]
}
选择的值就会出现提示语了
清除(clean)安装(install) 到本地仓库
ctrl+鼠标点击maven 生命周期的 clean 和install 在点击运行
创建一个springbootweb项目引入刚刚安装到仓库的项目坐标坐标
然后配置yml文件
启动项目就会发现会自动打印了