code搜索

48 阅读2分钟
### app网关添加路由配置

首先需要在app的网关中添加搜索微服务的路由配置
#搜索微服务
  - id: leadnews-search
    uri: lb://leadnews-search
    predicates:
    - Path=/search/**
    filters:
    - StripPrefix= 1
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>   
  加入redis的配置
  spring:
      redis:
        host: 192.168.137.136
### 配置拦截器
package com.heima.search.interceptors;

import com.heima.common.threadlocal.UserThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
public class UserInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //得到header中的信息
        String userId = request.getHeader("userId");
        if(StringUtils.isNotBlank(userId)){
            //把用户id存入threadloacl中
            UserThreadLocalUtils.setUserId(Integer.valueOf(userId));
            log.info("UserInterceptor设置用户信息到threadlocal中...");
        }

        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("清理threadlocal...");
        UserThreadLocalUtils.removeUser();
    }
} 
  
@RestController
public class MySearchContoller {

    @Autowired
    private MySearchService mySearchService;

    /**
     * 关键词搜索
     * @param dto
     * @return
     */
    @PostMapping("/api/v1/article/search/search")
    public ResponseResult<List<ArticleDto>> search(@RequestBody UserSearchDto dto){
        return ResponseResult.ok(mySearchService.search(dto));
    }
} 

```js
@Slf4j
@Service
public class MySearchServiceImpl implements MySearchService {

    @Autowired
    private RestHighLevelClient highLevelClient;

    private String indexName = "app_info_article"; 
    @Override
    public List<ArticleDto> search(UserSearchDto dto) {

        String searchWords = dto.getSearchWords();
        if(StringUtils.isBlank(searchWords)){
            log.error("没有关键词");
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID);
        }
//        封装搜索请求
        SearchRequest searchRequest = new SearchRequest(indexName); 
//        必须包含关键词搜索
searchWords "title"  content  labels  id 多个字段  
//         分页  时间 排序    
//        关键搜索,把请求发给es服务端
        try {
            SearchResponse response = highLevelClient.search(searchRequest, RequestOptions.DEFAULT); 
            List<ArticleDto> list = new ArrayList<>();
            SearchHits hits = response.getHits();  
//         如果有搜索的结果,业务解耦,异步操作 。需要保存搜索记录
           Integer userId = UserThreadLocalUtils.getUserId();
           redisService.saveSearchWord(searchWords,userId,dto.getEquipmentId());
           return list; 
        } catch (IOException e) {
            log.error("es搜索异常");
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
    }
} 
启动类 @Async
搜索结果保存 
package com.heima.search.service;

import java.util.Set;

public interface RedisService {
    /**
     * 保存用户搜索记录
     * @param searchWords
     * @param userId
     * @param equipmentId
     */
    void saveSearchWord(String searchWords, Integer userId, String equipmentId);

    /**
     * 获取搜索记录
     * @param userId
     * @param equipmentId
     * @return
     */
    Set<String> getSearchWord(Integer userId, String equipmentId); 
 
}  
package com.heima.search.service.impl;

import com.heima.search.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Set;

@Slf4j
@Service
public class RedisServiceImpl implements RedisService {

    @Autowired
    private StringRedisTemplate redisTemplate;
    不用 redisTemplate数据太冗余

    private String PRE_FIX = "ld:search:word:";
    /**
     * 异步解耦
     * 保存用户搜索记录
     * @param searchWords
     * @param userId
     * @param equipmentId
     */
    @Async("taskExecutor") //标记当前方法是异步执行方法---threadpoolconfig
    @Override
    public void saveSearchWord(String searchWords, Integer userId, String equipmentId) {

        String key = getKey(userId,equipmentId);
//        把用户搜索记录放入redis的zset结构
        redisTemplate.opsForZSet().incrementScore(key,searchWords,1数量);
    }

    @Override
    public Set<String> getSearchWord(Integer userId, String equipmentId) {

        String key = getKey(userId, equipmentId);

        Set<String> set = redisTemplate.opsForZSet().reverseRange(key, start0, end-1);//倒序

        return set;
    }

    @Override
    public void delSearchWord(Integer userId, String equipmentId, String searchWords) {
        String key = getKey(userId,equipmentId);

        redisTemplate.opsForZSet().remove(key,searchWords);
    }

    /**
     * 如果userId有正常的值,优先使用userId
     * @param userId
     * @param equipmentId
     * @return
     */
    private String getKey(Integer userId, String equipmentId) {

        if(userId != null && userId != 0){
            return PRE_FIX + userId;
        }
        return PRE_FIX+equipmentId;
    }
} 

image.png