一、控制层
package com.xxx.webapi.knowledgebase;
import com.xxx.service.HotMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.*;
/**
* @author nick
*/
@RestController
@RequestMapping("/hot-ten")
@Slf4j
public class HotMessageController {
@Resource
private HotMessageService hotMessageService;
/**
* 添加数据
*/
@PostMapping
public String redisAdd(@PathVariable("tenantId") String tenantId,
@RequestParam(required = false) String message) {
hotMessageService.addTop(message,tenantId);
return CommonResponse.success();
}
/**
* 根据key搜索相关最热的前十名
*/
@GetMapping
public List<String> redisGet(@PathVariable("tenantId") String tenantId) {
Map<String, Object> params = new HashMap<>(1);
params.put("tenantId",tenantId);
return hotMessageService.getTopList(params);
}
/**
* 热点问题计数
*/
@PutMapping
public String incrementScore(@PathVariable("tenantId") String tenantId,
@RequestBody Map<String, Object> params) {
params.put("tenantId",tenantId);
hotMessageService.incrementScore(params);
return "ok";
}
}
二、接口层
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
/**
* @author nick
*/
@Service
@Slf4j
public class HotMessageService {
@Resource
private RedisTemplate redisTemplate;
/**
* 添加数据 通过租户ID进行区分
* @param message 回答问题
* @param tenantId 租户ID
*/
public void addTop(String message, String tenantId){
//预处理数据
if (StringUtils.isNotBlank(message)) {
//去除标点等特殊词
String author = message.replaceAll("\\﹝.*?\\﹞|\\〔.*?\\〕|\\(.*?\\)|\\{.*?}|\\[.*?]|\\[.*?]|\\【.*?】|(.*?)|等|著|编者|主编|[^0-9a-zA-Z\u4e00-\u9fa5.,,•·《 》]", "").trim();
message = author.replaceAll("\\s+", " ").trim();
//去除html标签
Jsoup.clean(message, Whitelist.none());
//用租户ID进行 添加到redis数据中
Long now = System.currentTimeMillis();
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
ValueOperations<String, Long> valueOperations = redisTemplate.opsForValue();
//转list类型
List<String> title = Arrays.asList(message);
for (int i = 0, lends = title.size(); i < lends; i++) {
String tle = title.get(i);
try {
if (zSetOperations.score(tenantId, tle) <= 0) {
zSetOperations.add(tenantId, tle, 0);
valueOperations.set(tle, now);
}
} catch (Exception e) {
zSetOperations.add(tenantId, tle, 0);
valueOperations.set(tle, now);
}
}
}
}
/**
*根据key搜索相关最热的前十名
* tenantId 标识租户ID
* key 表示内容
*/
public List<String> getTopList(Map<String, Object> params){
//String key = params.get("key").toString();
String vacs = params.get("tenantId").toString();
Long now = System.currentTimeMillis();
List<String> result = new ArrayList<>();
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
ValueOperations<String, Long> valueOperations = redisTemplate.opsForValue();
Set<String> value = zSetOperations.reverseRangeByScore(vacs, 0, Double.MAX_VALUE);
//key不为空的时候 推荐相关的最热前十名
for (String val : value) {
//if (StringUtils.containsIgnoreCase(val, key)) {}
//只返回最热的前十名
if (result.size() > 9) {
break;
}
//返回最近一个月的数据
Long time = valueOperations.get(val);
if ((now - time) < 2592000000L) {
result.add(val);
} else {
//时间超过一个月没搜索就把这个词热度归0
zSetOperations.add(vacs, val, 0);
}
}
return result;
}
/**
* 每次点击给相关词热度 +1
* @param params
* key 标识问题
* tenantId 标识租户ID
*/
public void incrementScore(Map<String, Object> params){
String key = params.get("key").toString();
String vacs = params.get("tenantId").toString();
Long now = System.currentTimeMillis();
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
ValueOperations<String, Long> valueOperations = redisTemplate.opsForValue();
zSetOperations.incrementScore(vacs, key, 1);
valueOperations.getAndSet(key, now);
}
}
优化:
@Service
@Slf4j
public class HotMessageService {
@Resource
private RedisTemplate redisTemplate;
/**
* 添加数据 通过租户ID进行区分
*
* @param message 回答问题
* @param tenantId 租户ID
*/
public void addTop(String message, String tenantId) {
// 预处理数据
if (!StringUtils.isEmpty(message)) {
//去除标点等特殊词
String author = message.replaceAll("\\﹝.*?\\﹞|\\〔.*?\\〕|\\(.*?\\)|\\{.*?}|\\[.*?]|\\[.*?]|\\【.*?】|(.*?)|等|著|编者|主编|[^0-9a-zA-Z\u4e00-\u9fa5.,,•·《 》]", "").trim();
message = author.replaceAll("\\s+", " ").trim();
//去除html标签
Jsoup.clean(message, Whitelist.none());
//用租户ID进行 添加到redis数据中
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
String key = "top_".concat(tenantId);
//转list类型
List<String> title = Arrays.asList(message);
for (int i = 0, lends = title.size(); i < lends; i++) {
String tle = title.get(i);
try {
if (zSetOperations.score(tenantId, tle) <= 0) {
redisTemplate.opsForHash().put(key, tle, System.currentTimeMillis());
}
} catch (Exception e) {
zSetOperations.add(tenantId, tle, 0);
redisTemplate.opsForHash().put(key, tle, System.currentTimeMillis());
}
}
}
}
/**
* 根据key搜索相关最热的前十名
* tenantId 标识租户ID
* key 表示内容
*/
public List<String> getTopList(Map<String, Object> params) {
String tenantId = params.get("tenantId").toString();
Long now = System.currentTimeMillis();
List<String> result = new ArrayList<>();
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
String key = "top_".concat(tenantId);
Set<String> value = zSetOperations.reverseRangeByScore(tenantId, 0, Double.MAX_VALUE);
//key不为空的时候 推荐相关的最热前十名
for (String val : value) {
//只返回最热的前十名
if (result.size() > 9) {
break;
}
Object time = redisTemplate.opsForHash().get(key, val);
if (!StringUtils.isEmpty(time)) {
//返回最近一个月的数据
if ((now - Long.parseLong(String.valueOf(time))) < 2592000000L) {
result.add(val);
} else {
//时间超过一个月没搜索就把这个词热度归0
zSetOperations.add(tenantId, val, 0);
}
}
}
return result;
}
/**
* 每次点击给相关词热度 +1
*
* @param params key 标识问题
* tenantId 标识租户ID
*/
public void incrementScore(Map<String, Object> params) {
String key = params.get("key").toString();
String vacs = params.get("tenantId").toString();
Long now = System.currentTimeMillis();
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
ValueOperations<String, Long> valueOperations = redisTemplate.opsForValue();
zSetOperations.incrementScore(vacs, key, 1);
valueOperations.getAndSet(key, now);
}
}
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>