1.基本类的创建以及相关配置
原理:通过ip访问开放api,获取返回json数据
String body = HttpUtil.get("https://ip.taobao.com/outGetIpInfo?ip=" + ip + "&accessKey=alibaba-inc");
对body进行反序列化
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class IpDetail implements Serializable {
private static final long serialVersionUID = 1L;
//注册时的ip
private String ip;
//最新登录的ip
private String isp;
private String isp_id;
private String city;
private String city_id;
private String country;
private String country_id;
private String region;
private String region_id;
}
@Data
public class IpInfo implements Serializable {
private static final long serialVersionUID = 1L;
//注册时的ip
private String createIp;
//注册时的ip详情
private IpDetail createIpDetail;
//最新登录的ip
private String updateIp;
//最新登录的ip详情
private IpDetail updateIpDetail;
}
对应映射对象 1.添加@TableName(value ="sec_user", autoResultMap = true),否则对象不能反序列化,结果为空 2.typeHandler = JacksonTypeHandler.class指定序列化工具类 3.mysql数据库中的数据结构为json
@TableName(value ="sec_user", autoResultMap = true)
@Data
public class User implements Serializable {
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
*
*/
private String icon;
/**
* 昵称
*/
private String nickname;
/**
* 电话
*/
private Long phone;
/**
* 邮箱
*/
private String mail;
/**
*
*/
private Integer state;
/**
*
*/
private Date updateTime;
/**
*
*/
private Date createTime;
/**
*
*/
@TableField( value = "ip_info",typeHandler = JacksonTypeHandler.class)
private IpInfo ipInfo;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}
2.流程介绍
1.创建用户并添加数据库(只需要更新ip,不需要detail更新)
2.把用户的基本信息作为事件传递
3.使用uid更新detail
3.代码中实现
1.事件发布可以通过spring有关event的组件,将String换成User就行
/**
* moudle------
* <p></p>
*
* @author : zlx
* @date : 2024-08-14 23:54
**/
@Component
@Slf4j
public class Listener {
@Async()
@EventListener(classes = MyEvent.class)
public void onEvent(MyEvent event)
{
String msg = event.getMsg();
log.info(msg);
}
@Async()
@EventListener(classes = MyEvent.class)
public void onEvent2(MyEvent event)
{
String msg = event.getMsg();
log.info(msg+"demo1");
}
}
@Getter
public class MyEvent extends ApplicationEvent {
private final String msg;
public MyEvent(Object source,String msg) {
super(source);
this.msg=msg;
}
}
2.因为对象的嵌套关系User->ipInfo->IpDeatil 我们可以在外层对象中编写方法,创建或者修改内部对象的属性,减少new的使用
public void refreshIp(String ip) {
if (ipInfo == null) {
ipInfo = new IpInfo();
}
ipInfo.refreshIp(ip);
}
User对象中,设置一个基本的IpInfo
3.Ipinfo对象中,处理四个变量之间的关系和相互值设置
1.ip创建阶段:
1.创建时,设置updateIP和createIP 此时值是相同的,
2.当更新时,处理updateIP
public void CreatorRefreshIp(String ip) {
if (StringUtils.isEmpty(ip)) {
return;
}
updateIp = ip;
if (createIp == null) {
createIp = ip;
}
}
2.detail处理阶段:
detail的第一步通过ip获取detail,有两种情景需要访问,获取需要处理的ip
情景1 detail为空
情景2 updateIp先行更新,detail不匹配
public String needRefreshIp() {
//或条件的编写
boolean notNeedRefresh = Optional.ofNullable(updateIpDetail)
// 1
.map(IpDetail::getIp)
// 2.
.filter(ip -> Objects.equals(ip, updateIp))
.isPresent();
return notNeedRefresh ? null : updateIp;
}
代码解释:.ofNullable(updateIpDetail)可返回空, .filter(ip -> Objects.equals(ip, updateIp))可返回空,两个条件是"或"关系
通过空判断bool
3.detail设置阶段
创建时,ip相同 两个detail都能实现 更新时,只更新 update的Detail
public void refreshIpDetail(IpDetail ipDetail) {
if (Objects.equals(createIp, ipDetail.getIp())) {
createIpDetail = ipDetail;
}
if (Objects.equals(updateIp, ipDetail.getIp())) {
updateIpDetail = ipDetail;
}
}
4工具类的封装
此笔记为mallchat的学习记录
参考少年阿斌/MallChat - 码云 - 开源中国 (gitee.com)中mallchat-chat-server/src/main/java/com/abin/mallchat/common/user/service/impl中的方法