热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

标签缓存展示相关问题回复通知回复展示(9)

1.标签展示1.1question.html展示标签通过”,”切割成数组,并循环

1. 标签展示

1.1 question.html展示标签

通过”,”切割成数组,并循环

标签缓存展示-相关问题-回复通知-回复展示-(9)

1.2 标签样式question-tag

标签缓存展示-相关问题-回复通知-回复展示-(9)
标签缓存展示-相关问题-回复通知-回复展示-(9)

2. 相关问题展示

2.1 编写sql

QuestionMapper.xml文件

这样可以模糊查询通过标签,查出有相同标签的文章

标签缓存展示-相关问题-回复通知-回复展示-(9)

    SELECT * from question WHERE id != #{id} and tag regexp #{tag}

2.2 Service层进行封装

,替换为|用于查询

标签缓存展示-相关问题-回复通知-回复展示-(9)
public List selectRelated(QuestionDTO queryDTO) {
    if(StringUtils.isBlank(queryDTO.getTag())){
        return new ArrayList();
    }
    String[] tags = StringUtils.split(queryDTO.getTag(), ",");
    String regexpTag = Arrays.stream(tags).collect(Collectors.joining("|"));
    Question question = new Question();
    question.setId(queryDTO.getId());
    question.setTag(regexpTag);
    List questiOns= questionMapper.selectRelated(question);
    List questiOnDTOS= questions.stream().map(q -> {
        QuestionDTO questiOnDTO= new QuestionDTO();
        BeanUtils.copyProperties(q, questionDTO);
        return questionDTO;
    }).collect(Collectors.toList());
    return questionDTOS;
}

2.3 Controller使用

标签缓存展示-相关问题-回复通知-回复展示-(9)

2.4 页面展示

标签缓存展示-相关问题-回复通知-回复展示-(9)

3. 指定标签展示

3.1 创建TagDTO

  • categoryName:上层标签
  • tags:下层标签
标签缓存展示-相关问题-回复通知-回复展示-(9)

3.2 缓存标签类

  • 用来存放标签的内容,所有的标签都通过它的get()方法获取
  • filterInvalid(String tags):用来校验传来的标签中标签库里是否存在
标签缓存展示-相关问题-回复通知-回复展示-(9)
package life.guohui.community.cache;
public class TagCache {
    public static List get(){
        ArrayList tagDTOS = new ArrayList();
        TagDTO program = new TagDTO();
        program.setCategoryName("开发语言");
        program.setTags(Arrays.asList("Javascript", "php", "css", "html", "html5", "java", "node.js", "python", "c++", "c", "golang", "objective-c", "typescript", "shell", "swift", "c#", "sass", "ruby", "bash", "less", "asp.net", "lua", "scala", "coffeescript", "actionscript", "rust", "erlang", "perl"));
        tagDTOS.add(program);
        TagDTO framework = new TagDTO();
        framework.setCategoryName("平台框架");
        framework.setTags(Arrays.asList("laravel", "spring", "express", "django", "flask", "yii", "ruby-on-rails", "tornado", "koa", "struts"));
        tagDTOS.add(framework);


        TagDTO server = new TagDTO();
        server.setCategoryName("服务器");
        server.setTags(Arrays.asList("linux", "nginx", "docker", "apache", "ubuntu", "centos", "缓存 tomcat", "负载均衡", "unix", "hadoop", "windows-server"));
        tagDTOS.add(server);

        TagDTO db = new TagDTO();
        db.setCategoryName("数据库");
        db.setTags(Arrays.asList("mysql", "redis", "mongodb", "sql", "oracle", "nosql memcached", "sqlserver", "postgresql", "sqlite"));
        tagDTOS.add(db);

        TagDTO tool = new TagDTO();
        tool.setCategoryName("开发工具");
        tool.setTags(Arrays.asList("git", "github", "visual-studio-code", "vim", "sublime-text", "xcode intellij-idea", "eclipse", "maven", "ide", "svn", "visual-studio", "atom emacs", "textmate", "hg"));
        tagDTOS.add(tool);
        return tagDTOS;
    }
    public static String filterInvalid(String tags){
        String[] split = StringUtils.split(tags, ",");
        List tagDTOS = get();
        List tagList = tagDTOS.stream().flatMap(tag -> tag.getTags().stream()).collect(Collectors.toList());
        String invalid = Arrays.stream(split).filter(t -> !tagList.contains(t)).collect(Collectors.joining(","));
        return invalid;
    }
}

