项目场景:
版本:spring boot:2.5.4,JDK:1.8
在学习过程中,遇到这样的一个需求:创建一个简单的项目,实现一个简单的功能,当用户进行查询操作时,获取该用户的IP地址以及统计该用户的访问次数,然后通过第三方项目导入这个项目的坐标。
业务Bean:
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 实现功能:客户端在访问项目的时候,记录客户端的IP地址和统计访问次数
* 实现技术:使用map集合存储客户端访问的次数
* 实现思路:1. 创建一个map集合,用于存储用户ip和访问次数
* 2. 获取客户端的IP地址:从使用该项目的容器中自动装配HttpServletRequest类,调用方法获取IP地址
* 3. 先对客户访问IP是否存在做一个判断,如果不存在,将次数1放入map集合,否则先获取该客户的IP访问次数再进行累加,最后再访问map集合
*/
public class IpCountService {
private Map<String, Integer> map = new HashMap<>();
@Autowired
//初始化在使用该starter的项目工程中实现
private HttpServletRequest httpServletServlet;
public void IpCount(){
//获取客户端IP地址
String ipAddress = httpServletServlet.getRemoteAddr();
//对客户端IP地址是否存在做判断
if (!map.containsKey(ipAddress)){
map.put(ipAddress, 1);
}else{
map.put(ipAddress, map.get(ipAddress)+1);
}
}
@Autowired
private IpProperties ipProperties;
@Scheduled(cron = "0/5 * * * * ?")
public void print(){
//使用String.format格式打印定时器
System.out.println("+-----ip-address-----+--number--+");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String ipAddress = entry.getKey();
Integer count = entry.getValue();
System.out.println(String.format("|%20s+%9d |", ipAddress, count));
}
System.out.println("+--------------------+----------+");
//判断是否在展示完报表后对数据做清除
if (ipProperties.isClear()){
map.clear();
}
}
}
属性Bean:
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("ip-count")
public class IpProperties {
/**
* 日志刷新时间
*/
private Long cycle = 10L;
/**
* 是否在展示完报表后清理数据
*/
private boolean cycleReset = false;
//private boolean isClear = true;
/**
* 报表显示的模式:
* simple-简洁
* detail-详细
*/
private String pattern = Pattern.DETAIL.value;
public Long getCycle() {
return cycle;
}
public void setCycle(Long cycle) {
this.cycle = cycle;
}
public boolean isClear() {
return isClear;
}
public void setClear(boolean clear) {
isClear = clear;
}
// public boolean isCycleReset() {
// return cycleReset;
// }
//
// public void setCycleReset(boolean cycleReset) {
// this.cycleReset = cycleReset;
// }
public String getPattern() {
return pattern;
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
/**
* 对于一些属性的值是一些限定的常量值,应使用枚举类型
*/
public enum Pattern{
//定义枚举中的对象
DETAIL("detail"),
SIMPLE("simple");
//定义枚举对象初始化的值
private final String value;
Pattern(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}
实现功能:记录IP地址和访问次数(具体的前端代码和第三方项目就不再这里展示,因为跟这里遇到的问题关系不大,注意导入在修改自定starter的项目之后,在Maven里面clean之后install一下,或者打开项目结构那里看看jar包有没有导进去就好了)
问题描述
这里想通过配置文件修改报表显示之后清空的效果:
这是没有清空的效果:
清空后的效果就是第二段报表里面的IP和number都清空
原因分析:
检查代码逻辑基本都没有问题,最后发现是变量命名的问题,对于布尔类型的属性我使用了"is"开头命名,导致后续框架无法解析属性,具体也可以参考阿里的规范:
【强制】POJ0类中布尔类型的变量,都不要加is,否则部分框架解析会引起序列化错误。
反例:定义为基本数据类型Boolean isDeleted:的属性,它的方法也是 isDeleted(),RPC框架在反向解析的时候,“以为"对应的属性名称是 deleted,导致属性获取不到,进而抛出异常
或者参考这位老哥的博客:https://blog.csdn.net/baidu_39322753/article/details/121651516
解决方案:
把控制报表刷新的属性修改一下就好了(不用“is”开头)
提示:注意修改starter里面对应的getter方法,还有就是重新生成一下这个属性setter和getter方法,或者直接使用lombok里面的@Data注解