redis+springboot实现TOP10排行榜

一、控制层

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>

参考:https://blog.csdn.net/wangh92/category_6969732.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值