3.3 在PublishController中把标签存到Model中

标签缓存展示-相关问题-回复通知-回复展示-(9)

3.4 在发布问题功能中做校验

标签缓存展示-相关问题-回复通知-回复展示-(9)
String invalid = TagCache.filterInvalid(tag);
if(StringUtils.isNotBlank(invalid)){
    model.addAttribute("error", "输入非法标签:"+invalid);
    return "publish";
}

3.5 publish.html处理

标签缓存展示-相关问题-回复通知-回复展示-(9)
function selectTag(e){
    var value = e.getAttribute("data-tag");
    var previous = $("#tag").val();

    if(previous.indexOf(value) == -1){
        if(previous){
            $("#tag").val(previous+','+value);
        }else {
            $("#tag").val(value);
        }
    }
}
function showSelectTag() {
    $("#select-tag").show();
}

第二个参数为index,利用它的.first判断是不是第一个元素,来控制选中高亮及标签显示

th:each="selectCategory,selectCategoryStat : ${tags}"

4. 回复通知

4.1 表的设计

create table notification
(
    id bigint auto_increment primary key,
    notifier bigint not null,-- 评论当前问题的人的Id
    receiver bigint not null,-- 接受者Id,当前问题的发起者Id
    outerid bigint not null,-- 当前问题的Id
    type int not null,-- 回复了问题(1),还是回复了评论(2)
    gmt_create bigint not null,
    status int default 0 not null,-- 已读Or未读
    notifier_name varchar(100),-- 评论当前问题的人名
    outer_title varchar(256)-- 当前问题的标题
);

逆向工程生成对应的实体类和mapper

4.2 创建NotificationTypeEnum

  • 区分是回复了问题,还是回复了评论。
  • nameOfType(int type)方法返回数字对应的信息
标签缓存展示-相关问题-回复通知-回复展示-(9)
package life.guohui.community.enums;
public enum NotificationTypeEnum {
    REPLY_QUESTION(1,"回复了问题"),
    REPLY_COMMENT(2,"回复了评论")
    ;
    private int type;
    private String name;

    NotificationTypeEnum(int status, String name) {
        this.type = status;
        this.name = name;
    }

    public int getType() {
        return type;
    }

    public String getName() {
        return name;
    }
    public static String nameOfType(int type) {
        for (NotificationTypeEnum notificationTypeEnum : NotificationTypeEnum.values()) {
            if (notificationTypeEnum.getType() == type) {
                return notificationTypeEnum.getName();
            }
        }
        return "";
    }
}

4.3 创建NotificationStatusEnum

用来区分回复是已读还是未读

标签缓存展示-相关问题-回复通知-回复展示-(9)

4.4 创建NotificationDTO

用来在页面上展示对应的数据

标签缓存展示-相关问题-回复通知-回复展示-(9)
package life.guohui.community.dto;
@Data
public class NotificationDTO {
    private Long id;
    private Long gmtCreate;
    private Integer status;
    private Long notifier;//评论者
    private Long outerid;//问题Id
    private String notifierName;//评论者的名字
    private String outerTitle;//问题提出者的问题标题
    private String typeName;
    private Integer type;
}

4.5 评论后会去哪?增加回复

a. 点击评论后发送Ajax请求/commentCommentController执行insert方法

