通过”,”切割成数组,并循环
QuestionMapper.xml
文件
这样可以模糊查询通过标签,查出有相同标签的文章
SELECT * from question WHERE id != #{id} and tag regexp #{tag}
把,
替换为|
用于查询
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;
}
categoryName
:上层标签tags
:下层标签get()
方法获取filterInvalid(String tags)
:用来校验传来的标签中标签库里是否存在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;
}
}
String invalid = TagCache.filterInvalid(tag);
if(StringUtils.isNotBlank(invalid)){
model.addAttribute("error", "输入非法标签:"+invalid);
return "publish";
}
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}"
-
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
nameOfType(int type)
方法返回数字对应的信息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 "";
}
}
用来区分回复是已读还是未读
用来在页面上展示对应的数据
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;
}
/comment
到CommentController
执行insert
方法增加一个创建通知的方法,该方法的参数:
Comment
receiver
notifierName
,从Controller
层中传过来,从session
中获取user
outerTitle
notificationType
,回复的是问题Or评论outerId
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);
}
@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());
}
}
可以存入不同类型的集合数据
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
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;
}
public Long unreadCount(Long userId) {
NotificationExample notificatiOnExample= new NotificationExample();
notificationExample.createCriteria().andReceiverEqualTo(userId).andStatusEqualTo(NotificationStatusEnum.UNREAD.getStatus());
return notificationMapper.countByExample(notificationExample);
}
未读
未读数量
我的问题
最新回复
点击后跳转到该问题的question.html
页面
read(id,user)
方法id
为回复对象的Id
,该方法返回这个notificationDTO
对象
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;
}