当前位置: 首页 > news >正文

物流公司做网站高端外贸建站

物流公司做网站,高端外贸建站,湖南好搜网站建设,火车头采集器wordpress下载文章目录 day05-问答系统表 用户端分页查询问题目标效果代码实现 3.6.管理端分页查询问题ES相关 管理端互动问题分页实现三级分类3.6.5.2.多级缓存3.6.5.3.CaffeineTODO#xff1a;使用Caffeine作为本地缓存#xff0c;另外使用redis或者memcache作为分布式缓存#xff0c;构… 文章目录 day05-问答系统表 用户端分页查询问题目标效果代码实现 3.6.管理端分页查询问题ES相关 管理端互动问题分页实现三级分类3.6.5.2.多级缓存3.6.5.3.CaffeineTODO使用Caffeine作为本地缓存另外使用redis或者memcache作为分布式缓存构造多级缓存体系 4.评论相关接口目标效果新增回答或评论 day05-问答系统 效果 表 互动提问的问题表 CREATE TABLE IF NOT EXISTS interaction_question (id bigint NOT NULL COMMENT 主键互动问题的id,title varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 互动问题的标题,description varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT COMMENT 问题描述信息,course_id bigint NOT NULL COMMENT 所属课程id,chapter_id bigint NOT NULL COMMENT 所属课程章id,section_id bigint NOT NULL COMMENT 所属课程节id,user_id bigint NOT NULL COMMENT 提问学员id,latest_answer_id bigint DEFAULT NULL COMMENT 最新的一个回答的id,answer_times int unsigned NOT NULL DEFAULT 0 COMMENT 问题下的回答数量,anonymity bit(1) NOT NULL DEFAULT b0 COMMENT 是否匿名默认false,hidden bit(1) NOT NULL DEFAULT b0 COMMENT 是否被隐藏默认false,status tinyint DEFAULT 0 COMMENT 管理端问题状态0-未查看1-已查看,create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 提问时间,update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间,PRIMARY KEY (id) USING BTREE,KEY idx_course_id (course_id) USING BTREE,KEY section_id (section_id),KEY user_id (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci ROW_FORMATDYNAMIC COMMENT互动提问的问题表;回答或评论表 CREATE TABLE IF NOT EXISTS interaction_reply (id bigint NOT NULL COMMENT 互动问题的回答id,question_id bigint NOT NULL COMMENT 互动问题问题id,answer_id bigint DEFAULT 0 COMMENT 回复的上级回答id,user_id bigint NOT NULL COMMENT 回答者id,content varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 回答内容,target_user_id bigint DEFAULT 0 COMMENT 回复的目标用户id,target_reply_id bigint DEFAULT 0 COMMENT 回复的目标回复id,reply_times int NOT NULL DEFAULT 0 COMMENT 评论数量,liked_times int NOT NULL DEFAULT 0 COMMENT 点赞数量,hidden bit(1) NOT NULL DEFAULT b0 COMMENT 是否被隐藏默认false,anonymity bit(1) NOT NULL DEFAULT b0 COMMENT 是否匿名默认false,create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间,update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间,PRIMARY KEY (id) USING BTREE,KEY idx_question_id (question_id) USING BTREE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci ROW_FORMATDYNAMIC COMMENT互动问题的回答或评论;KEY 关键字用于定义索引而 USING BTREE 是一个可选的子句用于显式指定索引的存储类型。如果不指定 USING BTREEMySQL 会默认使用 B-Tree 索引结构 用户端分页查询问题 目标效果 代码实现 3.6.管理端分页查询问题 ES相关 Feign接口 package com.tianji.api.client.search;import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam;import java.util.List;FeignClient(search-service) public interface SearchClient {GetMapping(/courses/name)ListLong queryCoursesIdByName(RequestParam(value keyword, required false) String keyword); } Controller: package com.tianji.search.controller;import com.tianji.common.domain.dto.PageDTO; import com.tianji.search.domain.query.CoursePageQuery; import com.tianji.search.domain.vo.CourseVO; import com.tianji.search.service.ICourseService; import com.tianji.search.service.ISearchService; import io.swagger.annotations.Api; import org.springframework.web.bind.annotation.*; import springfox.documentation.annotations.ApiIgnore;RestController RequestMapping(courses) Api(tags 课程搜索接口) RequiredArgsConstructor public class CourseController {private final ISearchService searchService;private final ICourseService courseService;ApiOperation(用户端课程搜索接口)GetMapping(/portal)public PageDTOCourseVO queryCoursesForPortal(CoursePageQuery query){return searchService.queryCoursesForPortal(query);}ApiIgnoreGetMapping(/name)public ListLong queryCoursesIdByName(RequestParam(keyword) String keyword){return searchService.queryCoursesIdByName(keyword);}管理端互动问题分页实现 管理端互动问题分页: Admin可以通过关键字搜索课程但由于问题表中没有课程名称字段所以通过 课程ID获取课程名字课程ID可以从Feign获取 QuestionAdminPageQuery.getCourseName是课程名称的关键字 课程ID可以从Feign获取接受课程关键字搜ES public PageDTOQuestionAdminVO getInterationQuestionByAdminPage(QuestionAdminPageQuery pageQuery) {// 如果用户传了课程名称参数则从es中获取该名称对应的课程idListLong courseIdList null;if (StringUtils.isNotBlank(pageQuery.getCourseName())) {// feign远程调用从es中获取该名称对应的课程idcourseIdList searchClient.queryCoursesIdByName(pageQuery.getCourseName());// 判断查询结果是否为空if (CollUtil.isEmpty(courseIdList)) {return PageDTO.empty(0L, 0L);}}// 查询互动问题表PageInteractionQuestion questionPage lambdaQuery().eq(pageQuery.getStatus() ! null, InteractionQuestion::getStatus, pageQuery.getStatus()).ge(pageQuery.getBeginTime() ! null, InteractionQuestion::getCreateTime, pageQuery.getBeginTime()).le(pageQuery.getEndTime() ! null, InteractionQuestion::getCreateTime, pageQuery.getEndTime()).in(!CollUtil.isEmpty(courseIdList), InteractionQuestion::getCourseId, courseIdList) // 实现课程名称模糊查询.page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());// 查询到的列表为空则返回空集ListInteractionQuestion records questionPage.getRecords();if (CollUtil.isEmpty(records)) {return PageDTO.of(questionPage, Collections.emptyList());}// 这里用for循环而不是Stream流减少循环次数SetLong userIds new HashSet();SetLong courseIds new HashSet();SetLong chapterAndSections new HashSet();for (InteractionQuestion question : records) {userIds.add(question.getUserId());courseIds.add(question.getCourseId());chapterAndSections.add(question.getChapterId());chapterAndSections.add(question.getSectionId());}// feign远程调用用户服务获取用户信息ListUserDTO userDTOS userClient.queryUserByIds(userIds);if (CollUtil.isEmpty(userDTOS)) {throw new BizIllegalException(用户不存在);}MapLong, UserDTO userMap userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, userDTO - userDTO));// feign远程调用课程服务获取课程信息ListCourseSimpleInfoDTO courseDTOs courseClient.getSimpleInfoList(courseIds);if (CollUtil.isEmpty(courseDTOs)) {throw new BizIllegalException(课程不存在);}MapLong, CourseSimpleInfoDTO courseMap courseDTOs.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, courseDTO - courseDTO));// feign远程调用课程服务获取章节信息ListCataSimpleInfoDTO catalogueDTOs catalogueClient.batchQueryCatalogue(chapterAndSections);if (CollUtil.isEmpty(catalogueDTOs)) {throw new BizIllegalException(章节不存在);}// 封装为章节id章节名称需要根据章节id赋值章节名称MapLong, String catalogueMap catalogueDTOs.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));// 封装VO并返回ListQuestionAdminVO voList new ArrayList();for (InteractionQuestion record : records) {QuestionAdminVO questionAdminVO BeanUtils.copyBean(record, QuestionAdminVO.class);UserDTO userDTO userMap.get(record.getUserId());if (userDTO ! null) {questionAdminVO.setUserName(userDTO.getName()); // 用户昵称}CourseSimpleInfoDTO courseDTO courseMap.get(record.getCourseId());if (courseDTO ! null) {questionAdminVO.setCourseName(courseDTO.getName()); // 课程名称// 获取课程的三级分类id根据三级分类id拼接分类名称String categoryName categoryCache.getCategoryNames(courseDTO.getCategoryIds());questionAdminVO.setCategoryName(categoryName); // 课程所述分类名称}// 使用getOrDefault防止异常questionAdminVO.setChapterName(catalogueMap.getOrDefault(record.getChapterId(), )); // 章节名称questionAdminVO.setSectionName(catalogueMap.getOrDefault(record.getSectionId(), )); // 小节名称voList.add(questionAdminVO);}return PageDTO.of(questionPage, voList);}三级分类 表里设置parent_id代表上级是谁 都是IT-互联网下面的二级分类红框里的 因为分类信息的改动量比较小一般都不会动了所以就缓存起来 课程分类数据在很多业务中都需要查询这样的数据如此频繁的查询有没有性能优化的办法呢 3.6.5.2.多级缓存 相信很多同学都能想到借助于Redis缓存来提高性能减少数据库压力。非常好不过Redis虽然能提高性能但每次查询缓存还是会增加网络带宽消耗也会存在网络延迟。 而分类数据具备两大特点 数据量小长时间不会发生变化。 像这样的数据除了建立Redis缓存以外还非常适合做本地缓存Local Cache。这样就可以形成多级缓存机制 数据查询时优先查询本地缓存本地缓存不存在再查询Redis缓存Redis不存在再去查询数据库。 本地缓存简单来说就是JVM内存的缓存比如你建立一个HashMap把数据库查询的数据存入进去。以后优先从这个HashMap查询一个本地缓存就建立好了。 本地缓存由于无需网络查询速度非常快。不过由于上述缺点本地缓存往往适用于数据量小、更新不频繁的数据。而课程分类恰好符合。 3.6.5.3.Caffeine 当然我们真正创建本地缓存的时候并不是直接使用HashMap之类的集合因为维护起来不太方便。而且内存淘汰机制实现起来也比较麻烦。 所以我们会使用成熟的框架来完成比如Caffeine Caffeine是一个基于Java8开发的提供了近乎最佳命中率的高性能的本地缓存库。目前Spring内部的缓存使用的就是Caffeine。 第二次get就不会执行了 Caffeine提供了三种缓存驱逐策略 基于容量设置缓存的数量上限 // 创建缓存对象 CacheString, String cache Caffeine.newBuilder().maximumSize(1) // 设置缓存大小上限为 1.build();基于时间设置缓存的有效时间 // 创建缓存对象 CacheString, String cache Caffeine.newBuilder()// 设置缓存有效期为 10 秒从最后一次写入开始计时 .expireAfterWrite(Duration.ofSeconds(10)) .build();Caffeine.newBuilder().initialCapacity(1) // 初始容量 缓存初始化时会分配足够的内存来存储1个键值对。.maximumSize(10_000) // 最大容量 缓存最多可以存储10,000个键值对。.expireAfterWrite(Duration.ofMinutes(30)) // 指定了缓存项在写入后多长时间过期。Duration.ofMinutes(30)是一个静态方法用于创建一个表示30分钟的时间持续对象.build();和上面明星例子一样如果缓存没有则远程调用获取放到缓存中 下次30分钟查 直接返回【一级分类id、二级分类id、三级分类id】 public MapLong, CategoryBasicDTO getCategoryMap() {return categoryCaches.get(CATEGORY, key - {// 1.从CategoryClient查询ListCategoryBasicDTO list categoryClient.getAllOfOneLevel();if (list null || list.isEmpty()) {return CollUtils.emptyMap();}return list.stream().collect(Collectors.toMap(CategoryBasicDTO::getId, Function.identity()));}); }拼接三级分类名称用/分隔 /*** 根据三级分类id拼接三级分类名称* param ids 一级分类id、二级分类id、三级分类id* return 拼接三级分类名称用/分隔*/public String getCategoryNames(ListLong ids) {if (ids null || ids.size() 0) {return ;}// 1.读取分类缓存MapLong, CategoryBasicDTO map getCategoryMap();// 2.根据id查询分类名称并组装StringBuilder sb new StringBuilder();for (Long id : ids) {sb.append(map.get(id).getName()).append(/);}// 3.返回结果return sb.deleteCharAt(sb.length() - 1).toString();}调用 questionAdminVO.setCourseName(courseDTO.getName()); // 课程名称 // 获取课程的三级分类id根据三级分类id拼接分类名称 String categoryName categoryCache.getCategoryNames(courseDTO.getCategoryIds()); questionAdminVO.setCategoryName(categoryName); // 课程所述分类名称SpringBoot的自动加载机制启动缓存生效这一系列流程 Feign客户端的实现类是由Feign在运行时动态生成的你不需要手动编写实现类。只要你的项目配置正确Feign会自动处理接口的实现并通过HTTP请求调用远程服务。 TODO使用Caffeine作为本地缓存另外使用redis或者memcache作为分布式缓存构造多级缓存体系 4.评论相关接口 目标效果 回答 评论是 回答下面的 新增回答或评论 Data ApiModel(description 互动回答信息) public class ReplyDTO {ApiModelProperty(回答内容)NotNull(message 回答内容不能为空)private String content;ApiModelProperty(是否匿名提问)private Boolean anonymity;ApiModelProperty(互动问题id)NotNull(message 问题id不能为空)private Long questionId;// 该字段为null表示是回答否则表示评论ApiModelProperty(回复的上级回答id没有可不填)private Long answerId;ApiModelProperty(回复的目标回复id没有可不填)private Long targetReplyId;ApiModelProperty(回复的目标用户id没有可不填)private Long targetUserId;ApiModelProperty(标记是否是学生提交的回答默认true)private Boolean isStudent true; }Transactional public void addReply(ReplyDTO replyDTO) {// 拷贝实体InteractionReply reply BeanUtil.toBean(replyDTO, InteractionReply.class);if (reply.getAnswerId() null) { // 当前是回答的话不需要target_user_id字段reply.setTargetUserId(null);}// 获取当前登录用户Long userId UserContext.getUser();reply.setUserId(userId);// 保存评论或回答this.save(reply);// 查询关联的问题InteractionQuestion question questionMapper.selectById(reply.getQuestionId());if (question null) {throw new BizIllegalException(参数异常);}// 根据answerId是否为null判断是回答还是评论如果是需要在interaction_question中记录最新一次回答的idif (reply.getAnswerId() null) { // answerId为null表示当前是回答question.setLatestAnswerId(reply.getId()); // 更新问题的最新回答idquestion.setAnswerTimes(question.getAnswerTimes() 1); // 该问题的回答数量1} else { // 如果是评论// 获取评论关联的回答InteractionReply interactionReply this.getById(reply.getAnswerId());interactionReply.setReplyTimes(interactionReply.getReplyTimes() 1); // 该回答的评论数量1// 更新评论关联的回答this.updateById(interactionReply);}// 如果是学生提交则需要更新问题状态为未查看if (replyDTO.getIsStudent()) {question.setStatus(QuestionStatus.UN_CHECK);}// 更新问题questionMapper.updateById(question);// 发送MQ消息新增积分rabbitMqHelper.send(MqConstants.Exchange.LEARNING_EXCHANGE,MqConstants.Key.WRITE_REPLY,SignInMessage.of(userId,5)); // 一个问题5积分}
http://www.w-s-a.com/news/309228/

