热门标签 | 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)

推荐阅读
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了将mysql从5.6.15升级到5.7.15的详细步骤,包括关闭访问、备份旧库、备份权限、配置文件备份、关闭旧数据库、安装二进制、替换配置文件以及启动新数据库等操作。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
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社区 版权所有