feat: 用户商品浏览历史

用redis zset实现的最近十条记录(高并发时可能会有误差),满足我目前的需求了。想要京东淘宝那样丰富的可能需要借助es。
This commit is contained in:
Gadfly 2021-08-11 18:07:13 +08:00
parent 85c386c2a7
commit 654a1cfe56
10 changed files with 126 additions and 3 deletions

View File

@ -0,0 +1,20 @@
package com.youlai.mall.pms.pojo.vo;
import lombok.Data;
import java.io.Serializable;
/**
* @author Gadfly
* @since 2021-08-10 15:44
*/
@Data
public class ProductHistoryVO implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private String pic;
}

View File

@ -110,6 +110,12 @@
<groupId>com.youlai</groupId>
<artifactId>common-rabbitmq</artifactId>
</dependency>
<dependency>
<groupId>com.youlai</groupId>
<artifactId>ums-api</artifactId>
<version>2.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@ -1,13 +1,16 @@
package com.youlai.mall.pms;
import com.youlai.mall.ums.api.MemberFeignClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableDiscoveryClient
@EnableFeignClients(basePackageClasses = {MemberFeignClient.class})
@EnableTransactionManagement
public class PmsApplication {
public static void main(String[] args) {

View File

@ -14,10 +14,12 @@ import com.youlai.mall.pms.pojo.entity.PmsSku;
import com.youlai.mall.pms.pojo.entity.PmsSpec;
import com.youlai.mall.pms.pojo.entity.PmsSpu;
import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue;
import com.youlai.mall.pms.pojo.vo.ProductHistoryVO;
import com.youlai.mall.pms.service.IPmsSkuService;
import com.youlai.mall.pms.service.IPmsSpecService;
import com.youlai.mall.pms.service.IPmsSpuAttributeValueService;
import com.youlai.mall.pms.service.IProductService;
import com.youlai.mall.ums.api.MemberFeignClient;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
@ -44,6 +46,7 @@ public class ProductServiceImpl extends ServiceImpl<PmsSpuMapper, PmsSpu> implem
private final RedisUtils redisUtils;
private final RedissonClient redissonClient;
private final ProductLocalCache productLocalCache;
private final MemberFeignClient memberFeignClient;
@Override
@ -52,12 +55,18 @@ public class ProductServiceImpl extends ServiceImpl<PmsSpuMapper, PmsSpu> implem
ProductFormDTO product = productLocalCache.get(PRODUCT_DETAIL_CACHE + spuId);
if (null != product) {
log.info("get LocalCache product:" + product);
ProductHistoryVO vo = new ProductHistoryVO();
BeanUtil.copyProperties(product.getSpu(), vo);
memberFeignClient.addProductViewHistory(vo);
return product;
}
//2二级缓存设置Redis中获取商品详情信息
product = (ProductFormDTO) redisUtils.get(PRODUCT_DETAIL_CACHE + spuId);
if (null != product) {
log.info("get redis product:" + product);
ProductHistoryVO vo = new ProductHistoryVO();
BeanUtil.copyProperties(product.getSpu(), vo);
memberFeignClient.addProductViewHistory(vo);
return product;
}
//3分布式锁保证原子操作
@ -102,6 +111,9 @@ public class ProductServiceImpl extends ServiceImpl<PmsSpuMapper, PmsSpu> implem
}
}
}
ProductHistoryVO vo = new ProductHistoryVO();
BeanUtil.copyProperties(product.getSpu(), vo);
memberFeignClient.addProductViewHistory(vo);
return product;
}
}

View File

@ -34,5 +34,11 @@
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-micro-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.youlai</groupId>
<artifactId>pms-api</artifactId>
<version>2.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,19 +1,20 @@
package com.youlai.mall.ums.api;
import com.youlai.common.result.Result;
import com.youlai.mall.ums.pojo.entity.UmsMember;
import com.youlai.mall.pms.pojo.vo.ProductHistoryVO;
import com.youlai.mall.ums.pojo.dto.MemberDTO;
import com.youlai.mall.ums.pojo.entity.UmsMember;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
@FeignClient(name = "mall-ums",contextId = "member")
@FeignClient(name = "mall-ums", contextId = "member")
public interface MemberFeignClient {
@PostMapping("/app-api/v1/members")
Result<Long> add(@RequestBody UmsMember member);
@PutMapping("/app-api/v1/members/{id}")
<T> Result<T> update(@PathVariable Long id,@RequestBody UmsMember member);
<T> Result<T> update(@PathVariable Long id, @RequestBody UmsMember member);
/**
* 获取会员信息
@ -50,6 +51,12 @@ public interface MemberFeignClient {
*/
@GetMapping("/app-api/v1/members/{id}/balance")
Result<Long> getBalance(@PathVariable Long id);
/**
* 添加浏览记录
*/
@PostMapping("/app-api/v1/members/view/history")
<T> Result<T> addProductViewHistory(@RequestBody ProductHistoryVO product);
}