相关文章:

  • 做线上网站需要多少钱系统开发板价格
  • 建筑企业登录哪个网站wordpress feed地址
  • 网站建设流程百科提升seo搜索排名
  • 杭州网站建设 巴零做销售怎么和客户聊天
  • 北京自己怎样做网站wordpress oauth2插件
  • 上海800做网站wordpress建站的好处
  • 婚纱摄影网站设计模板如何做好网站内容
  • cdn网站加速招商计划书模板ppt
  • 我在某网站网站做代理开发小程序外包
  • 设计网站国外商城网站的建设费用
  • 网站开发工作需要什么专业学做网站游戏教程
  • 电子商务网站规划 分析 设计杭州网站优化平台
  • 汕头企业自助建站系统网站后台登陆验证码无法显示
  • 宁波网站制作服务做外贸推广自己网站
  • php 微信 网站开发青岛网站互联网公司
  • 网站软件免费下载大全网站建设开发价格高吗
  • asp网站制作软件上海做网站制作
  • 福田区住房和建设局网站好搜搜索引擎
  • 平面设计师看的网站济南机场建设
  • 俄文网站开发翻译平台页面设计模板
  • 建设在线购物网站淮南电商网站建设价格
  • 龙泉市旅游门户网站建设wordpress faq插件
  • 网站的流程图贵阳做网站方舟网络
  • c 做网站开发实例wordpress 加上index
  • 济南seo网站推广搜索广告推广
  • 有关于网站建设的参考文献宁波seo网络推广公司
  • 网站设配色个人主页介绍文案
  • 网站seo相关设置优化网站建设的好处
  • 上海市建设工程安全生产协会网站郴州网站设计公司
  • 网站大型网页游戏自己搭建服务器做视频网站