dsx %!s(int64=2) %!d(string=hai) anos
pai
achega
bf89366237

+ 1 - 1
src/main/java/com/fdkankan/tracking/entity/TrackingBody.java

@@ -1,4 +1,4 @@
-package com.fdkankan.tracking.entity;
+package com.fdkankan.tracking.bean;
 
 import java.util.Date;
 

+ 31 - 0
src/main/java/com/fdkankan/tracking/config/EsConfig.java

@@ -0,0 +1,31 @@
+package com.fdkankan.tracking.config;
+
+import org.apache.http.HttpHost;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestClientBuilder;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class EsConfig {
+
+    @Value("es.host")
+    private String host;
+    @Value("es.port")
+    private int port;
+    @Value("es.scheme")
+    private String scheme;
+
+    //把方法返回的对象交予spring容器管理
+    @Bean
+    public RestHighLevelClient restHighLevelClient(){
+        HttpHost httpHost=new HttpHost(host,port,scheme);
+        RestClientBuilder restClientBuilder = RestClient.builder(httpHost);
+        RestHighLevelClient restHighLevelClient = new RestHighLevelClient(restClientBuilder);
+        return restHighLevelClient;
+    }
+
+}

+ 38 - 31
src/main/java/com/fdkankan/tracking/controller/TrackingController.java

@@ -1,50 +1,57 @@
 package com.fdkankan.tracking.controller;
 
-import com.alibaba.fastjson.JSONObject;
-import com.fdkankan.tracking.entity.TrackingBody;
-import com.fdkankan.tracking.entity.TrackingEntity;
+import com.fdkankan.tracking.utils.EsUtil;
+import com.fdkankan.tracking.vo.TrackingParamVo;
 import com.fdkankan.tracking.service.TrackingService;
-import com.fdkankan.tracking.utils.IpUtils;
+import com.fdkankan.web.controller.BaseController;
 import com.fdkankan.web.response.ResultData;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import javax.servlet.http.HttpServletRequest;
-import java.util.Date;
+import java.io.IOException;
 
 @RestController
 @RequestMapping("/log")