View File

@ -0,0 +1,9 @@
package com.youlai.mall.ums.constant;
/**
* @author Gadfly
* @since 2021-08-10 12:12
*/
public interface UmsConstants {
String USER_PRODUCT_HISTORY = "user:product:history:";
}

View File

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.youlai.common.result.Result;
import com.youlai.common.result.ResultCode;
import com.youlai.common.web.util.JwtUtils;
import com.youlai.mall.pms.pojo.vo.ProductHistoryVO;
import com.youlai.mall.ums.pojo.entity.UmsMember;
import com.youlai.mall.ums.pojo.dto.MemberDTO;
import com.youlai.mall.ums.service.IUmsMemberService;
@ -17,6 +18,9 @@ import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.Collections;
import java.util.Set;
@Api(tags = "【移动端】会员服务")
@RestController
@RequestMapping("/app-api/v1/members")
@ -143,4 +147,29 @@ public class MemberController {
}
return Result.success(balance);
}
@ApiOperation(value = "添加浏览历史")
@PostMapping("/view/history")
public <T> Result<T> addProductViewHistory(@RequestBody ProductHistoryVO product) {
Long userId = null;
try {
userId = JwtUtils.getUserId();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
iUmsMemberService.addProductViewHistory(product, userId);
return Result.success();
}
@ApiOperation(value = "获取浏览历史")
@GetMapping("/view/history")
public Result<Set<ProductHistoryVO>> getProductViewHistory() {
try {
Long userId = JwtUtils.getUserId();
Set<ProductHistoryVO> historyList = iUmsMemberService.getProductViewHistory(userId);
return Result.success(historyList);
} catch (Exception e) {
return Result.success(Collections.emptySet());
}
}
}

View File

@ -4,9 +4,16 @@ package com.youlai.mall.ums.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.youlai.mall.pms.pojo.vo.ProductHistoryVO;
import com.youlai.mall.ums.pojo.entity.UmsMember;
import java.util.Set;
public interface IUmsMemberService extends IService<UmsMember> {
IPage<UmsMember> list(Page<UmsMember> page, UmsMember user);
void addProductViewHistory(ProductHistoryVO product, Long userId);
Set<ProductHistoryVO> getProductViewHistory(Long userId);
}

View File

@ -3,16 +3,23 @@ package com.youlai.mall.ums.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.mall.pms.pojo.vo.ProductHistoryVO;
import com.youlai.mall.ums.constant.UmsConstants;
import com.youlai.mall.ums.pojo.entity.UmsMember;
import com.youlai.mall.ums.mapper.UmsUserMapper;
import com.youlai.mall.ums.service.IUmsMemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Set;
@Service
@RequiredArgsConstructor
public class UmsMemberServiceImpl extends ServiceImpl<UmsUserMapper, UmsMember> implements IUmsMemberService {
private final RedisTemplate redisTemplate;
@Override
public IPage<UmsMember> list(Page<UmsMember> page, UmsMember spu) {
@ -20,4 +27,21 @@ public class UmsMemberServiceImpl extends ServiceImpl<UmsUserMapper, UmsMember>
page.setRecords(list);
return page;
}
@Override
public void addProductViewHistory(ProductHistoryVO product, Long userId) {
if (userId != null) {
String key = UmsConstants.USER_PRODUCT_HISTORY + userId;
redisTemplate.opsForZSet().add(key, product, System.currentTimeMillis());
Long size = redisTemplate.opsForZSet().size(key);
if (size > 10) {
redisTemplate.opsForZSet().removeRange(key, 0, size - 11);
}
}
}
@Override
public Set<ProductHistoryVO> getProductViewHistory(Long userId) {
return redisTemplate.opsForZSet().reverseRange(UmsConstants.USER_PRODUCT_HISTORY + userId, 0, 9);
}
}