标签缓存展示-相关问题-回复通知-回复展示-(9)
标签缓存展示-相关问题-回复通知-回复展示-(9)

b. 添加一个评论时,我们就要同时创建一个通知

增加一个创建通知的方法,该方法的参数:

  • 评论的实体类对象Comment
  • 问题的提出者Id:receiver
  • 当前评论者的名字:notifierName,从Controller层中传过来,从session中获取user
  • 当前问题的标题:outerTitle
  • 回复的类型:notificationType,回复的是问题Or评论
  • 当前问题的Id:outerId
标签缓存展示-相关问题-回复通知-回复展示-(9)
private void createNotify(Comment comment, Long receiver, String notifierName, String outerTitle, NotificationTypeEnum notificationType,Long outerId) {
    Notification notification = new Notification();
    notification.setGmtCreate(System.currentTimeMillis());
    notification.setType(notificationType.getType());
    notification.setOuterid(outerId);//发布问题的id
    notification.setNotifier(comment.getCommentator());//评论人的人的id
    notification.setStatus(NotificationStatusEnum.UNREAD.getStatus());
    notification.setReceiver(receiver);//当前问题发布人的Id
    notification.setNotifierName(notifierName);//评论的人的名字
    notification.setOuterTitle(outerTitle);//发布问题的人的问题标题
    notificationMapper.insert(notification);
}

c. 在添加评论的方法中使用创建通知方法

标签缓存展示-相关问题-回复通知-回复展示-(9)
@Transactional
public void insert(Comment comment, User commentator) {
    if(comment.getParentId() == null || comment.getParentId() == 0){
        throw new CustomizeException(CustomizeErrorCode.TARGET_PARAM_NOT_FOUND);
    }
    if(comment.getType() == null || !CommentTypeEnum.isExist(comment.getType())){
        throw new CustomizeException(CustomizeErrorCode.TYPE_PARAM_WRONG);
    }
    if(comment.getType() == CommentTypeEnum.COMMENT.getType()){
        //回复评论
        Comment dbComment = commentMapper.selectByPrimaryKey(comment.getParentId());
        if(dbComment == null){
            throw new CustomizeException(CustomizeErrorCode.COMMENT_NOT_FOUND);
        }
        Question question = questionMapper.selectByPrimaryKey(dbComment.getParentId());
        if(question == null){
            throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
        }
        commentMapper.insert(comment);

        //增加评论数
        Comment parentComment = new Comment();
        parentComment.setId(comment.getParentId());
        parentComment.setCommentCount(1);
        commentMapper.incCommentCount(parentComment);
        //创建通知
        createNotify(comment, dbComment.getCommentator(), commentator.getName(), question.getTitle(), NotificationTypeEnum.REPLY_COMMENT,question.getId());
    }else {
        //回复问题
        Question question = questionMapper.selectByPrimaryKey(comment.getParentId());
        if(question == null){
            throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
        }
        comment.setCommentCount(0);
        commentMapper.insert(comment);
        question.setCommentCount(1);
        questionMapper.incCommentCount(question);
        //创建通知
        createNotify(comment,question.getCreator(),commentator.getName(),question.getTitle(),NotificationTypeEnum.REPLY_QUESTION,question.getId());
    }
}

4.6 展示回复

标签缓存展示-相关问题-回复通知-回复展示-(9)
标签缓存展示-相关问题-回复通知-回复展示-(9)
标签缓存展示-相关问题-回复通知-回复展示-(9)

a. 给分页DTO添加泛型

可以存入不同类型的集合数据

标签缓存展示-相关问题-回复通知-回复展示-(9)
package life.guohui.community.dto;
@Data
public class PaginationDTO {
    private List data;
    private boolean showPrevious;
    private boolean showFirstPage;
    private boolean showNext;
    private boolean showEndPage;
    private Integer page;
    private Integer totalPage;
    private List pages = new ArrayList();