-public class TrackingController {
-
-    private static final Logger log = LoggerFactory.getLogger(TrackingController.class);
+public class TrackingController extends BaseController {
 
     @Autowired
     private TrackingService trackingService;
+    @Autowired
+    private EsUtil esUtil;
+
+
+//    @RequestMapping("save")
+//    public ResultData saveLog(@RequestBody TrackingEntity entity, HttpServletRequest request){
+//        TrackingBody trackingBody = entity.getPayload();
+//        if(ObjectUtils.isEmpty(trackingBody)){
+//            return ResultData.ok();
+//        }
+//        trackingBody.setUserAgent(request.getHeader("user-agent"));
+//        trackingBody.setUserIP(IpUtils.getIPAddress(request));
+//        trackingBody.setTime(new Date());
+//        if(ObjectUtils.isEmpty(trackingBody.getSource())){
+//            trackingBody.setSource("FRONT");
+//        }
+//        if(!ObjectUtils.isEmpty(trackingBody.getUserIP())){
+//            trackingBody.setUserIpAdress(IpUtils.getUserAddress(trackingBody.getUserIP()));
+//        }
+//        log.info("收到打点请求:{}", JSONObject.toJSONString(entity));
+//        trackingService.save(entity);
+//
+//        return ResultData.ok();
+//    }
+
+    @PostMapping("/save")
+    public ResultData saveLog(@RequestBody TrackingParamVo param) throws IOException {
+        return trackingService.saveLog(param, request);
+    }
 
-
-    @RequestMapping("save")
-    public ResultData saveLog(@RequestBody TrackingEntity entity, HttpServletRequest request){
-        TrackingBody trackingBody = entity.getPayload();
-        if(ObjectUtils.isEmpty(trackingBody)){
-            return ResultData.ok();
-        }
-        trackingBody.setUserAgent(request.getHeader("user-agent"));
-        trackingBody.setUserIP(IpUtils.getIPAddress(request));
-        trackingBody.setTime(new Date());
-        if(ObjectUtils.isEmpty(trackingBody.getSource())){
-            trackingBody.setSource("FRONT");
-        }
-        if(!ObjectUtils.isEmpty(trackingBody.getUserIP())){
-            trackingBody.setUserIpAdress(IpUtils.getUserAddress(trackingBody.getUserIP()));
-        }
-        log.info("收到打点请求:{}", JSONObject.toJSONString(entity));
-        trackingService.save(entity);
-
+    @PostMapping("/createIndex")
+    public ResultData createIndex(String index) throws IOException {
+        esUtil.createIndex(index, null);
         return ResultData.ok();
     }
 

+ 6 - 39
src/main/java/com/fdkankan/tracking/service/TrackingService.java

@@ -1,45 +1,12 @@
 package com.fdkankan.tracking.service;
 
-import com.alibaba.fastjson.JSONObject;
-import com.alibaba.fastjson.serializer.SerializerFeature;
-import com.fdkankan.tracking.entity.TrackingBody;
-import com.fdkankan.tracking.entity.TrackingEntity;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-import org.springframework.web.client.RestTemplate;
+import com.fdkankan.tracking.vo.TrackingParamVo;
+import com.fdkankan.web.response.ResultData;
 
-@Service
-public class TrackingService {
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
 
-    private static final Logger log = LoggerFactory.getLogger(TrackingService.class);
+public interface TrackingService {
 
-    @Value("${es.host:http://120.24.144.164:18201}")
-    private String esHost;
-
-    private RestTemplate restTemplate = new RestTemplate();
-
-    public void save(TrackingEntity entity) {
-        if(entity.getPayload().getUrl().contains("?")){
-            String[] url = entity.getPayload().getUrl().split("\\?");
-            entity.getPayload().setUrl(url[0]);
-            entity.getPayload().setUrlParam(url[1]);
-        }
-        if(entity.getPayload().getReferrer().contains("?")){
-            String[] reffer = entity.getPayload().getReferrer().split("\\?");
-            entity.getPayload().setReferrer(reffer[0]);
-            entity.getPayload().setReferrerParam(reffer[1]);
-        }
-        String url = esHost.concat("/").concat(entity.getType().toLowerCase()).concat("/log?pretty&pretty");
-        log.info("es host:{}", url);
-        try{
-            // value 转换为String 格式
-            TrackingBody trackingBody = JSONObject.parseObject(JSONObject.toJSONString(entity.getPayload(), SerializerFeature.WriteNonStringValueAsString), TrackingBody.class);
-            restTemplate.postForEntity(url, trackingBody, String.class);
-        }catch (Exception e){
-            e.printStackTrace();
-            throw new RuntimeException(e.getMessage());
-        }
-    }
+    ResultData saveLog(TrackingParamVo param, HttpServletRequest request) throws IOException;
 }

+ 87 - 0
src/main/java/com/fdkankan/tracking/service/impl/TrackingServiceImpl.java

@@ -0,0 +1,87 @@
+package com.fdkankan.tracking.service.impl;
+
+import cn.hutool.extra.servlet.ServletUtil;
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.fdkankan.tracking.bean.TrackingBody;
+import com.fdkankan.tracking.utils.EsUtil;
+import com.fdkankan.tracking.vo.TrackingParamVo;
+import com.fdkankan.tracking.service.TrackingService;
+import com.fdkankan.tracking.utils.IpUtils;
+import com.fdkankan.web.response.ResultData;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.client.RestTemplate;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Objects;
+
+@Slf4j
+@Service
+public class TrackingServiceImpl implements TrackingService {
+
+
+//    public void save(TrackingParamVo entity) {
+//        if(entity.getPayload().getUrl().contains("?")){
+//            String[] url = entity.getPayload().getUrl().split("\\?");
+//            entity.getPayload().setUrl(url[0]);
+//            entity.getPayload().setUrlParam(url[1]);
+//        }
+//        if(entity.getPayload().getReferrer().contains("?")){
+//            String[] reffer = entity.getPayload().getReferrer().split("\\?");
+//            entity.getPayload().setReferrer(reffer[0]);
+//            entity.getPayload().setReferrerParam(reffer[1]);
+//        }
+//        String url = esHost.concat("/").concat(entity.getType().toLowerCase()).concat("/log?pretty&pretty");
+//        log.info("es host:{}", url);
+//        try{
+//            // value 转换为String 格式
+//            TrackingBody trackingBody = JSONObject.parseObject(JSONObject.toJSONString(entity.getPayload(), SerializerFeature.WriteNonStringValueAsString), TrackingBody.class);
+//            restTemplate.postForEntity(url, trackingBody, String.class);
+//        }catch (Exception e){
+//            e.printStackTrace();
+//            throw new RuntimeException(e.getMessage());
+//        }
+//    }
+
+    @Autowired
+    private EsUtil esUtil;
+
+
+    @Override
+    public ResultData saveLog(TrackingParamVo param, HttpServletRequest request) throws IOException {
+        TrackingBody trackingBody = param.getPayload();
+        if(ObjectUtils.isEmpty(trackingBody)){
+            return ResultData.ok();
+        }
+        trackingBody.setUserAgent(request.getHeader("user-agent"));
+        trackingBody.setUserIP(ServletUtil.getClientIP(request));
+        trackingBody.setTime(Calendar.getInstance().getTime());
+        trackingBody.setSource("FRONT");
+
+        if(trackingBody.getUrl().contains("?")){
+            String[] url = trackingBody.getUrl().split("\\?");
+            trackingBody.setUrl(url[0]);
+            trackingBody.setUrlParam(url[1]);
+        }
+
+        if(trackingBody.getReferrer().contains("?")){
+            String[] reffer = trackingBody.getReferrer().split("\\?");
+            trackingBody.setReferrer(reffer[0]);
+            trackingBody.setReferrerParam(reffer[1]);
+        }
+
+        String index = trackingBody.getAppId().split("-")[0];
+        esUtil.insert(trackingBody, index, null);
+
+        return ResultData.ok();
+    }
+}

+ 342 - 0
src/main/java/com/fdkankan/tracking/utils/EsUtil.java

@@ -0,0 +1,342 @@
+package com.fdkankan.tracking.utils;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
+import org.elasticsearch.action.delete.DeleteRequest;
+import org.elasticsearch.action.delete.DeleteResponse;
+import org.elasticsearch.action.get.GetRequest;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
+import org.elasticsearch.action.update.UpdateRequest;
+import org.elasticsearch.action.update.UpdateResponse;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.indices.CreateIndexRequest;
+import org.elasticsearch.client.indices.CreateIndexResponse;
+import org.elasticsearch.client.indices.GetIndexRequest;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.text.Text;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
+import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
+import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
+import org.elasticsearch.search.sort.SortOrder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+@Slf4j
+@Component
+public class EsUtil {
+
+    @Autowired
+    private RestHighLevelClient restHighLevelClient;
+
+    /**
+     * 关键字
+     */
+    public static final String KEYWORD = ".keyword";
+
+    /**
+     * 创建索引
+     *
+     * @param index 索引
+     * @return
+     */
+    public boolean createIndex(String index, String mapping) throws IOException {
+        if(isIndexExist(index)){
+            log.error("Index is exits!");
+            return false;
+        }
+        //1.创建索引请求
+        CreateIndexRequest request = new CreateIndexRequest(index);
+        if(StrUtil.isNotBlank(mapping)){
+            request.source(mapping, XContentType.JSON);
+        }
+        //2.执行客户端请求
+        CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
+
+        log.info("创建索引{}成功",index);
+
+        return response.isAcknowledged();
+    }
+
+    /**
+     * 删除索引
+     *
+     * @param index
+     * @return
+     */
+    public boolean deleteIndex(String index) throws IOException {
+        if(!isIndexExist(index)) {
+            log.error("Index is not exits!");
+            return false;
+        }
+        //删除索引请求
+        DeleteIndexRequest request = new DeleteIndexRequest(index);
+        //执行客户端请求
+        AcknowledgedResponse delete = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
+
+        log.info("删除索引{}成功",index);
+
+        return delete.isAcknowledged();
+    }
+
+
+
+    /**
+     * 判断索引是否存在
+     *
+     * @param index
+     * @return
+     */
+    public boolean isIndexExist(String index) throws IOException {
+
+        GetIndexRequest request = new GetIndexRequest(index);
+
+        boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
+
+        return exists;
+    }
+
+
+
+    /**
+     * 数据添加,正定ID
+     *
+     * @param object 要增加的数据  《键值对》
+     * @param index      索引,类似数据库
+     * @param id         数据ID, 为null时es随机生成
+     * @return
+     */
+    public String insert(Object object, String index, String id) throws IOException {
+
+        //创建请求
+        IndexRequest request = new IndexRequest(index);
+        //规则 put /test_index/_doc/1
+        request.id(id);
+        request.timeout(TimeValue.timeValueSeconds(1));
+        //将数据放入请求 json
+        request.source(object, XContentType.JSON);
+        //客户端发送请求
+        IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
+        log.info("添加数据成功 索引为: {}, response 状态: {}, id为: {}",index,response.status().getStatus(), response.getId());
+        return response.getId();
+    }
+
+
+
+    /**
+     * 数据添加 随机id
+     *
+     * @param jsonObject 要增加的数据
+     * @param index      索引,类似数据库
+     * @return
+     */
+    public String insert(Object jsonObject, String index) throws IOException {
+        return insert(jsonObject, index, UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
+    }
+
+    /**
+     * 通过ID删除数据
+     *
+     * @param index 索引,类似数据库
+     * @param id    数据ID
+     */
+    public void deleteDataById(String index, String id) throws IOException {
+        //删除请求
+        DeleteRequest request = new DeleteRequest(index, id);
+        //执行客户端请求
+        DeleteResponse delete = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
+        log.info("索引为: {}, id为: {}删除数据成功",index, id);
+    }
+
+
+    /**
+     * 通过ID 更新数据
+     *
+     * @param object     要增加的数据
+     * @param index      索引,类似数据库
+     * @param id         数据ID
+     * @return
+     */
+    public void updateDataById(Object object, String index, String id) throws IOException {
+        //更新请求
+        UpdateRequest update = new UpdateRequest(index, id);
+
+        update.timeout("1s");
+        update.doc(JSON.toJSONString(object), XContentType.JSON);
+        //执行更新请求
+        UpdateResponse update1 = restHighLevelClient.update(update, RequestOptions.DEFAULT);
+        log.info("索引为: {}, id为: {}, 更新数据成功",index, id);
+    }
+
+
+    /**
+     * 通过ID 更新数据,保证实时性
+     *
+     * @param object     要增加的数据
+     * @param index      索引,类似数据库
+     * @param id         数据ID
+     * @return
+     */
+    public void updateDataByIdNoRealTime(Object object, String index, String id) throws IOException {
+        //更新请求
+        UpdateRequest update = new UpdateRequest(index, id);
+
+        //保证数据实时更新
+        update.setRefreshPolicy("wait_for");
+
+        update.timeout("1s");
+        update.doc(JSON.toJSONString(object), XContentType.JSON);
+        //执行更新请求
+        UpdateResponse response = restHighLevelClient.update(update, RequestOptions.DEFAULT);
+        log.info("索引为: {}, id为: {}, 更新数据成功",index, id);
+    }
+
+
+    /**
+     * 通过ID获取数据
+     *
+     * @param index  索引,类似数据库
+     * @param id     数据ID
+     * @param fields 需要显示的字段,逗号分隔(缺省为全部字段)
+     * @return
+     */
+    public Map<String,Object> searchDataById(String index, String id, String[] fields) throws IOException {
+        GetRequest request = new GetRequest(index, id);
+        if (fields != null && fields.length > 0){
+            //只查询特定字段。如果需要查询所有字段则不设置该项。
+            request.fetchSourceContext(new FetchSourceContext(true,fields, Strings.EMPTY_ARRAY));
+        }
+        GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
+        Map<String, Object> map = response.getSource();
+        //为返回的数据添加id
+        map.put("id",response.getId());
+        return map;
+    }
+
+    /**
+     * 通过ID判断文档是否存在
+     * @param index  索引,类似数据库
+     * @param id     数据ID
+     * @return
+     */
+    public  boolean existsById(String index,String id) throws IOException {
+        GetRequest request = new GetRequest(index, id);
+        //不获取返回的_source的上下文
+        request.fetchSourceContext(new FetchSourceContext(false));
+        request.storedFields("_none_");
+        return restHighLevelClient.exists(request, RequestOptions.DEFAULT);
+    }
+
+    /**
+     * 获取低水平客户端
+     * @return
+     */
+    public RestClient getLowLevelClient() {
+        return restHighLevelClient.getLowLevelClient();
+    }
+
+
+    /**
+     * 高亮结果集 特殊处理
+     * map转对象 JSONObject.parseObject(JSONObject.toJSONString(map), Content.class)
+     * @param searchResponse
+     * @param highlightField
+     */
+    public List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse, String highlightField) {
+        //解析结果
+        List<Map<String,Object>> list = new ArrayList<>();
+        for (SearchHit hit : searchResponse.getHits().getHits()) {
+            Map<String, HighlightField> high = hit.getHighlightFields();
+            HighlightField title = high.get(highlightField);
+
+            hit.getSourceAsMap().put("id", hit.getId());
+
+            //原来的结果
+            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
+            //解析高亮字段,将原来的字段换为高亮字段
+            if (title!=null){
+                Text[] texts = title.fragments();
+                String nTitle="";
+                for (Text text : texts) {
+                    nTitle+=text;
+                }
+                //替换
+                sourceAsMap.put(highlightField,nTitle);
+            }
+            list.add(sourceAsMap);
+        }
+        return list;
+    }
+
+
+    /**
+     * 查询并分页
+     * @param index          索引名称
+     * @param query          查询条件
+     * @param size           文档大小限制
+     * @param from           从第几页开始
+     * @param fields         需要显示的字段,逗号分隔(缺省为全部字段)
+     * @param sortField      排序字段
+     * @param highlightField 高亮字段
+     * @return
+     */
+    public List<Map<String, Object>> searchListData(String index,
+                                                    SearchSourceBuilder query,
+                                                    Integer size,
+                                                    Integer from,
+                                                    String[] fields,
+                                                    String sortField,
+                                                    String highlightField) throws IOException {
+        SearchRequest request = new SearchRequest(index);
+        SearchSourceBuilder builder = query;
+        if (fields != null && fields.length > 0){
+            //只查询特定字段。如果需要查询所有字段则不设置该项。
+            builder.fetchSource(new FetchSourceContext(true,fields, Strings.EMPTY_ARRAY));
+        }
+        from = from <= 0 ? 0 : from*size;
+        //设置确定结果要从哪个索引开始搜索的from选项,默认为0
+        builder.from(from);
+        builder.size(size);
+        if (StrUtil.isNotBlank(sortField)){
+            //排序字段,注意如果proposal_no是text类型会默认带有keyword性质,需要拼接.keyword
+            builder.sort(sortField+".keyword", SortOrder.ASC);
+        }
+        //高亮
+        HighlightBuilder highlight = new HighlightBuilder();
+        highlight.field(highlightField);
+        //关闭多个高亮
+        highlight.requireFieldMatch(false);
+        highlight.preTags("<span style='color:red'>");
+        highlight.postTags("</span>");
+        builder.highlighter(highlight);
+        //不返回源数据。只有条数之类的数据。
+        //builder.fetchSource(false);
+        request.source(builder);
+        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
+        log.error("=="+response.getHits().getTotalHits());
+        if (response.status().getStatus() == 200) {
+            // 解析对象
+            return setSearchResponse(response, highlightField);
+        }
+        return null;
+    }
+
+}

+ 4 - 2
src/main/java/com/fdkankan/tracking/entity/TrackingEntity.java

@@ -1,6 +1,8 @@
-package com.fdkankan.tracking.entity;
+package com.fdkankan.tracking.vo;
 
-public class TrackingEntity {
+import com.fdkankan.tracking.bean.TrackingBody;
+
+public class TrackingParamVo {
     /**
      * 打点类型
      */