文章目录
- 一、背景
- 二、项目需求
- 三、环境配置
- 四、项目代码
- 4.1 Redis工具类增加集合操作方法
- 4.2 客户实体类
- 4.3 客户信息WebApi
- 4.4 记录并缓存客户信息实现类
- 五、测试与验证
- 5.1 相同信息自动去重
- 5.2 不同集合之间的交集与差集
- 六、源码
一、背景
在前三篇文章
- 《Redis项目应用场景与实例(一):哈希表(Hash)》
- 《Redis项目应用场景与实例(二):字符串(String)》
- 《Redis项目应用场景与实例(三):队列(List)》 介绍了Redis对于Hash表、字符串、队列的操作,该文将对集合(Set)的应用场景进行实际演练。
strings | hashes | lists | sets | sorted sets |
封锁一个IP地址 | 存储用户信息 | 模拟队列 | 自动去重 | 以某一个条件为权重,进行排序 |
二、项目需求
- 创建SpringBoot添加客户信息服务接口;
- 通过Redis集合缓存客户信息,要求自动去重,不得重复记录。
三、环境配置
- 开发环境:
- JDK 1.8
- SpringBoot 2.2.5
- JPA
- Spring Security
- Mysql 8.0
- Redis Server 3.2.1
- Redis Desktop Manager
- Swagger2
– java后端项目结构
四、项目代码
4.1 Redis工具类增加集合操作方法
/**
* Redis工具类
*
* @author zhuhuix
* @date 2020-06-15
* @date 2020-06-17 增加队列操作方法
* @date 2020-06-22 增加集合(set)操作方法
*/
@Component
@AllArgsConstructor
public class RedisUtils {
private RedisTemplate<Object, Object> redisTemplate;
/**
* 向集合中增加元素
*
* @param key 集合键值
* @param value 元素
* @return 添加数量
*/
public long setAdd(String key, Object value) {
return redisTemplate.opsForSet().add(key,value);
}
/**
* 向集合中批量增加元素
*
* @param key 集合键值
* @param list 元素列表
* @return 添加数量
*/
public long setAdd(String key, List<Object> list) {
return redisTemplate.opsForSet().add(key,list);
}
/**
* 集合删除指定元素
*
* @param key 集合键值
* @param value 指定元素
* @return 删除数量
*/
public long setRemove(String key, Object value) {
return redisTemplate.opsForSet().remove(key, value);
}
/**
* 集合批量删除指定元素
*
* @param key 集合键值
* @param list 指定元素列表
* @return 删除数量
*/
public long setRemove(String key, List<Object> list) {
return redisTemplate.opsForSet().remove(key, list);
}
/**
* 取出两信集合的交集
*
* @param key1 集合1键值
* @param key2 集合2键值
* @return 交集
*/
public Set<Object> setInter(String key1, String key2) {
return redisTemplate.opsForSet().intersect(key1, key2);
}
/**
* 取出多个集合的交集
*
* @param keys 键值列表
* @return 交集
*/
public Set<Object> setInte(List<Object> keys) {
return redisTemplate.opsForSet().intersect(keys);
}
/**
* 取出两个集合的差集
*
* @param key1 集合1键值
* @param key2 集合2键值
* @return 差集
*/
public Set<Object> setDifference(String key1,String key2){
return redisTemplate.opsForSet().difference(key1,key2);
}
}
4.2 客户实体类
/**
* CRM客户信息
*
* @author zhuhuix
* @date 2020-05-04
*/
@Entity
@Getter
@Setter
@Table(name = "customer")
public class Customer implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = Update.class)
private Long id;
@Column(name = "open_id")
private String openId;
/**
* 客户代码
*/
@Column(name = "customer_code")
private String customerCode;
/**
* 客户名称
*/
@Column(name = "customer_name")
private String customerName;
/**
* 首字母
*/
@Column(name = "first_letter")
private String firstLetter;
/**
* 创建时间
*/
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
/**
* 更新时间
*/
@Column(name = "update_time")
@UpdateTimestamp
private Timestamp updateTime;
@Override
public String toString() {
return "Customer{" +
"customerCode='" + customerCode + '\'' +
", customerName='" + customerName + '\'' +
'}';
}
}
4.3 客户信息WebApi
@ApiOperation(value = "通过扫一扫功能上传客户信息")
@PostMapping(value = "/crmScan/{openId}")
public ResponseEntity crmScan(@RequestBody WxScanDto wxScanDto, @PathVariable String openId) {
return ResponseEntity.ok(wxMiniCrm.wxScan(wxScanDto, openId));
}
4.4 记录并缓存客户信息实现类
/**
* 微信小程序CRM实现类
*
* @author zhuhuix
* @date 2020-04-20
* @date 2020-06-17 将最新的上传信息推入Redis队列
* @date 2020-06-22 记录并将客户信息通过Redis集合缓存
*/
@Slf4j
@AllArgsConstructor
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class WxMiniCrmImpl implements WxMiniCrm {
private final UploadFileTool uploadFileTool;
private final CrmIndexRepository crmIndexRepository;
private final CustomerRepository customerRepository;
private final UserService userService;
private final RedisUtils redisUtils;
...
@Override
@Transactional(rollbackFor = Exception.class)
public Result<WxScanDto> wxScan(WxScanDto wxScanDto, String openId) {
//微信扫一扫保存客户信息
if (Constant.SAVE_CUSTOMER_INFO.equals(wxScanDto.getScanType()) && wxScanDto.getJsonObject() != null) {
try {
Customer customer = JSONObject.parseObject(wxScanDto.getJsonObject().toJSONString(), Customer.class);
Customer target = customerRepository.findByCustomerCodeAndOpenId(customer.getCustomerCode(), openId);
if (target != null) {
BeanUtils.copyProperties(customer, target, RepositoryUtil.getNullPropertyNames(customer));
} else {
target = customer;
target.setOpenId(openId);
}
wxScanDto.setReturnObject(customerRepository.save(target));
// 将用户增加的客户信息添加到redis集合中
redisUtils.setAdd(openId.concat("_customer"),customer.toString());
return new Result<WxScanDto>().ok(wxScanDto);
} catch (JSONException ex) {
throw new RuntimeException("json转换失败:" + ex.getMessage());
}
}
return new Result<WxScanDto>().error("无法处理扫一扫功能");
}
}
五、测试与验证
5.1 相同信息自动去重
- swagger2进行接口测试
– 多次提交相同的客户信息 - Redis Desktop Manager验证数据
– 查看集合中的数据,实现自动去重
5.2 不同集合之间的交集与差集
– 用户1通过接口添加4个客户
–用户2通过接口添加3个客户
– 获取用户1与用户2相同及不同的客户信息
/**
* Redis测试
*
* @author zhuhuix
* @date 2020-06-22 set测试
*/
@SpringBootTest
@Slf4j
public class TestSet {
@Test
void test() {
RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class);
//获取交集:相同客户
Set<Object> setInter=redisUtils.setInter("openId1_customer","openId2_customer");
Iterator iterator = setInter.iterator();
log.info("openId1_customer与openId2_customer相同的客户为:");
while(iterator.hasNext()){
log.info(iterator.next().toString());
}
//获取差集:不同客户
Set<Object> setDiff=redisUtils.setDifference("openId1_customer","openId2_customer");
iterator = setDiff.iterator();
log.info("openId1_customer与openId2_customer不同的客户为:");
while(iterator.hasNext()){
log.warn(iterator.next().toString());
}
//获取差集:不同客户
Set<Object> setDiff1=redisUtils.setDifference("openId2_customer","openId1_customer");
iterator = setDiff1.iterator();
log.info("openId2_customer与openId1_customer不同的客户为:");
while(iterator.hasNext()){
log.warn(iterator.next().toString());
}
}
}
- 测试结果
六、源码
Redis项目应用场景与实例(四)后端源码Redis项目应用场景与实例(四)前端源码