> 文章列表 > 基于java进行收藏功能的实现

基于java进行收藏功能的实现

基于java进行收藏功能的实现

1.首先进行建表

大部分点赞都是文章,帖子,或者商品的收藏,然后登录用户进行收藏,创建表的话需要文章,帖子,或者商品的id和用户的id,我这里是文章postId和ud

2.接下来就是代码层面的实现

ourcontroller层(PostFavAddRequest中放的是文章id)

 @PostMapping("/")public BaseResponse<Integer> doPostFavour(@RequestBody PostFavourAddRequest postFavourAddRequest,HttpServletRequest request) {if (postFavourAddRequest == null || postFavourAddRequest.getPostId() <= 0) {throw new BusinessException(ErrorCode.PARAMS_ERROR);}// 登录才能操作final User loginUser = userService.getLoginUser(request);long postId = postFavourAddRequest.getPostId();int result = postFavourService.doPostFavour(postId, loginUser);return ResultUtils.success(result);}

service层

    int doPostFavour(long postId, User loginUser);

serviceImpl层(用户串行点赞必须加锁)

 @Overridepublic int doPostFavour(long postId, User loginUser) {// 判断是否存在Post post = postService.getById(postId);if (post == null) {throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);}// 是否已帖子收藏long userId = loginUser.getId();// 每个用户串行帖子收藏// 锁必须要包裹住事务方法//在同一个类中,非事务方法A调用事务方法B,事务失效,得采用AopContext.currentProxy().xx()来进行调用,事务才能生效。PostFavourService postFavourService = (PostFavourService) AopContext.currentProxy();synchronized (String.valueOf(userId).intern()) {return postFavourService.doPostFavourInner(userId, postId);}

doPostThumbInner是对数据库进行操作的,实现如下

 /* 帖子收藏(内部服务) @param userId* @param postId* @return*/int doPostFavourInner(long userId, long postId);

 封装了事务的方法,出现错误立即回滚。

大概逻辑就是首先判断首先是否已经进行过收藏,如果已经收藏,当用户在进行收藏时,会取消收藏,首先移除收藏表里的信息,如果移除成功,将post里的收藏数进行更新,收藏数必须大于0才能进行减一操作,修改成功返回-1,失败返回0。如果用户未进行收藏更新post里的收藏数,收藏数进行加一操作

 @Override@Transactional(rollbackFor = Exception.class)public int doPostFavourInner(long userId, long postId) {PostFavour postFavour = new PostFavour();postFavour.setUserId(userId);postFavour.setPostId(postId);QueryWrapper<PostFavour> postFavourQueryWrapper = new QueryWrapper<>(postFavour);PostFavour oldPostFavour = this.getOne(postFavourQueryWrapper);boolean result;// 已收藏if (oldPostFavour != null) {result = this.remove(postFavourQueryWrapper);if (result) {// 帖子收藏数 - 1result = postService.update().eq("id", postId).gt("favourNum", 0).setSql("favourNum = favourNum - 1").update();return result ? -1 : 0;} else {throw new BusinessException(ErrorCode.SYSTEM_ERROR);}} else {// 未帖子收藏result = this.save(postFavour);if (result) {// 帖子收藏数 + 1result = postService.update().eq("id", postId).setSql("favourNum = favourNum + 1").update();return result ? 1 : 0;} else {throw new BusinessException(ErrorCode.SYSTEM_ERROR);}}}

接下来就是如何查看自己的收藏(点赞)的作品,点赞和收藏逻辑一模一样。首先以page的形式展现出来 

controller层(当前登录id即为点赞或者收藏的id)

 @PostMapping("/my/list/page")public BaseResponse<Page<PostVO>> listMyFavourPostByPage(@RequestBody PostQueryRequest postQueryRequest,HttpServletRequest request) {if (postQueryRequest == null) {throw new BusinessException(ErrorCode.PARAMS_ERROR);}User loginUser = userService.getLoginUser(request);long current = postQueryRequest.getCurrent();long size = postQueryRequest.getPageSize();// 限制爬虫ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);Page<Post> postPage = postFavourService.listFavourPostByPage(new Page<>(current, size),postService.getQueryWrapper(postQueryRequest), loginUser.getId());return ResultUtils.success(postService.getPostVOPage(postPage, request));}

getQueryWrapper方法(实际就是拼接sql语句查询)

  public QueryWrapper<Post> getQueryWrapper(PostQueryRequest postQueryRequest) {QueryWrapper<Post> queryWrapper = new QueryWrapper<>();if (postQueryRequest == null) {return queryWrapper;}String searchText = postQueryRequest.getSearchText();String sortField = postQueryRequest.getSortField();String sortOrder = postQueryRequest.getSortOrder();Long id = postQueryRequest.getId();String title = postQueryRequest.getTitle();String content = postQueryRequest.getContent();List<String> tagList = postQueryRequest.getTags();Long userId = postQueryRequest.getUserId();Long notId = postQueryRequest.getNotId();// 拼接查询条件if (StringUtils.isNotBlank(searchText)) {queryWrapper.like("title", searchText).or().like("content", searchText);}queryWrapper.like(StringUtils.isNotBlank(title), "title", title);queryWrapper.like(StringUtils.isNotBlank(content), "content", content);if (CollectionUtils.isNotEmpty(tagList)) {for (String tag : tagList) {queryWrapper.like("tags", "\\"" + tag + "\\"");}}queryWrapper.ne(ObjectUtils.isNotEmpty(notId), "id", notId);queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);queryWrapper.eq("isDelete", false);queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),sortField);return queryWrapper;}

getPostVoPage就是关联查询用户信息以及点赞收藏信息

 public Page<PostVO> getPostVOPage(Page<Post> postPage, HttpServletRequest request) {//获取记录数list集合List<Post> postList = postPage.getRecords();//getTotal()获取记录总数,getRecords()是获取记录数,getCurrent()获取当前页数,getPages()获取总页数Page<PostVO> postVOPage = new Page<>(postPage.getCurrent(), postPage.getSize(), postPage.getTotal());if (CollectionUtils.isEmpty(postList)) {return postVOPage;}// 1. 关联查询用户信息//以userid作为键返回的set集合Set<Long> userIdSet = postList.stream().map(Post::getUserId).collect(Collectors.toSet());//将set集合转换为map键为集合Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream().collect(Collectors.groupingBy(User::getId));// 2. 已登录,获取用户点赞、收藏状态Map<Long, Boolean> postIdHasThumbMap = new HashMap<>();Map<Long, Boolean> postIdHasFavourMap = new HashMap<>();//获得当前登录用户User loginUser = userService.getLoginUserPermitNull(request);if (loginUser != null) {Set<Long> postIdSet = postList.stream().map(Post::getId).collect(Collectors.toSet());loginUser = userService.getLoginUser(request);// 获取点赞QueryWrapper<PostThumb> postThumbQueryWrapper = new QueryWrapper<>();postThumbQueryWrapper.in("postId", postIdSet);postThumbQueryWrapper.eq("userId", loginUser.getId());//获取点赞列表List<PostThumb> postPostThumbList = postThumbMapper.selectList(postThumbQueryWrapper);postPostThumbList.forEach(postPostThumb -> postIdHasThumbMap.put(postPostThumb.getPostId(), true));// 获取收藏QueryWrapper<PostFavour> postFavourQueryWrapper = new QueryWrapper<>();postFavourQueryWrapper.in("postId", postIdSet);postFavourQueryWrapper.eq("userId", loginUser.getId());List<PostFavour> postFavourList = postFavourMapper.selectList(postFavourQueryWrapper);postFavourList.forEach(postFavour -> postIdHasFavourMap.put(postFavour.getPostId(), true));}// 填充信息List<PostVO> postVOList = postList.stream().map(post -> {//将字符串转换为json格式PostVO postVO = PostVO.objToVo(post);Long userId = post.getUserId();User user = null;if (userIdUserListMap.containsKey(userId)) {user = userIdUserListMap.get(userId).get(0);}//设置脱敏后的user设置点赞数和收藏数postVO.setUser(userService.getUserVO(user));//这两个Map是基于postId作为key,psot的信息作为值,在这里根据postId来获取post的值postVO.setHasThumb(postIdHasThumbMap.getOrDefault(post.getId(), false));postVO.setHasFavour(postIdHasFavourMap.getOrDefault(post.getId(), false));return postVO;}).collect(Collectors.toList());postVOPage.setRecords(postVOList);return postVOPage;}

objToVo方法(将post中的json类型Tags转换为字符串)

 public static PostVO objToVo(Post post) {if (post == null) {return null;}PostVO postVO = new PostVO();BeanUtils.copyProperties(post, postVO);//将字符串型的tags转换为json格式postVO.setTagList(GSON.fromJson(post.getTags(), new TypeToken<List<String>>() {}.getType()));return postVO;}

service层

 Page<Post> listFavourPostByPage(IPage<Post> page, Wrapper<Post> queryWrapper,long favourUserId);

serviceimpl层

 @Overridepublic Page<Post> listFavourPostByPage(IPage<Post> page, Wrapper<Post> queryWrapper, long favourUserId) {if (favourUserId <= 0) {return new Page<>();}return baseMapper.listFavourPostByPage(page, queryWrapper, favourUserId);}

MyBatis-Plus 最核心的功能要数通用 Mapper 了,只要我们的 Mapper 接口实现了 BaseMapper,就可以完成单表大部分的 CRUD 操作了,并且它还附带了一个功能强大的条件构造器。

所以此处的baseMapper就是底层mapper,创建了listFavourPostByPage这个方法

在PostFavourMapper中

 Page<Post> listFavourPostByPage(IPage<Post> page, @Param(Constants.WRAPPER) Wrapper<Post> queryWrapper,long favourUserId);

.xml中(对于这样父子查询的sql,首先先执行子sql,然后再执行父sql,对于这个sql,首先查询postId,然后再进行关联查询)

important(关联查询到文章)

 <select id="listFavourPostByPage" resultType="文件路径">select p.*from post pjoin (select postId from post_favour where userId = #{favourUserId}) pfon p.id = pf.postId ${ew.customSqlSegment}</select>

到此为止,就可以获得自己收藏或者点赞的文章了!!