parent
f5ed96dca8
commit
dae3c5b24a
@ -0,0 +1,139 @@ |
|||||||
|
package com.keyware.shandan.browser; |
||||||
|
|
||||||
|
import cn.hutool.core.date.DateField; |
||||||
|
import cn.hutool.core.date.DateTime; |
||||||
|
import cn.hutool.core.date.DateUtil; |
||||||
|
import cn.hutool.json.JSONUtil; |
||||||
|
import com.alibaba.fastjson.JSONArray; |
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||||
|
import com.keyware.shandan.common.util.StringUtils; |
||||||
|
import com.keyware.shandan.system.entity.SysOperateLog; |
||||||
|
import com.keyware.shandan.system.service.SysOperateLogService; |
||||||
|
import com.keyware.shandan.system.utils.DictUtil; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* 用于处理分析系统热词和用户搜索历史 |
||||||
|
*/ |
||||||
|
@Slf4j |
||||||
|
@Component |
||||||
|
public class SearchLogProcessor extends Thread { |
||||||
|
private final SysOperateLogService logService; |
||||||
|
private int cycle = 7; |
||||||
|
private DateField unit = DateField.DAY_OF_MONTH; |
||||||
|
private final Map<String, Integer> systemWords = new HashMap<>(); |
||||||
|
|
||||||
|
public SearchLogProcessor(SysOperateLogService logService) { |
||||||
|
this.logService = logService; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
log.info("搜索日志处理程序启动成功"); |
||||||
|
while (true) { |
||||||
|
parseConfig(); |
||||||
|
systemWords.clear(); |
||||||
|
LambdaQueryWrapper<SysOperateLog> query = new LambdaQueryWrapper<>(); |
||||||
|
DateTime date = DateUtil.offset(new Date(), unit, cycle); |
||||||
|
query.gt(SysOperateLog::getOperateTime, date.toJdkDate()); |
||||||
|
logService.list(query).forEach(logs -> { |
||||||
|
String word = parseLogs(logs); |
||||||
|
if (StringUtils.hasText(word)) { |
||||||
|
addSystemWords(word); |
||||||
|
} |
||||||
|
}); |
||||||
|
try { |
||||||
|
Thread.sleep(1000 * 60 * 30); |
||||||
|
} catch (InterruptedException ignore) { |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取用户的搜索历史 |
||||||
|
* |
||||||
|
* @param loginName |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public List<String> getUserSearchHistory(String loginName) { |
||||||
|
List<String> searchHistory = new ArrayList<>(); |
||||||
|
LambdaQueryWrapper<SysOperateLog> query = new LambdaQueryWrapper<>(); |
||||||
|
query.eq(SysOperateLog::getLoginName, loginName).orderByDesc(SysOperateLog::getOperateTime).last("limit 30"); |
||||||
|
for (SysOperateLog logs : logService.list(query)) { |
||||||
|
String word = parseLogs(logs); |
||||||
|
if (StringUtils.hasText(word) && !searchHistory.contains(word)) { |
||||||
|
searchHistory.add(word); |
||||||
|
} |
||||||
|
} |
||||||
|
return searchHistory; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取系统级热词 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public List<String> getSystemWords() { |
||||||
|
return systemWords |
||||||
|
.entrySet() |
||||||
|
.stream() |
||||||
|
//.sorted(Comparator.comparingInt(Map.Entry::getValue))
|
||||||
|
.sorted((a, b) -> b.getValue() - a.getValue()) |
||||||
|
.map(Map.Entry::getKey) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private String parseLogs(SysOperateLog logs) { |
||||||
|
String value = null; |
||||||
|
String url = logs.getUrl(); |
||||||
|
if (url.startsWith("/browser/search/")) { |
||||||
|
String paramsText = logs.getParams(); |
||||||
|
if (JSONUtil.isJsonArray(logs.getParams())) { |
||||||
|
for (Object object : JSONArray.parseArray(paramsText)) { |
||||||
|
JSONObject json = (JSONObject) object; |
||||||
|
String fieldName = json.getString("fieldName"); |
||||||
|
if ("metadataName".equals(fieldName)) { |
||||||
|
value = json.getString("fieldValue"); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
JSONObject json = JSONObject.parseObject(paramsText); |
||||||
|
if (json.containsKey("search")) { |
||||||
|
value = json.getString("search"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
private void addSystemWords(String word) { |
||||||
|
Integer count = systemWords.get(word); |
||||||
|
count = count == null ? 0 : count; |
||||||
|
systemWords.put(word, ++count); |
||||||
|
} |
||||||
|
|
||||||
|
private void parseConfig() { |
||||||
|
String systemWordsConfig = DictUtil.getPublicDict("browser_system_words_config"); |
||||||
|
if (StringUtils.hasText(systemWordsConfig)) { |
||||||
|
systemWordsConfig = systemWordsConfig.toLowerCase(); |
||||||
|
if (systemWordsConfig.endsWith("d")) { |
||||||
|
cycle = -Math.abs(Integer.parseInt(systemWordsConfig.replace("d", ""))); |
||||||
|
unit = DateField.DAY_OF_YEAR; |
||||||
|
} else if (systemWordsConfig.endsWith("m")) { |
||||||
|
cycle = -Math.abs(Integer.parseInt(systemWordsConfig.replace("m", ""))); |
||||||
|
unit = DateField.MONTH; |
||||||
|
} else if (systemWordsConfig.endsWith("y")) { |
||||||
|
cycle = -Math.abs(Integer.parseInt(systemWordsConfig.replace("y", ""))); |
||||||
|
unit = DateField.YEAR; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package com.keyware.shandan.browser.controller; |
||||||
|
|
||||||
|
import com.keyware.shandan.browser.SearchLogProcessor; |
||||||
|
import com.keyware.shandan.common.entity.Result; |
||||||
|
import com.keyware.shandan.frame.config.security.SecurityUtil; |
||||||
|
import org.springframework.security.core.Authentication; |
||||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||||
|
import org.springframework.web.bind.annotation.RestController; |
||||||
|
|
||||||
|
/** |
||||||
|
* 搜索建议前端控制器 |
||||||
|
*/ |
||||||
|
@RestController |
||||||
|
@RequestMapping("/search/suggest") |
||||||
|
public class SearchSuggestController { |
||||||
|
|
||||||
|
private final SearchLogProcessor logProcessor; |
||||||
|
|
||||||
|
public SearchSuggestController(SearchLogProcessor logProcessor) { |
||||||
|
this.logProcessor = logProcessor; |
||||||
|
} |
||||||
|
|
||||||
|
@GetMapping("/user/history") |
||||||
|
public Result<Object> getUserHistory() { |
||||||
|
String loginName = SecurityUtil.getLoginUsername(); |
||||||
|
return Result.of(logProcessor.getUserSearchHistory(loginName)); |
||||||
|
} |
||||||
|
|
||||||
|
@GetMapping("/system/words") |
||||||
|
public Result<Object> getSystemWords() { |
||||||
|
return Result.of(logProcessor.getSystemWords()); |
||||||
|
} |
||||||
|
} |
Reference in new issue