java B2B2C多用户商城系统

Wesley13
• 阅读 864

需求分析:

在javashop电商系统中,商品数据是存在elasticsearch中,使用ik分词器分词,ik分词器的词库内置了2万多个。

但在实际运维过程中,因为商品的个性化,词库不一定可以满足,为了搜索引擎分词(关键词)更加准确,要求可对分词词库进行手工维护。

思路:

IK自定义词库是支持远程热加载的。

先看下官方的说明:

remote_ext_dict:

1.该 http 请求需要返回两个头部(header),一个是 Last-Modified,一个是 ETag,这两者都是字符串类型,只要有一个发生变化,该插件就会去抓取新的分词进而更新词库。

2.该 http 请求返回的内容格式是一行一个分词,换行符用 \n 即可。

满足上面两点要求就可以实现热更新分词了,不需要重启 ES 实例。

由此,我们可以开放一个API供IK调用。

搜索分词(关键词)架构思路

1.管理端对关键词进行维护;

2.管理端设置秘钥(此秘钥仅做加载分词API验证使用);

3.管理端展示分词列表,根据最后修改时间倒序展示。

时序图:

java B2B2C多用户商城系统

数据结构:

关键词表(es_custom_words):

字段名

提示文字

类型

长度

是否主键

id

id

int

10

name

关键词

字符串

100

add_time

添加时间

长整型

20

modify_time

最后修改时间

长整型

20

disabled

是否可用:可用:1 ;隐藏: 0

整形

1

秘钥设置说明: 在系统设置表(es_setting)中新增分组(ES_SIGN),对秘钥进行维护时修改此分组下的数据。

领域模型

管理端

管理端添加搜索设置菜单,对关键词进行维护

java B2B2C多用户商城系统

模型

**属性 **

说明

备注

id

id

name

分词名称必填

addTime

添加时间

disabled

是否可用

可用:1;不可用:0

modifyTime

修改时间

ES加载词库API

在基础API中添加加载词库API,此Api需要校验秘钥,失败返回空字符串,成功则从数据库中加载数据并返回。

IK Analyzer 扩展配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
        <comment>IK Analyzer 扩展配置</comment>
        <!--用户可以在这里配置远程扩展字典 -->
        <entry key="remote_ext_dict">http://base-api-domain/load-customwords?secret_key=secret_value</entry>
</properties>

其中secret_value可以随意设置,此处配置的值,需要在管理端搜索分词列表处保存

base-api-domain改为自己的base-api域名或者IP:端口即可

源码

说明:此处仅展示IK加载片段代码,关于管理分此维护相关不做展示

CustomWordsBaseController

package com.enation.app.javashop.base.api;

import com.enation.app.javashop.core.base.SettingGroup;
import com.enation.app.javashop.core.client.system.SettingClient;
import com.enation.app.javashop.core.goods.GoodsErrorCode;
import com.enation.app.javashop.core.goodssearch.model.EsSecretSetting;
import com.enation.app.javashop.core.goodssearch.service.CustomWordsManager;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.util.JsonUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

/**
 * 自定义分词控制器
 *
 * @author liuyulei
 * @version v1.0
 * @since v7.0.0
 * 2019-05-26
 */
@RestController
@RequestMapping("/load-customwords")
@Api(description = "加载分词库")
public class CustomWordsBaseController {

    @Autowired
    private CustomWordsManager customWordsManager;
    @Autowired
    private SettingClient settingClient;

    @GetMapping
    @ApiImplicitParams({
            @ApiImplicitParam(name = "secret_key", value = "秘钥", required = true, dataType = "String", paramType = "query")

    })
    public String getCustomWords(@ApiIgnore  String secretKey){

        if(StringUtil.isEmpty(secretKey)){
            return "";
        }
        String value = settingClient.get(SettingGroup.ES_SIGN);
        if(StringUtil.isEmpty(value)){
            return "";
        }
        EsSecretSetting secretSetting = JsonUtil.jsonToObject(value,EsSecretSetting.class);
        if(!secretKey.equals(secretSetting.getSecretKey())){
            throw new ServiceException(GoodsErrorCode.E310.code(),"秘钥验证失败!");
        }
        String res = this.customWordsManager.deploy();
        try {
            return new String(res.getBytes(),"utf-8");
        }catch (Exception e){
            e.printStackTrace();
        }
        return "";

    }


}

CustomWordsManager

package com.enation.app.javashop.core.goodssearch.service;

/**
 * 自定义分词表业务层
 * @author fk
 * @version v1.0
 * @since v7.0.0
 * 2018-06-20 16:08:07
 *
 * * update by liuyulei 2019-05-27
 */
public interface CustomWordsManager    {

   /**
    * 部署替换
    * @return
    */
    String deploy();

}

CustomWordsManagerImpl

package com.enation.app.javashop.core.goodssearch.service.impl;

import com.enation.app.javashop.core.goodssearch.model.CustomWords;
import com.enation.app.javashop.core.goodssearch.service.CustomWordsManager;
import com.enation.app.javashop.framework.context.ThreadContextHolder;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.util.DateUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.List;

/**
 * 自定义分词表业务类
 *
 * @author fk
 * @version v1.0
 * @since v7.0.0
 * 2018-06-20 16:08:07
 *
 * update by liuyulei 2019-05-27
 */
@Service
public class CustomWordsManagerImpl implements CustomWordsManager {

    @Autowired
    @Qualifier("goodsDaoSupport")
    private DaoSupport daoSupport;

    @Override
    public String deploy() {
        String sql = "select * from es_custom_words where disabled = 1 order by modify_time desc";
        List<CustomWords> list = this.daoSupport.queryForList(sql, CustomWords.class);
        HttpServletResponse response = ThreadContextHolder.getHttpResponse();
        StringBuffer buffer = new StringBuffer();
        if (StringUtil.isNotEmpty(list)) {
            int i = 0;
            for (CustomWords word : list) {
                if (i == 0) {
                    SimpleDateFormat format =   new SimpleDateFormat( "yyyy-MM-dd hh:mm:ss" );
                    try {
                        response.setHeader("Last-Modified", format.parse(DateUtil.toString(word.getAddTime(),"yyyy-MM-dd hh:mm:ss")) + "");
                        response.setHeader("ETag", format.parse(DateUtil.toString(word.getModifyTime(),"yyyy-MM-dd hh:mm:ss")) + "");
                    }catch (Exception e){
                        e.printStackTrace();
                    }

                    buffer.append(word.getName());
                } else {
                    buffer.append("\n" + word.getName());
                }
                i++;
            }
        }
        return buffer.toString();
    }
}

以上为此次分享内容,后续每周会不定期分享架构文章,大家可以关注我们!!!

易族智汇(javashop)原创文章

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Elasticsearch 之(25)重写IK分词器源码来基于mysql热更新词库
热更新在上一节《IK分词器配置文件讲解以及自定义词库(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fblog.csdn.net%2Fwuzhiwei549%2Farticle%2Fdetails%2F80451031)》自定义词库,每次都是在es的扩展词典中,手动添加
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
ElasticSearch(六):IK分词器的安装与使用IK分词器创建索引
之前我们创建索引,查询数据,都是使用的默认的分词器,分词效果不太理想,会把text的字段分成一个一个汉字,然后搜索的时候也会把搜索的句子进行分词,所以这里就需要更加智能的分词器IK分词器了。1\.ik分词器的下载和安装,测试第一:下载地址:https://github.com/medcl/elasticsearchanalysisi
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这