- 实现,在发帖、点赞、加精、评论时=时将发生变化的帖子存入Redis中。再通过定时任务,每隔一定的时间,计算帖子的分数进行更新。
- 新建PostScoreRefreshJob类进行处理。
- 这里Redis中选择的是Set类型,因为Set数据类型中不允许有重复数据,从而防止了我们存入重复的帖子。
1.RedisKeyUtil
public class RedisKeyUtil {
private static final String SPLIT=":";
private static final String PREFIX_ENTITY_LIKE="like:entity";
private static final String PREFIX_USER_LIKE="like:user";
private static final String PREFIX_FOLLOWEE="followee";
private static final String PREFIX_FOLLOWER="follower";
private static final String PREFIX_KAPTCHA="kaptcha";
private static final String PREFIX_TICKET="ticket";
private static final String PREFIX_USER="user";
private static final String PREFIX_UV="uv";
private static final String PREFIX_DAU="dau";
private static final String PREFIX_POST="post";
//某个实体的赞
//like:entity:entityType:entityId->set(userId)
public static String getEntityLikeKey(int entityType,int entityId){
return PREFIX_ENTITY_LIKE+SPLIT+entityType+SPLIT+entityId;
}
//某个用户的赞
//like:user:userId->int
public static String getUserLikeKey(int userId){
return PREFIX_USER_LIKE+SPLIT+userId;
}
//某个用户关注的实体
//followee:userId:entityType->zset(entityId,now)
public static String getFolloweeKey(int userId,int entityType){
return PREFIX_FOLLOWEE+SPLIT+userId+SPLIT+entityType;
}
//某个实体拥有的粉丝
//follower:entityType:entityId->zset(userId,now)
public static String getFollowerKey(int entityType,int entityId){
return PREFIX_FOLLOWER+SPLIT+entityType+SPLIT+entityId;
}
//登录验证码
public static String getKaptchaKey(String owner){
return PREFIX_KAPTCHA+SPLIT+owner;
}
//登录凭证
public static String getTicketKey(String ticket){
return PREFIX_TICKET+SPLIT+ticket;
}
//用户
public static String getUserKey(int userId){
return PREFIX_USER+SPLIT+userId;
}
//单日UV
public static String getUVKey(String date){
return PREFIX_UV+SPLIT+date;
}
//区间UV
public static String getUVKey(String startDate,String endDate){
return PREFIX_UV+SPLIT+startDate+endDate;
}
//单日活跃用户
public static String getDAUKey(String date){
return PREFIX_DAU+SPLIT+date;
}
//区间活跃用户
public static String getDAUKey(String startDate,String endDate){
return PREFIX_DAU+SPLIT+startDate+SPLIT+endDate;
}
//计算帖子分数
public static String getPostScoreKey(){
return PREFIX_POST+SPLIT+"score";
}
}
2.处理发帖、加精、点赞、评论时的Controller
2.1 DiscussPostController 处理发帖、加精
import com.nowcoder.community.entity.*;
import com.nowcoder.community.event.EventProducer;
import com.nowcoder.community.service.CommentServiceImpl;
import com.nowcoder.community.service.DiscussPostServiceImpl;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.service.UserServiceImpl;
import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.CommunityUtil;
import com.nowcoder.community.util.HostHolder;
import com.nowcoder.community.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@Controller
@RequestMapping("/discuss")
public class DiscussPostController implements CommunityConstant {
@Autowired
private DiscussPostServiceImpl discussPostService;
@Autowired
private HostHolder hostHolder;
@Autowired
private UserServiceImpl userService;
@Autowired
private CommentServiceImpl commentService;
@Autowired
private LikeService likeService;
@Autowired
private EventProducer eventProducer;
@Autowired
private RedisTemplate redisTemplate;
@PostMapping("/add")
@ResponseBody
public String addDiscussPost(String title,String content){
User user = hostHolder.getUser();
if (user==null){
return CommunityUtil.getJSONString(403,"你还没有登陆");
}
DiscussPost discussPost = new DiscussPost();
discussPost.setUserId(user.getId());
discussPost.setTitle(title);
discussPost.setContent(content);
discussPost.setCreateTime(new Date());
discussPostService.addDiscussPost(discussPost);
//触发发帖事件
Event event = new Event()
.setTopic(TOPIC_PUBLISH)
.setEntityType(ENTITY_TYPE_POST)
.setEntityId(discussPost.getId())
.setUserId(user.getId());
eventProducer.fireEvent(event);
//计算帖子分数
String redisKey = RedisKeyUtil.getPostScoreKey();
redisTemplate.opsForSet().add(redisKey,discussPost.getId());
return CommunityUtil.getJSONString(0,"发布成功");
}
@GetMapping("/detail/{discussPostId}")
public String getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model, Page page){
//帖子
DiscussPost post = discussPostService.selectDiscussPostById(discussPostId);
model.addAttribute("post",post);
//作者
User user = userService.selectById(post.getUserId());
model.addAttribute("user",user);
//点赞数量
long likeCount = likeService.selectEntityLikeCount(CommunityConstant.ENTITY_TYPE_POST,discussPostId);
model.addAttribute("likeCount",likeCount);
//点赞状态
int likeStatus=hostHolder.getUser()==null ? 0 : likeService.selectEntityLikeStatus(hostHolder.getUser().getId(),CommunityConstant.ENTITY_TYPE_POST,discussPostId);
model.addAttribute("likeStatus",likeStatus);
//评论分页信息
page.setPath("/discuss/detail/"+discussPostId);
page.setLimit(5);
page.setRows(post.getCommentCount());
//评论:给帖子的评论
//回复:给评论的评论
//评论列表
List<Comment> commentList = commentService.selectCommentByEntity(ENTITY_TYPE_POST, post.getId(), page.getOffset(), page.getLimit());
//评论VO列表
List<Map<String,Object>> commentVoList=new ArrayList<>();
if (commentList!=null){
for (Comment comment : commentList) {
//评论VO
Map<String,Object> commentVo=new HashMap<>();
//评论
commentVo.put("comment",comment);
//作者
commentVo.put("user",userService.selectById(comment.getUserId()));
//点赞数量
likeCount = likeService.selectEntityLikeCount(CommunityConstant.ENTITY_TYPE_COMMENT,comment.getId());
//点赞状态
likeStatus=hostHolder.getUser()==null ? 0 : likeService.selectEntityLikeStatus(hostHolder.getUser().getId(),CommunityConstant.ENTITY_TYPE_COMMENT,comment.getId());
commentVo.put("likeCount",likeCount);
commentVo.put("likeStatus",likeStatus);
//回复列表
List<Comment> replayList = commentService.selectCommentByEntity(ENTITY_TYPE_COMMENT, comment.getId(), 0, Integer.MAX_VALUE);
//回复VO列表
List<Map<String,Object>> replayVoList=new ArrayList<>();
if (replayList!=null){
for (Comment replay : replayList) {
Map<String,Object> replayVo=new HashMap<>();
//回复
replayVo.put("replay",replay);
//作者
replayVo.put("user",userService.selectById(replay.getUserId()));
//回复目标
User target=replay.getTargetId()==0?null:userService.selectById(replay.getTargetId());
replayVo.put("target",target);
//点赞数量
likeCount = likeService.selectEntityLikeCount(CommunityConstant.ENTITY_TYPE_COMMENT,replay.getId());
//点赞状态
likeStatus=hostHolder.getUser()==null ? 0 : likeService.selectEntityLikeStatus(hostHolder.getUser().getId(),CommunityConstant.ENTITY_TYPE_COMMENT,replay.getId());
replayVo.put("likeCount",likeCount);
replayVo.put("likeStatus",likeStatus);
replayVoList.add(replayVo);
}
}
commentVo.put("replays",replayVoList);
//回复数量
int replayCount = commentService.selectCountByEntity(ENTITY_TYPE_COMMENT, comment.getId());
commentVo.put("replayCount",replayCount);
commentVoList.add(commentVo);
}
}
model.addAttribute("comments",commentVoList);
return "/site/discuss-detail";
}
//置顶
@PostMapping("/top")
@ResponseBody
public String setTop(int id){
discussPostService.updateType(id,1);
//触发发帖事件
Event event = new Event()
.setTopic(TOPIC_PUBLISH)
.setEntityType(ENTITY_TYPE_POST)
.setEntityId(id)
.setUserId(hostHolder.getUser().getId());
eventProducer.fireEvent(event);
return CommunityUtil.getJSONString(0);
}
//加精
@PostMapping("/wonderful")
@ResponseBody
public String setWonderful(int id){
discussPostService.updateStatus(id,1);
//触发发帖事件
Event event = new Event()
.setTopic(TOPIC_PUBLISH)
.setEntityType(ENTITY_TYPE_POST)
.setEntityId(id)
.setUserId(hostHolder.getUser().getId());
eventProducer.fireEvent(event);
//计算帖子分数
String redisKey = RedisKeyUtil.getPostScoreKey();
redisTemplate.opsForSet().add(redisKey,id);
return CommunityUtil.getJSONString(0);
}
//删除
@PostMapping("/delete")
@ResponseBody
public String setDelete(int id){
discussPostService.updateStatus(id,2);
//触发发帖事件
Event event = new Event()
.setTopic(TOPIC_DELETE)
.setEntityType(ENTITY_TYPE_POST)
.setEntityId(id)
.setUserId(hostHolder.getUser().getId());
eventProducer.fireEvent(event);
return CommunityUtil.getJSONString(0);
}
}
2.2 LikeController 处理点赞
import com.nowcoder.community.entity.Event;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.event.EventProducer;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.CommunityUtil;
import com.nowcoder.community.util.HostHolder;
import com.nowcoder.community.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@Controller
public class LikeController implements CommunityConstant {
@Autowired
private HostHolder hostHolder;
@Autowired
private LikeService likeService;
@Autowired
private EventProducer eventProducer;
@Autowired
private RedisTemplate redisTemplate;
@PostMapping("/like")
@ResponseBody
public String like(int entityType,int entityId,int entityUserId,int postId){
User user = hostHolder.getUser();
//点赞
likeService.like(user.getId(), entityType,entityId,entityUserId);
//点赞数量
long likeCount = likeService.selectEntityLikeCount(entityType, entityId);
//点赞状态
int likeStatus = likeService.selectEntityLikeStatus(user.getId(), entityType, entityId);
//返回的结果,用Map封装
Map<String,Object> map=new HashMap<>();
map.put("likeCount",likeCount);
map.put("likeStatus",likeStatus);
//触发点赞事件
if (likeStatus==1){
Event event=new Event()
.setTopic(TOPIC_LIKE)
.setUserId(hostHolder.getUser().getId())
.setEntityType(entityType)
.setEntityId(entityId)
.setEntityUserId(entityUserId)
.setData("postId",postId);
eventProducer.fireEvent(event);
}
if (entityType==ENTITY_TYPE_POST){
//计算帖子分数
String redisKey = RedisKeyUtil.getPostScoreKey();
redisTemplate.opsForSet().add(redisKey,postId);
}
return CommunityUtil.getJSONString(0,null,map);
}
}
2.3 CommentController 处理评论
import com.nowcoder.community.entity.Comment;
import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.entity.Event;
import com.nowcoder.community.event.EventProducer;
import com.nowcoder.community.service.CommentServiceImpl;
import com.nowcoder.community.service.DiscussPostServiceImpl;
import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.HostHolder;
import com.nowcoder.community.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Date;
@Controller
@RequestMapping("/comment")
public class CommentController implements CommunityConstant {
@Autowired
private CommentServiceImpl commentService;
@Autowired
private HostHolder hostHolder;
@Autowired
private EventProducer eventProducer;
@Autowired
private DiscussPostServiceImpl discussPostService;
@Autowired
private RedisTemplate redisTemplate;
@PostMapping("/add/{discussPostId}")
public String addComment(@PathVariable("discussPostId") int discussPostId, Comment comment){
comment.setUserId(hostHolder.getUser().getId());
comment.setStatus(0);
comment.setCreateTime(new Date());
commentService.addComment(comment);
//触发评论事件
Event event=new Event()
.setTopic(TOPIC_COMMENT)
.setUserId(hostHolder.getUser().getId())
.setEntityType(comment.getEntityType())
.setEntityId(comment.getEntityId())
.setData("postId",discussPostId);
if (comment.getEntityType()==ENTITY_TYPE_POST){
DiscussPost target = discussPostService.selectDiscussPostById(comment.getEntityId());
event.setEntityUserId(target.getUserId());
}else if (comment.getEntityType()==ENTITY_TYPE_COMMENT){
Comment target = commentService.selectCommentById(comment.getEntityId());
event.setEntityUserId(target.getUserId());
}
eventProducer.fireEvent(event);
if (comment.getEntityType()==ENTITY_TYPE_POST){
//触发发帖事件
event = new Event()
.setTopic(TOPIC_PUBLISH)
.setEntityType(ENTITY_TYPE_POST)
.setEntityId(discussPostId)
.setUserId(hostHolder.getUser().getId());
eventProducer.fireEvent(event);
//计算帖子分数
String redisKey = RedisKeyUtil.getPostScoreKey();
redisTemplate.opsForSet().add(redisKey,discussPostId);
}
return "redirect:/discuss/detail/"+discussPostId;
}
}
3.PostScoreRefreshJob 实现Job接口 刷新计算帖子分数
import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.service.DiscussPostServiceImpl;
import com.nowcoder.community.service.ElasticsearchService;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.RedisKeyUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class PostScoreRefreshJob implements Job, CommunityConstant {
private static final Logger logger= LoggerFactory.getLogger(PostScoreRefreshJob.class);
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private DiscussPostServiceImpl discussPostService;
@Autowired
private LikeService likeService;
@Autowired
private ElasticsearchService elasticsearchService;
// 牛客纪元
private static final Date epoch;
static {
try {
epoch = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2014-08-01 00:00:00");
} catch (ParseException e) {
throw new RuntimeException("初始化牛客纪元失败!", e);
}
}
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String redisKey = RedisKeyUtil.getPostScoreKey();
BoundSetOperations operations = redisTemplate.boundSetOps(redisKey);
if (operations.size()==0){
logger.info("[任务取消] 没有需要刷新的帖子!");
return;
}
logger.info("[任务开始] 正在刷新帖子分数:"+operations.size());
while (operations.size()>0){
this.refresh((Integer) operations.pop());
}
logger.info("[任务结束] 帖子分数刷新完毕!");
}
private void refresh(int postId){
DiscussPost post = discussPostService.selectDiscussPostById(postId);
if (post==null){
logger.error("该帖子不存在:id="+postId);
return;
}
//是否精华
boolean wonderful=post.getStatus()==1;
//评论数量
int commentCount = post.getCommentCount();
//点赞数量
long likeCount = likeService.selectEntityLikeCount(ENTITY_TYPE_POST, postId);
//计算权重
double w=(wonderful ? 75 : 0)+commentCount*10+likeCount*2;
//分数=帖子权重+距离天数
double score=Math.log10(Math.max(w,1))
+(post.getCreateTime().getTime()-epoch.getTime())/(1000*3600*24);
//更新帖子分数
discussPostService.updateScore(postId,score);
//同步搜索数据
post.setScore(score);
elasticsearchService.saveDiscussPost(post);
}
}
4. 配置QuartzConfig 设置定时
import com.nowcoder.community.quartz.AlphaJob;
import com.nowcoder.community.quartz.PostScoreRefreshJob;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
@Configuration
public class QuartzConfig {
//FactoryBean作用:简化bean的实例化过程
//1.通过FactoryBean封装Bean的实例化过程
//2.将FactoryBean装配到spring容器中
//3.将FactoryBean注入给其他的bean
//4.其他的bean即可获得FactoryBean所管理的对象实例
//1.配置jobDetail
// @Bean
public JobDetailFactoryBean alphaJobDetail() {
JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
factoryBean.setJobClass(AlphaJob.class); //声明要配置的job类
factoryBean.setName("alphaJob"); //声明job的名称
factoryBean.setGroup("alphaJobGroup"); //声明job的分组
factoryBean.setDurability(true); //job是否长久的存在
factoryBean.setRequestsRecovery(true); //job是否可被恢复
return factoryBean;
}
//2.配置trigger
// SimpleTriggerFactoryBean:简单的定时
// CronTriggerFactoryBean:可实现复杂的定时,如每年的1号进行清除
// @Bean
public SimpleTriggerFactoryBean alphaTrigger(JobDetail alphaJobDetail) {
SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
factoryBean.setJobDetail(alphaJobDetail); //确定JobDetail
factoryBean.setName("alphaTrigger"); //Trigger的名称
factoryBean.setGroup("alphaTriggerGroup"); //Trigger的分组
factoryBean.setRepeatInterval(3000); //时间间隔3秒
factoryBean.setJobDataMap(new JobDataMap()); //保存数据的类型
return factoryBean;
}
//刷新帖子分数任务
@Bean
public JobDetailFactoryBean postScoreRefreshJobDetail() {
JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
factoryBean.setJobClass(PostScoreRefreshJob.class); //声明要配置的job类
factoryBean.setName("postScoreRefreshJob"); //声明job的名称
factoryBean.setGroup("communityJobGroup"); //声明job的分组
factoryBean.setDurability(true); //job是否长久的存在
factoryBean.setRequestsRecovery(true); //job是否可被恢复
return factoryBean;
}
@Bean
public SimpleTriggerFactoryBean postScoreRefreshTrigger(JobDetail postScoreRefreshJobDetail) {
SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
factoryBean.setJobDetail(postScoreRefreshJobDetail); //确定JobDetail
factoryBean.setName("postScoreRefreshTrigger"); //Trigger的名称
factoryBean.setGroup("communityTriggerGroup"); //Trigger的分组
factoryBean.setRepeatInterval(1000*60*5); //时间间隔3秒
factoryBean.setJobDataMap(new JobDataMap()); //保存数据的类型
return factoryBean;
}
}
5.修改DiscussPostMapper的selectDiscussPosts方法,实现按照分数排序,同时修改调用该方法的地方
5.1 DiscussPostMapper
import com.nowcoder.community.entity.DiscussPost;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface DiscussPostMapper {
List<DiscussPost> selectDiscussPosts(int userId,int offset,int limit,int orderMode);
//@Param注解用于给参数取别名
//如果只有一个参数,并且在<if>里使用,则必须加别名
int selectDiscussPostRows(@Param("userId") int userId);
int insertDiscussPost(DiscussPost discussPost);
DiscussPost selectDiscussPostById(int id);
int updateCommentCount(int id,int commentCount);
int updateType(int id,int type);
int updateStatus(int id,int status);
int updateScore(int id,double score);
}
5.2 DiscussPostMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nowcoder.community.mapper.DiscussPostMapper">
<select id="selectDiscussPosts" resultType="DiscussPost">
select * from discuss_post
where status!=2
<if test="userId!=0">
and user_id=#{userId}
</if>
<if test="orderMode==0">
order by type desc,create_time desc
</if>
<if test="orderMode==1">
order by type desc,score desc,create_Time desc
</if>
limit #{offset},#{limit};
</select>
<select id="selectDiscussPostRows" resultType="int">
select count(id) from discuss_post
where status!=2
<if test="userId!=0">
and user_id=#{userId}
</if>
</select>
<insert id="insertDiscussPost" parameterType="DiscussPost" keyProperty="id">
insert into discuss_post(user_id, title, content, type, status, create_time, comment_count, score) VALUES (#{userId},#{title},#{content},#{type},#{status},#{createTime},#{commentCount},#{score});
</insert>
<select id="selectDiscussPostById" resultType="DiscussPost">
select * from discuss_post where id=#{id};
</select>
<update id="updateCommentCount">
update discuss_post set comment_count=#{commentCount} where id=#{id};
</update>
<update id="updateType">
update discuss_post set type=#{type} where id=#{id}
</update>
<update id="updateStatus">
update discuss_post set status=#{status} where id=#{id}
</update>
<update id="updateScore">
update discuss_post set score=#{score} where id=#{id}
</update>
</mapper>
5.3 DiscussPostService
import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.mapper.DiscussPostMapper;
import com.nowcoder.community.util.SensitiveFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.util.HtmlUtils;
import java.util.List;
@Service
public class DiscussPostServiceImpl implements DiscussPostService{
@Autowired
private DiscussPostMapper discussPostMapper;
@Autowired
private SensitiveFilter sensitiveFilter;
@Override
public List<DiscussPost> selectDiscussPosts(int userId, int offset, int limit,int orderMode) {
return discussPostMapper.selectDiscussPosts(userId, offset, limit,orderMode);
}
@Override
public int selectDiscussPostRows(int userId) {
return discussPostMapper.selectDiscussPostRows(userId);
}
@Override
public int insertDiscussPost(DiscussPost discussPost) {
return discussPostMapper.insertDiscussPost(discussPost);
}
@Override
public DiscussPost selectDiscussPostById(int id) {
return discussPostMapper.selectDiscussPostById(id);
}
@Override
public int updateCommentCount(int id, int commentCount) {
return discussPostMapper.updateCommentCount(id, commentCount);
}
@Override
public int updateType(int id, int type) {
return discussPostMapper.updateType(id, type);
}
@Override
public int updateStatus(int id, int status) {
return discussPostMapper.updateStatus(id, status);
}
@Override
public int updateScore(int id, double score) {
return discussPostMapper.updateScore(id, score);
}
public int addDiscussPost(DiscussPost discussPost){
if (discussPost==null){
throw new IllegalArgumentException("参数不能为空!");
}
//转移HTML标记
discussPost.setTitle(HtmlUtils.htmlEscape(discussPost.getTitle()));
discussPost.setContent(HtmlUtils.htmlEscape(discussPost.getContent()));
//过滤敏感词
discussPost.setTitle(sensitiveFilter.filter(discussPost.getTitle()));
discussPost.setContent(sensitiveFilter.filter(discussPost.getContent()));
return discussPostMapper.insertDiscussPost(discussPost);
}
}
5.4 HomeController
import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.entity.Page;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.service.DiscussPostServiceImpl;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.service.UserServiceImpl;
import com.nowcoder.community.util.CommunityConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
public class HomeController implements CommunityConstant {
@Autowired
private DiscussPostServiceImpl discussPostService;
@Autowired
private UserServiceImpl userService;
@Autowired
private LikeService likeService;
@GetMapping("/index")
public String getIndexPage(Model model, Page page,@RequestParam(name = "orderMode",defaultValue = "0") int orderMode)
{
page.setRows(discussPostService.selectDiscussPostRows(0));
page.setPath("/index?orderMode="+orderMode);
List<DiscussPost> list = discussPostService.selectDiscussPosts(0, page.getOffset(), page.getLimit(),orderMode);
List<Map<String,Object>> discussPosts=new ArrayList<>();
if (list!=null){
for (DiscussPost post : list) {
Map<String,Object> map=new HashMap<>();
map.put("post",post);
User user = userService.selectById(post.getUserId());
map.put("user",user);
long likeCount = likeService.selectEntityLikeCount(ENTITY_TYPE_POST, post.getId());
map.put("likeCount",likeCount);
discussPosts.add(map);
}
}
model.addAttribute("discussPosts",discussPosts);
model.addAttribute("orderMode",orderMode);
return "index";
}
@GetMapping("/error")
public String getErrorPage(){
return "/error/500";
}
@GetMapping("/denied")
public String getDeniedPage(){
return "/error/404";
}
}
6.index.html
<!-- 筛选条件 -->
<ul class="nav nav-tabs mb-3">
<li class="nav-item">
<a th:class="|nav-link ${orderMode==0?'active':''}|" th:href="@{/index(orderMode=0)}">最新</a>
</li>
<li class="nav-item">
<a th:class="|nav-link ${orderMode==1?'active':''}|" th:href="@{/index(orderMode=1)}">最热</a>
</li>
</ul>