    public void setPagination(Integer totalPage, Integer page) {
        this.totalPage = totalPage;
        this.page = page;
        pages.add(page);
        for(int i = 1;i 0){
                pages.add(0,page-i);
            }
            if(page+i 

b. 创建NotificationService

  • 查出当前用户的所有的回复
  • 将查出的所有Notification对象,赋值给NotificationDTO对象
public PaginationDTO list(Long id, Integer page, Integer size) {
    PaginationDTO paginatiOnDTO= new PaginationDTO();
    Integer totalPage;
    //拿到总数
    NotificationExample notificatiOnExample= new NotificationExample();
    notificationExample.createCriteria().andReceiverEqualTo(id);
    Integer totalCount = (int)notificationMapper.countByExample(notificationExample);

    if(totalCount % size == 0){totalPage = totalCount/size;}else{totalPage = totalCount/size + 1;}
    if(pagetotalPage){            page = totalPage;        }
    paginationDTO.setPagination(totalPage,page);
    Integer offset = size * (page - 1);
    NotificationExample example1 = new NotificationExample();
    example1.createCriteria().andReceiverEqualTo(id);
    List notificatiOns= notificationMapper.selectByExampleWithRowbounds(example1, new RowBounds(offset, size));

    if(notifications.size() == 0){
        return paginationDTO;
    }

    List notificatiOnDTOS= new ArrayList();
    for (Notification notification : notifications) {
        NotificationDTO notificatiOnDTO= new NotificationDTO();
        BeanUtils.copyProperties(notification,notificationDTO);
        notificationDTO.setTypeName(NotificationTypeEnum.nameOfType(notification.getType()));
        notificationDTOS.add(notificationDTO);
    }
    paginationDTO.setData(notificationDTOS);
    return paginationDTO;
}

c. 要查出当前用户未读评论的数量

public Long unreadCount(Long userId) {
    NotificationExample notificatiOnExample= new NotificationExample();
    notificationExample.createCriteria().andReceiverEqualTo(userId).andStatusEqualTo(NotificationStatusEnum.UNREAD.getStatus());
    return notificationMapper.countByExample(notificationExample);
}

d. 在ProfileController中存入Model

标签缓存展示-相关问题-回复通知-回复展示-(9)

e. 页面的渲染

未读

未读数量

我的问题

    最新回复
    

4.7 问题的标题是链接

点击后跳转到该问题的question.html页面

标签缓存展示-相关问题-回复通知-回复展示-(9)

a. Controller中增加read(id,user)方法

id为回复对象的Id,该方法返回这个notificationDTO对象

标签缓存展示-相关问题-回复通知-回复展示-(9)

b. Service中

  • 通过Id查出这个回复的信息,修改它的status为已读。
  • Notification的值赋给NotificationDTO并返回。
public NotificationDTO read(Long id, User user) {
    Notification notification = notificationMapper.selectByPrimaryKey(id);
    if(notification == null){
        throw new CustomizeException(CustomizeErrorCode.NOTIFICATION_NOT_FOUND);
    }
    //接收者和当前用户是不是同一个人,防止从网址中输入其他接收者的id
    if(!Objects.equals(notification.getReceiver(),user.getId())){
        throw new CustomizeException(CustomizeErrorCode.READ_NOTIFICATION_FAIL);
    }
    //更新已读
    notification.setStatus(NotificationStatusEnum.READ.getStatus());
    notificationMapper.updateByPrimaryKey(notification);
    NotificationDTO notificatiOnDTO= new NotificationDTO();
    BeanUtils.copyProperties(notification,notificationDTO);
    notificationDTO.setTypeName(NotificationTypeEnum.nameOfType(notification.getType()));
    return notificationDTO;
}

4.8 修复小问题

a. 把未读的回复存到session中

标签缓存展示-相关问题-回复通知-回复展示-(9)

b. 将回复列表按时间倒序

标签缓存展示-相关问题-回复通知-回复展示-(9)

推荐阅读
  • 字符串对比竟也暗藏玄机,你是否认同?
    在探讨字符串对比技术时,本文通过两个具体案例深入剖析了其背后的复杂性与技巧。首先,案例一部分详细介绍了需求背景、分析过程及两种不同的代码实现方法,并进行了总结。接着,案例二同样从需求描述出发,逐步解析问题并提供解决方案,旨在揭示字符串处理中容易被忽视的关键细节和技术挑战。 ... [详细]
  • 本文全面解析了 Python 中字符串处理的常用操作与技巧。首先介绍了如何通过 `s.strip()`, `s.lstrip()` 和 `s.rstrip()` 方法去除字符串中的空格和特殊符号。接着,详细讲解了字符串复制的方法,包括使用 `sStr1 = sStr2` 进行简单的赋值复制。此外,还探讨了字符串连接、分割、替换等高级操作,并提供了丰富的示例代码,帮助读者深入理解和掌握这些实用技巧。 ... [详细]
  • 阿里云 Aliplayer高级功能介绍(八):安全播放
    如何保障视频内容的安全,不被盗链、非法下载和传播,阿里云视频点播已经有一套完善的机 ... [详细]
  • 使用HTML和JavaScript实现视频截图功能
    本文介绍了如何利用HTML和JavaScript实现从远程MP4、本地摄像头及本地上传的MP4文件中截取视频帧,并展示了具体的实现步骤和示例代码。 ... [详细]
  • 本文介绍了如何使用Python爬取妙笔阁小说网仙侠系列中所有小说的信息,并将其保存为TXT和CSV格式。主要内容包括如何构造请求头以避免被网站封禁,以及如何利用XPath解析HTML并提取所需信息。 ... [详细]
  • 本文详细介绍了 Spark 中的弹性分布式数据集(RDD)及其常见的操作方法,包括 union、intersection、cartesian、subtract、join、cogroup 等转换操作,以及 count、collect、reduce、take、foreach、first、saveAsTextFile 等行动操作。 ... [详细]
  • 机器学习算法:SVM(支持向量机)
    SVM算法(SupportVectorMachine,支持向量机)的核心思想有2点:1、如果数据线性可分,那么基于最大间隔的方式来确定超平面,以确保全局最优, ... [详细]
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • 在软件开发过程中,经常需要将多个项目或模块进行集成和调试,尤其是当项目依赖于第三方开源库(如Cordova、CocoaPods)时。本文介绍了如何在Xcode中高效地进行多项目联合调试,分享了一些实用的技巧和最佳实践,帮助开发者解决常见的调试难题,提高开发效率。 ... [详细]
  • 本文详细解析了 Yii2 框架中视图和布局的各种函数,并综述了它们在实际开发中的应用场景。通过深入探讨每个函数的功能和用法,为开发者提供了全面的参考,帮助他们在项目中更高效地利用这些工具。 ... [详细]
  • 本文介绍了三种解决 Git Push 冲突的方法,包括创建新分支、手动解决冲突和强行推送。这些方法适用于不同的开发场景,如版本迭代、多人协作和个人开发。 ... [详细]
  • 本文详细介绍了MySQL故障排除工具及其使用方法,帮助开发者和数据库管理员高效地定位和解决数据库性能问题。 ... [详细]
  • 本文探讨了 Java 中 HttpClient 和 HtmlUnit 的区别,重点介绍了它们的功能和应用场景。 ... [详细]
  • http:blog.csdn.netzeo112140articledetails7675195使用TCPdump工具,抓TCP数据包。将数据包上传到PC,通过Wireshark查 ... [详细]
  • python模块之正则
    re模块可以读懂你写的正则表达式根据你写的表达式去执行任务用re去操作正则正则表达式使用一些规则来检测一些字符串是否符合个人要求,从一段字符串中找到符合要求的内容。在 ... [详细]
author-avatar
丨丶皓月_261
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有