接下来,我会将整篇毕设论文放上该专栏,其中按照论文提纲主要分为八大部分。每一部分单独列出一篇文章。 这一篇就是论文的第五部分系统详细设计与实现。因为该部分内容比较多,避免大家审阅疲劳,分为3个文章来进行解读。中括号代表的是参考文献,后面会有列出来
顾名思义,工具包就是为其他服务提供工具和方法的,减低服务之间的耦合性而设计,因为工具包是不用启动的。系统的所有接口及其方法在通用common包内声明。以及统一异常抛出方法和统一异常处理器,工具类,实体类都在此包下。接下来详细描述一下该包的主要代码
为了方便前端进行接收数据,一般都会写一个通用返回类,该返回类就应当包含状态码,提示信息,以及返回数据等三个属性。构建方法也应当包含无返回数据和带返回数据的构造方法。如下图5-1接口统一返回类图:
图 5-1 接口统一返回类图
其实这里也是添加了@Data注解,至于这里idea没有生成那条虚线。
有些状态码需要我们自定义输出,就是比如说前端弹窗出来的提示信息。这里状态码可以使用一个枚举类型,该系统的状态码以及提示信息如下表5-1:
表 5-1 项目状态码信息表
状态名称 | 状态码 | 提示信息 |
---|---|---|
SUCCESS | 200 | ok |
SYSTEM_ERROR | 500 | 系统异常 |
PARAMETER_ERROR | 601 | 参数异常 |
INSERT_PRODUCT_TYPE_ERROR | 602 | 该商品类型不能添加子类型 |
DELETE_PRODUCT_TYPE_ERROR | 603 | 该商品类型有子类型,无法删除 |
UPLOAD_FILE_ERROR | 604 | 文件上传失败 |
REGISTER_CODE_ERROR | 605 | 注册验证码错误 |
REGISTER_REPEAT_PHONE_ERROR | 606 | 该手机号已注册 |
REGISTER_REPEAT_NAME_ERROR | 607 | 该用户名已注册 |
LOGIN_NAME_PASSWORD_ERROR | 608 | 用户名或者密码异常 |
LOGIN_CODE_ERROR | 609 | 登录验证码错误 |
LOGIN_NOPHONE_ERROR | 610 | 该手机号未注册 |
LOGIN_USER_STATUS_ERROR | 611 | 该用户状态异常 |
VERRIFY_TOKE_ERROR | 612 | token解析异常 |
ALIPAY_ERROR | 613 | 支付Utils异常 |
QR_CODE_ERROR | 614 | 生成二维码异常 |
CHECK_SIGN_ERROR | 615 | 验证支付签名失败 |
NO_STOCK_ERROR | 616 | 库存不足 |
ORDER_EXPIRED_ERROR | 617 | 订单过期 |
针对于系统运行需要抛出异常,我们这里进行统一处理,以便前端能够友好展示提示信息。
如下图5-2展示的是自定义业务异常类,需要因为这里处理的是运行时异常,因此需要实现RunTimeException类以便在系统抛出该异常能继续运行,此外还应当实现Serializable接口,因为有部分异常抛出时需要序列化。
图 5-2 自定义业务异常类
如下图5-3所示,展示的是全局异常处理器,@RestControllerAdvice注解配置该类为控制器异常处理类,在defaultExceptionHandler方法上加上@ExceptionHandler注解,表示当抛出BusException异常类时,能够被该方法捕捉。
图 5-3 全局异常处理器
这里使用了Md5Util工具类,主要用于对用户密码进行加密,统一使用密钥进行加密。以及JWTUtil工具类,在用户登录时生成token所需要使用到的方法,还有RandomUtil工具类,该工具类用途在于用户进行短信验证时生成随机N位数的验证码。工具包类图组成如下图5-4所示:
图 5-4 工具包类图
前台用户服务主要的功能分为用户登录和注册等,其中用户登录可以分为短信登录以及用户密码登录等。
下图是用户注册时的程序流程图,用户注册先通过手机号短信验证,先查询该手机号是否已存在,如果存在则注册不了,反之进入下一步,输入用户名和密码,然后再次查询该用户名是否已存在,如果该用户名已存在也无法进入下一步,如果手机号和用户名都没有存在,则可以完成注册。跳转登录页面。前端页面展示和程序流程图如下图5-5所示:
图 5-5 用户注册程序流程图
如下图5-6是显示用户进行登录的数据流程图,首先用户可以选择通过账户名密码登录,也可选择通过短信验证登录。
图 5-6 短信验证登录流程图
1. 创建商品索引
这里前台搜索功能使用到了Elasticsearch搜索引擎实现的效果首先需要在Elasticsearch的可视化管理页面Kibana上面创建商品索引,把相关的关键词设置,以及分词器有拼音分词和智能分词器。
2. 根据被分词的文本进行分词
首先要获取Elasticsearch里面的分词集合,注意这里我们时根据输入的字符串,以及使用的是哪一种分词器来获取分词集合,如果搜索框为空,则默认搜索所有商品。
// 分词请求
AnalyzeRequest request = AnalyzeRequest.withIndexAnalyzer("goods",analyzer,text);
// 奉送分词请求,获取相应结果
AnalyzeResponse response = restHighLevelClient.indices().analyze(request, RequestOptions.DEFAULT);
// 处理响应结果
List<String> words = new ArrayList<>(); // 分词结果集合
List<AnalyzeResponse.AnalyzeToken> tokens = response.getTokens();
for (AnalyzeResponse.AnalyzeToken token:tokens){
// 分出的词
String term = token.getTerm();
words.add(term);
}
上面就是通过该方法AnalyzeRequest.withIndexAnalyzer获取分词请求对象,然后再通过restHighLevelClient.indices().analyze()方法发送请求,获取分词响应结果,分词集合就再响应结果的Tokens里面,然后再进行列举获取分词,将其放到集合words即可完成分词。
3. 对于前端的输入框进行自动补齐
对于前端输入框的字符串进行自动补齐,这里是一个固定写法,先创建补全条件,再发送请求,最后处理结果。
4. 构造搜索条件
这里我们要先定义前端传过来的查询对象应当包括什么,因为这里查询的比较复杂,我们需要先确定查询有关键字、商品名、商品品牌、以及价格区间、规格项集合、排序字段、页码和每页条数等。其中规格项只包括规格项名称以及值,相当于key-value集合,因此这里规格项集合为Map集合,键:规格名,值:规格值。搜索参数实体类如下图5-7所示:
图 5-7 搜索参数实体类
(1) 首先构建复杂的查询对象
BoolQueryBuilder builder = QueryBuilders.boolQuery();
(2) 这里我们要明白,如果有关键词查询则关键词可以匹配ES索引里面的商品名,商品副标题,商品品牌等字段。否则查询全部。MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keyword, "goodsName", "caption", "brand");该代码就表示包括关键词不为空是就匹配商品副标题caption,商品名goodsName,品牌brand等字段进行查询,否则查询全部。代码如下图-8所示:
图 5-8
(3) 当然如果查询条件包括商品名,商品品牌、商品价格、商品规格项则实现精准查询。其中商品规格项的查询比较复杂,首先要通过商品搜索参数获取商品规格项集合goodsSearchParam.getSpecificationOption(),代码如下图5-9所示:
图 5-9
(4) 添加分页条件,以及如果查询条件包括排序条件,则添加排序条件。
5. 完成搜索功能
这里可以使用ElasticsearchRestTemplate自带的搜索方法进行查询,如下代码:
SearchHits<GoodsES> search = template.search(query, GoodsES.class);
6. 将查询结果封装为Mybatis-Plus自带的Page对象,这里直接将查询结果用ES中商品实体类当作返回实体封装即可,并将其遍历到List集合,最后将List集合的结果集封装到Mybatis-Plus的Page对象即可。如以下代码所示
List<GoodsES> content = new ArrayList<>();
for (SearchHit<GoodsES> goodsESSearchHit : search) {
GoodsES goodsES = goodsESSearchHit.getContent();
content.add(goodsES);
}
// 3.2 将List转为MP-Page对象
Page<GoodsES> page = new Page<>();
page
// 当前页
.setCurrent(goodsSearchParam.getPage())
// 每页条数
.setSize(goodsSearchParam.getSize())
// 总条数
.setTotal(search.getTotalHits())
// 结果集
.setRecords(content);
7. 封装结果对象
这里主要是将结果对象所包含的品牌集合,商品类型集合,商品规格项集合封装到结果对象,并在前端渲染到查询面板中,由于此段代码和上面查询结果封装到规格项中大同小异就不过多阐述,总的来说,该服务的搜索程序流程图如下图5-10所示:
图 5-10 搜索程序流程图
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。