课程说明

  • 点赞消息列表
  • 喜欢消息列表
  • 评论消息列表
  • 公告列表
  • 个人主页
  • 聊一下功能
  • 谁看过我的功能

    1、消息点赞、喜欢、评论列表

    在消息模块中的点赞、喜欢、评论列表,是别人对自己发布的内容的操作,其实现基本一致,所以在一起实现。
    效果:
    day07-完善消息功能以及个人主页 - 图1
    点赞列表接口地址:https://mock-java.itheima.net/project/35/interface/api/779
    评论列表接口地址:https://mock-java.itheima.net/project/35/interface/api/785
    喜欢列表接口地址:https://mock-java.itheima.net/project/35/interface/api/791

    1.1、dubbo服务

    1.1.1、定义接口

    1. //com.tanhua.dubbo.server.api.QuanZiApi
    2. /**
    3. * 查询对我的点赞消息列表
    4. *
    5. * @return
    6. */
    7. PageInfo<Comment> queryLikeCommentListByUser(Long userId, Integer page, Integer pageSize);
    8. /**
    9. * 查询对我的喜欢消息列表
    10. *
    11. * @return
    12. */
    13. PageInfo<Comment> queryLoveCommentListByUser(Long userId, Integer page, Integer pageSize);
    14. /**
    15. * 查询对我的评论消息列表
    16. *
    17. * @return
    18. */
    19. PageInfo<Comment> queryCommentListByUser(Long userId, Integer page, Integer pageSize);

    1.1.2、编写实现

    1. //com.tanhua.dubbo.server.api.QuanziApiImpl
    2. @Override
    3. public PageInfo<Comment> queryLikeCommentListByUser(Long userId, Integer page, Integer pageSize) {
    4. return this.queryCommentListByUser(userId, CommentType.LIKE, page, pageSize);
    5. }
    6. @Override
    7. public PageInfo<Comment> queryLoveCommentListByUser(Long userId, Integer page, Integer pageSize) {
    8. return this.queryCommentListByUser(userId, CommentType.LOVE, page, pageSize);
    9. }
    10. @Override
    11. public PageInfo<Comment> queryCommentListByUser(Long userId, Integer page, Integer pageSize) {
    12. return this.queryCommentListByUser(userId, CommentType.COMMENT, page, pageSize);
    13. }
    14. private PageInfo<Comment> queryCommentListByUser(Long userId, CommentType commentType, Integer page, Integer pageSize) {
    15. PageRequest pageRequest = PageRequest.of(page - 1, pageSize,
    16. Sort.by(Sort.Order.desc("created")));
    17. Query query = new Query(Criteria
    18. .where("publishUserId").is(userId)
    19. .and("commentType").is(commentType.getType())).with(pageRequest);
    20. List<Comment> commentList = this.mongoTemplate.find(query, Comment.class);
    21. PageInfo<Comment> pageInfo = new PageInfo<>();
    22. pageInfo.setPageNum(page);
    23. pageInfo.setPageSize(pageSize);
    24. pageInfo.setRecords(commentList);
    25. return pageInfo;
    26. }

    1.2、APP接口服务

    1.2.1、MessageCommentVo

    根据接口定义vo对象。
    1. package com.tanhua.server.vo;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. @Data
    6. @NoArgsConstructor
    7. @AllArgsConstructor
    8. public class MessageCommentVo {
    9. private String id;
    10. private String avatar;
    11. private String nickname;
    12. private String createDate; //格式:2019-09-08 10:07
    13. }

    1.2.3、IMController

    1. //com.tanhua.server.controller.IMController
    2. /**
    3. * 查询消息点赞列表
    4. *
    5. * @param page
    6. * @param pageSize
    7. * @return
    8. */
    9. @GetMapping("likes")
    10. public ResponseEntity<PageResult> queryLikeCommentList(@RequestParam(value = "page", defaultValue = "1") Integer page,
    11. @RequestParam(value = "pagesize", defaultValue = "10") Integer pageSize) {
    12. try {
    13. PageResult pageResult = this.imService.queryLikeCommentList(page, pageSize);
    14. return ResponseEntity.ok(pageResult);
    15. } catch (Exception e) {
    16. log.error("查询点赞列表失败~ ", e);
    17. }
    18. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    19. }
    20. /**
    21. * 查询消息评论列表
    22. *
    23. * @param page
    24. * @param pageSize
    25. * @return
    26. */
    27. @GetMapping("comments")
    28. public ResponseEntity<PageResult> queryUserCommentList(@RequestParam(value = "page", defaultValue = "1") Integer page,
    29. @RequestParam(value = "pagesize", defaultValue = "10") Integer pageSize) {
    30. try {
    31. PageResult pageResult = this.imService.queryUserCommentList(page, pageSize);
    32. return ResponseEntity.ok(pageResult);
    33. } catch (Exception e) {
    34. log.error("查询评论列表失败~ ", e);
    35. }
    36. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    37. }
    38. /**
    39. * 查询消息喜欢列表
    40. *
    41. * @param page
    42. * @param pageSize
    43. * @return
    44. */
    45. @GetMapping("loves")
    46. public ResponseEntity<PageResult> queryLoveCommentList(@RequestParam(value = "page", defaultValue = "1") Integer page,
    47. @RequestParam(value = "pagesize", defaultValue = "10") Integer pageSize) {
    48. try {
    49. PageResult pageResult = this.imService.queryLoveCommentList(page, pageSize);
    50. return ResponseEntity.ok(pageResult);
    51. } catch (Exception e) {
    52. log.error("查询喜欢列表失败~ ", e);
    53. }
    54. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    55. }

    1.2.4、IMService

    1. //com.tanhua.server.service.IMService
    2. public PageResult queryLikeCommentList(Integer page, Integer pageSize) {
    3. User user = UserThreadLocal.get();
    4. PageInfo<Comment> pageInfo = this.quanZiApi.queryLikeCommentListByUser(user.getId(), page, pageSize);
    5. return this.fillUserCommentList(pageInfo);
    6. }
    7. public PageResult queryLoveCommentList(Integer page, Integer pageSize) {
    8. User user = UserThreadLocal.get();
    9. PageInfo<Comment> pageInfo = this.quanZiApi.queryLoveCommentListByUser(user.getId(), page, pageSize);
    10. return this.fillUserCommentList(pageInfo);
    11. }
    12. public PageResult queryUserCommentList(Integer page, Integer pageSize) {
    13. User user = UserThreadLocal.get();
    14. PageInfo<Comment> pageInfo = this.quanZiApi.queryCommentListByUser(user.getId(), page, pageSize);
    15. return this.fillUserCommentList(pageInfo);
    16. }
    17. private PageResult fillUserCommentList(PageInfo<Comment> pageInfo){
    18. PageResult pageResult = new PageResult();
    19. pageResult.setPage(pageInfo.getPageNum());
    20. pageResult.setPagesize(pageInfo.getPageSize());
    21. List<Comment> records = pageInfo.getRecords();
    22. if(CollUtil.isEmpty(records)){
    23. //没有查询到数据
    24. return pageResult;
    25. }
    26. List<Object> userIdList = CollUtil.getFieldValues(records, "userId");
    27. List<UserInfo> userInfoList = this.userInfoService.queryUserInfoByUserIdList(userIdList);
    28. List<MessageCommentVo> messageCommentVoList = new ArrayList<>();
    29. for (Comment comment : records) {
    30. for (UserInfo userInfo : userInfoList) {
    31. if(ObjectUtil.equals(comment.getUserId(), userInfo.getUserId())){
    32. MessageCommentVo messageCommentVo = new MessageCommentVo();
    33. messageCommentVo.setId(comment.getId().toHexString());
    34. messageCommentVo.setAvatar(userInfo.getLogo());
    35. messageCommentVo.setNickname(userInfo.getNickName());
    36. messageCommentVo.setCreateDate(DateUtil.format(new Date(comment.getCreated()), "yyyy-MM-dd HH:mm"));
    37. messageCommentVoList.add(messageCommentVo);
    38. break;
    39. }
    40. }
    41. }
    42. pageResult.setItems(messageCommentVoList);
    43. return pageResult;
    44. }

    1.3、测试

    day07-完善消息功能以及个人主页 - 图2

    2、公告列表

    公告是后台系统对所有用户发布的公告消息。
    效果:
    day07-完善消息功能以及个人主页 - 图3
    接口地址:https://mock-java.itheima.net/project/35/interface/api/797

    2.1、表结构

    1. CREATE TABLE `tb_announcement` (
    2. `id` bigint(20) NOT NULL AUTO_INCREMENT,
    3. `title` varchar(200) DEFAULT NULL COMMENT '标题',
    4. `description` text COMMENT '描述',
    5. `created` datetime DEFAULT NULL,
    6. `updated` datetime DEFAULT NULL,
    7. PRIMARY KEY (`id`),
    8. KEY `created` (`created`)
    9. ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='公告表';
    1. --插入数据
    2. INSERT INTO `tb_announcement` (`id`, `title`, `description`, `created`, `updated`) VALUES ('1', '探花新版本上线发布啦~,盛夏high趴开始了,赶紧来报名吧!', '探花App2019年7月23日起在苹果商店…,浓情夏日,清爽一聚,探花将吧大家聚…', '2019-10-14 11:06:34', '2019-10-14 11:06:37');
    3. INSERT INTO `tb_announcement` (`id`, `title`, `description`, `created`, `updated`) VALUES ('2', '探花交友的圈子功能正式上线啦~~', '探花交友的圈子功能正式上线啦,欢迎使用~', '2019-10-14 11:09:31', '2019-10-14 11:09:33');
    4. INSERT INTO `tb_announcement` (`id`, `title`, `description`, `created`, `updated`) VALUES ('3', '国庆放假期间,探花交友正常使用~', '国庆放假期间,探花交友正常使用~', '2019-10-14 11:10:01', '2019-10-14 11:10:04');

    2.2、pojo

    1. package com.tanhua.common.pojo;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. @Data
    6. @NoArgsConstructor
    7. @AllArgsConstructor
    8. public class Announcement extends BasePojo {
    9. private Long id;
    10. private String title;
    11. private String description;
    12. }

    2.3、AnnouncementMapper

    1. package com.tanhua.common.mapper;
    2. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    3. import com.tanhua.common.pojo.Announcement;
    4. public interface AnnouncementMapper extends BaseMapper<Announcement> {
    5. }

    2.4、AnnouncementService

    1. package com.tanhua.server.service;
    2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    3. import com.baomidou.mybatisplus.core.metadata.IPage;
    4. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    5. import com.tanhua.common.mapper.AnnouncementMapper;
    6. import com.tanhua.common.pojo.Announcement;
    7. import org.springframework.beans.factory.annotation.Autowired;
    8. import org.springframework.stereotype.Service;
    9. @Service
    10. public class AnnouncementService {
    11. @Autowired
    12. private AnnouncementMapper announcementMapper;
    13. public IPage<Announcement> queryList(Integer page, Integer pageSize) {
    14. QueryWrapper queryWrapper = new QueryWrapper();
    15. queryWrapper.orderByDesc("created");
    16. return this.announcementMapper.selectPage(new Page<Announcement>(page, pageSize), queryWrapper);
    17. }
    18. }

    2.5、定义vo对象

    1. package com.tanhua.server.vo;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. @Data
    6. @NoArgsConstructor
    7. @AllArgsConstructor
    8. public class AnnouncementVo {
    9. private String id;
    10. private String title;
    11. private String description;
    12. private String createDate;
    13. }

    2.6、IMController

    1. /**
    2. * 查询公告列表
    3. *
    4. * @param page
    5. * @param pageSize
    6. * @return
    7. */
    8. @GetMapping("announcements")
    9. @NoAuthorization //优化,无需进行token校验
    10. public ResponseEntity<PageResult> queryMessageAnnouncementList(@RequestParam(value = "page", defaultValue = "1") Integer page,
    11. @RequestParam(value = "pagesize", defaultValue = "10") Integer pageSize) {
    12. try {
    13. PageResult pageResult = this.imService.queryMessageAnnouncementList(page, pageSize);
    14. return ResponseEntity.ok(pageResult);
    15. } catch (Exception e) {
    16. log.error("查询公告列表失败~ ", e);
    17. }
    18. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    19. }

    2.7、IMService

    1. public PageResult queryMessageAnnouncementList(Integer page, Integer pageSize) {
    2. IPage<Announcement> announcementPage = this.announcementService.queryList(page, pageSize);
    3. List<AnnouncementVo> announcementVoList = new ArrayList<>();
    4. for (Announcement record : announcementPage.getRecords()) {
    5. AnnouncementVo announcementVo = new AnnouncementVo();
    6. announcementVo.setId(record.getId().toString());
    7. announcementVo.setTitle(record.getTitle());
    8. announcementVo.setDescription(record.getDescription());
    9. announcementVo.setCreateDate(DateUtil.format(record.getCreated(), "yyyy-MM-dd HH:mm"));
    10. announcementVoList.add(announcementVo);
    11. }
    12. PageResult pageResult = new PageResult();
    13. pageResult.setPage(page);
    14. pageResult.setPagesize(pageSize);
    15. pageResult.setItems(announcementVoList);
    16. return pageResult;
    17. }

    2.8、测试

    day07-完善消息功能以及个人主页 - 图4

    3、个人主页

    点击首页的今日佳人或任意推荐人的图片就会进入个人主页页面,效果如下:
    day07-完善消息功能以及个人主页 - 图5
    在个人主页的页面中,会显示出个人信息、缘分值、个人相册等内容。

    3.1、个人信息

    3.1.1、dubbo服务

    需要在dubbo服务中提供查询缘分值的接口服务。
    3.1.1.1、定义接口
    1. //com.tanhua.dubbo.server.api.RecommendUserApi
    2. /**
    3. * 查询推荐好友的缘分值
    4. *
    5. * @param userId 好友的id
    6. * @param toUserId 我的id
    7. * @return
    8. */
    9. Double queryScore(Long userId, Long toUserId);
    3.1.1.2、实现接口
    1. //com.tanhua.dubbo.server.api.RecommendUserApiImpl
    2. @Override
    3. public Double queryScore(Long userId, Long toUserId) {
    4. Query query = Query.query(Criteria.where("toUserId").is(toUserId)
    5. .and("userId").is(userId));
    6. RecommendUser recommendUser = this.mongoTemplate.findOne(query, RecommendUser.class);
    7. if (null != recommendUser) {
    8. return recommendUser.getScore();
    9. }
    10. return null;
    11. }

    3.1.2、APP接口服务

    接口地址:https://mock-java.itheima.net/project/35/interface/api/629

    说明:该接口的返回值接口与今日佳人的结构一致,所以可以通用今日佳人的对象。

3.1.2.1、TanHuaController
  1. package com.tanhua.server.controller;
  2. import com.tanhua.server.service.TanHuaService;
  3. import com.tanhua.server.vo.TodayBest;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.http.HttpStatus;
  6. import org.springframework.http.ResponseEntity;
  7. import org.springframework.web.bind.annotation.GetMapping;
  8. import org.springframework.web.bind.annotation.PathVariable;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RestController;
  11. @RequestMapping("tanhua")
  12. @RestController
  13. public class TanHuaController {
  14. @Autowired
  15. private TanHuaService tanHuaService;
  16. /**
  17. * 查询个人主页的个人信息
  18. *
  19. * @param userId
  20. * @return
  21. */
  22. @GetMapping("{id}/personalInfo")
  23. public ResponseEntity<TodayBest> queryUserInfo(@PathVariable("id") Long userId) {
  24. try {
  25. TodayBest todayBest = this.tanHuaService.queryUserInfo(userId);
  26. return ResponseEntity.ok(todayBest);
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. }
  30. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  31. }
  32. }

3.1.2.2、TanHuaService
  1. package com.tanhua.server.service;
  2. import cn.hutool.core.convert.Convert;
  3. import cn.hutool.core.util.ObjectUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.tanhua.common.pojo.User;
  6. import com.tanhua.common.pojo.UserInfo;
  7. import com.tanhua.common.utils.UserThreadLocal;
  8. import com.tanhua.server.vo.TodayBest;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.stereotype.Service;
  11. @Service
  12. public class TanHuaService {
  13. @Autowired
  14. private UserInfoService userInfoService;
  15. @Autowired
  16. private RecommendUserService recommendUserService;
  17. public TodayBest queryUserInfo(Long userId) {
  18. UserInfo userInfo = this.userInfoService.queryUserInfoByUserId(userId);
  19. if(ObjectUtil.isEmpty(userInfo)){
  20. return null;
  21. }
  22. TodayBest todayBest = new TodayBest();
  23. todayBest.setId(userId);
  24. todayBest.setAge(userInfo.getAge());
  25. todayBest.setGender(userInfo.getSex().name().toLowerCase());
  26. todayBest.setNickname(userInfo.getNickName());
  27. todayBest.setTags(Convert.toStrArray(StrUtil.split(userInfo.getTags(),',')));
  28. todayBest.setAvatar(userInfo.getLogo());
  29. //缘分值
  30. User user = UserThreadLocal.get();
  31. todayBest.setFateValue(this.recommendUserService.queryScore(userId, user.getId()).longValue());
  32. return todayBest;
  33. }
  34. }

3.1.2.3、RecommendUserService
  1. //com.tanhua.server.service.RecommendUserService
  2. /**
  3. * 查询推荐好友的缘分值
  4. *
  5. * @param userId
  6. * @param toUserId
  7. * @return
  8. */
  9. public Double queryScore(Long userId, Long toUserId){
  10. Double score = this.recommendUserApi.queryScore(userId, toUserId);
  11. if(ObjectUtil.isNotEmpty(score)){
  12. return score;
  13. }
  14. //默认值
  15. return 98d;
  16. }

3.1.3、测试

day07-完善消息功能以及个人主页 - 图6
day07-完善消息功能以及个人主页 - 图7

3.2、个人相册

3.2.1、dubbo服务

3.2.1.1、定义接口
  1. //com.tanhua.dubbo.server.api.QuanZiApi
  2. /**
  3. * 查询相册表
  4. *
  5. * @param userId
  6. * @param page
  7. * @param pageSize
  8. * @return
  9. */
  10. PageInfo<Publish> queryAlbumList(Long userId, Integer page, Integer pageSize);

3.2.1.2、实现接口
  1. //com.tanhua.dubbo.server.api.QuanZiApiImpl
  2. @Override
  3. public PageInfo<Publish> queryAlbumList(Long userId, Integer page, Integer pageSize) {
  4. PageInfo<Publish> pageInfo = new PageInfo<>();
  5. pageInfo.setPageNum(page);
  6. pageInfo.setPageSize(pageSize);
  7. PageRequest pageRequest = PageRequest.of(page - 1 , pageSize,
  8. Sort.by(Sort.Order.desc("created")));
  9. Query query = new Query().with(pageRequest);
  10. //查询自己的相册表
  11. List<Album> albumList = this.mongoTemplate.find(query, Album.class, "quanzi_album_" + userId);
  12. if(CollUtil.isEmpty(albumList)){
  13. return pageInfo;
  14. }
  15. List<Object> publishIdList = CollUtil.getFieldValues(albumList, "publishId");
  16. Query queryPublish = Query.query(Criteria.where("id").in(publishIdList))
  17. .with(Sort.by(Sort.Order.desc("created")));
  18. List<Publish> publishList = this.mongoTemplate.find(queryPublish, Publish.class);
  19. pageInfo.setRecords(publishList);
  20. return pageInfo;
  21. }

3.2.2、APP接口服务

接口文档地址:https://mock-java.itheima.net/project/35/interface/api/689

3.2.2.1、QuanZiController
  1. //com.tanhua.server.controller.QuanZiController
  2. /**
  3. * 自己的所有动态
  4. *
  5. * @return
  6. */
  7. @GetMapping("all")
  8. public ResponseEntity<PageResult> queryAlbumList(@RequestParam(value = "page", defaultValue = "1") Integer page,
  9. @RequestParam(value = "pagesize", defaultValue = "10") Integer pageSize,
  10. @RequestParam(value = "userId") Long userId) {
  11. try {
  12. PageResult pageResult = this.quanZiService.queryAlbumList(userId, page, pageSize);
  13. return ResponseEntity.ok(pageResult);
  14. } catch (Exception e) {
  15. e.printStackTrace();
  16. }
  17. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  18. }

3.2.2.2、QuanZiService
  1. //com.tanhua.server.service.QuanZiService
  2. public PageResult queryAlbumList(Long userId, Integer page, Integer pageSize) {
  3. PageResult pageResult = new PageResult();
  4. pageResult.setPage(page);
  5. pageResult.setPagesize(pageSize);
  6. //查询数据
  7. PageInfo<Publish> pageInfo = this.quanZiApi.queryAlbumList(userId, page, pageSize);
  8. if(CollUtil.isEmpty(pageInfo.getRecords())){
  9. return pageResult;
  10. }
  11. //填充数据
  12. pageResult.setItems(this.fillQuanZiVo(pageInfo.getRecords()));
  13. return pageResult;
  14. }

3.2.3、测试

day07-完善消息功能以及个人主页 - 图8
day07-完善消息功能以及个人主页 - 图9

3.3、整合测试

day07-完善消息功能以及个人主页 - 图10

4、聊一下

在个人主页中,点击聊一下按钮,会弹出回答问题窗口,输入答案后,系统会向对方发送一条陌聊消息,如果对方在陌聊消息中点击聊一下,他们就会成为好友。
用户1在用户2的个人主页中点击“聊一下”,流程如下:
day07-完善消息功能以及个人主页 - 图11

4.1、陌聊问题

点击聊一下时,需要显示出问题,所以需要在mysql中存储用户的问题。

4.1.1、表结构

  1. CREATE TABLE `tb_question` (
  2. `id` bigint(20) NOT NULL AUTO_INCREMENT,
  3. `user_id` bigint(20) DEFAULT NULL COMMENT '用户id',
  4. `txt` varchar(200) DEFAULT NULL COMMENT '问题内容',
  5. `created` datetime DEFAULT NULL,
  6. `updated` datetime DEFAULT NULL,
  7. PRIMARY KEY (`id`),
  8. KEY `user_id` (`user_id`)
  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

4.1.2、Question实体对象

在my-tanhua-common工程中完成。

  1. package com.tanhua.common.pojo;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. @Data
  6. @NoArgsConstructor
  7. @AllArgsConstructor
  8. public class Question extends BasePojo {
  9. private Long id;
  10. private Long userId;
  11. //问题内容
  12. private String txt;
  13. }

4.1.3、QuestionMapper

在my-tanhua-common工程中完成。

  1. package com.tanhua.common.mapper;
  2. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  3. import com.tanhua.common.pojo.Question;
  4. public interface QuestionMapper extends BaseMapper<Question> {
  5. }

4.1.4、QuestionService

在my-tanhua-server工程中完成。

  1. package com.tanhua.server.service;
  2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  3. import com.tanhua.common.mapper.QuestionMapper;
  4. import com.tanhua.common.pojo.Question;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Service;
  7. @Service
  8. public class QuestionService {
  9. @Autowired
  10. private QuestionMapper questionMapper;
  11. public Question queryQuestion(Long userId) {
  12. QueryWrapper queryWrapper = new QueryWrapper();
  13. queryWrapper.eq("user_id", userId);
  14. return this.questionMapper.selectOne(queryWrapper);
  15. }
  16. }

4.2、APP接口服务

接口地址:https://mock-java.itheima.net/project/35/interface/api/635

4.2.1、TanHuaController

  1. //com.tanhua.server.controller.TanHuaController
  2. /**
  3. * 查询陌生人问题
  4. *
  5. * @param userId
  6. * @return
  7. */
  8. @GetMapping("strangerQuestions")
  9. public ResponseEntity<String> queryQuestion(@RequestParam("userId") Long userId) {
  10. try {
  11. String question = this.tanHuaService.queryQuestion(userId);
  12. return ResponseEntity.ok(question);
  13. } catch (Exception e) {
  14. e.printStackTrace();
  15. }
  16. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  17. }

4.2.2、TanHuaService

  1. //com.tanhua.server.service.TanHuaService
  2. public String queryQuestion(Long userId) {
  3. Question question = this.questionService.queryQuestion(userId);
  4. if(ObjectUtil.isNotEmpty(question)){
  5. return question.getTxt();
  6. }
  7. //默认的问题
  8. return "你的爱好是什么?";
  9. }

4.2.3、测试

day07-完善消息功能以及个人主页 - 图12

4.3、回复陌生人问题

点击问题窗口中的“聊一下”,需要通过admin权限发送系统消息。

4.3.1、dubbo服务

4.3.1.1、定义接口
  1. //com.tanhua.dubbo.server.api.HuanXinApi
  2. /**
  3. * 以管理员身份发送消息
  4. * 文档地址:http://docs-im.easemob.com/im/server/basics/messages#%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF
  5. *
  6. * @param targetUserName 发送目标的用户名
  7. * @param huanXinMessageType 消息类型
  8. * @param msg
  9. * @return
  10. */
  11. Boolean sendMsgFromAdmin(String targetUserName, HuanXinMessageType huanXinMessageType, String msg);
  1. package com.tanhua.dubbo.server.enums;
  2. /**
  3. * 消息类型;txt:文本消息,img:图片消息,loc:位置消息,audio:语音消息,video:视频消息,file:文件消息
  4. */
  5. public enum HuanXinMessageType {
  6. TXT("txt"), IMG("img"), LOC("loc"), AUDIO("audio"), VIDEO("video"), FILE("file");
  7. String type;
  8. HuanXinMessageType(String type) {
  9. this.type = type;
  10. }
  11. public String getType() {
  12. return type;
  13. }
  14. }

4.3.1.2、实现接口
  1. //com.tanhua.dubbo.server.api.HuanXinApiImpl
  2. @Override
  3. public Boolean sendMsgFromAdmin(String targetUserName, HuanXinMessageType huanXinMessageType, String msg) {
  4. String targetUrl = this.huanXinConfig.getUrl()
  5. + this.huanXinConfig.getOrgName() + "/"
  6. + this.huanXinConfig.getAppName() + "/messages";
  7. try {
  8. //{"target_type": "users","target": ["user2","user3"],"msg": {"type": "txt","msg": "testmessage"},"from": "user1"}
  9. String body = JSONUtil.createObj()
  10. .set("target_type", "users")
  11. .set("target", JSONUtil.createArray().set(targetUserName))
  12. .set("msg", JSONUtil.createObj()
  13. .set("type", huanXinMessageType.getType())
  14. .set("msg", msg)).toString();
  15. //表示消息发送者;无此字段Server会默认设置为“from”:“admin”,有from字段但值为空串(“”)时请求失败
  16. // .set("from", "")
  17. return this.requestService.execute(targetUrl, body, Method.POST).isOk();
  18. } catch (Exception e) {
  19. log.error("发送消息失败~ targetUserName = " + targetUserName+", type = " + huanXinMessageType.getType()+", msg = " + msg, e);
  20. }
  21. return false;
  22. }

4.3.2、APP接口服务

接口文档:https://mock-java.itheima.net/project/35/interface/api/641

4.3.2.1、TanHuaController
  1. //com.tanhua.server.controller.TanHuaController
  2. /**
  3. * 回复陌生人问题
  4. *
  5. * @return
  6. */
  7. @PostMapping("strangerQuestions")
  8. public ResponseEntity<Void> replyQuestion(@RequestBody Map<String, Object> param) {
  9. try {
  10. Long userId = Long.valueOf(param.get("userId").toString());
  11. String reply = param.get("reply").toString();
  12. Boolean result = this.tanHuaService.replyQuestion(userId, reply);
  13. if (result) {
  14. return ResponseEntity.ok(null);
  15. }
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. }
  19. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  20. }

4.3.2.2、TanHuaService
  1. //com.tanhua.server.service.TanHuaService
  2. @Reference(version = "1.0.0")
  3. private HuanXinApi huanXinApi;
  4. public Boolean replyQuestion(Long userId, String reply) {
  5. User user = UserThreadLocal.get();
  6. UserInfo userInfo = this.userInfoService.queryUserInfoByUserId(user.getId());
  7. //构建消息内容
  8. Map<String, Object> msg = new HashMap<>();
  9. msg.put("userId", user.getId());
  10. msg.put("huanXinId", "HX_" + user.getId());
  11. msg.put("nickname", userInfo.getNickName());
  12. msg.put("strangerQuestion", this.queryQuestion(userId));
  13. msg.put("reply", reply);
  14. //发送环信消息
  15. return this.huanXinApi.sendMsgFromAdmin("HX_" + userId,
  16. HuanXinMessageType.TXT, JSONUtil.toJsonStr(msg));
  17. }

4.3.3、测试

day07-完善消息功能以及个人主页 - 图13
day07-完善消息功能以及个人主页 - 图14
用户heima_37收到陌生人消息:
day07-完善消息功能以及个人主页 - 图15
day07-完善消息功能以及个人主页 - 图16
可以看到好友已经添加完成,可以在通讯录中选择好友进行聊天。

在陌聊消息中的“确认添加”功能,就是前面实现的添加联系人接口。

5、谁看过我

查询别人来访了我的主页的信息,其他用户在浏览我的主页时,需要记录访客数据。访客在一天内每个用户只记录一次。
查询数据时,如果用户查询过列表,就需要记录这次查询数据的时间,下次查询时查询大于等于该时间的数据。
如果,用户没有记录查询时间,就查询最近的5个来访用户。
页面效果如下:
day07-完善消息功能以及个人主页 - 图17

5.1、dubbo服务

5.1.1、实体对象

  1. package com.tanhua.dubbo.server.pojo;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. import org.bson.types.ObjectId;
  6. import org.springframework.data.mongodb.core.mapping.Document;
  7. @Data
  8. @NoArgsConstructor
  9. @AllArgsConstructor
  10. @Document(collection = "visitors")
  11. public class Visitors implements java.io.Serializable{
  12. private static final long serialVersionUID = 2811682148052386573L;
  13. private ObjectId id;
  14. private Long userId; //我的id
  15. private Long visitorUserId; //来访用户id
  16. private String from; //来源,如首页、圈子等
  17. private Long date; //来访时间
  18. private Double score; //得分
  19. }

5.1.2、定义接口

  1. package com.tanhua.dubbo.server.api;
  2. import com.tanhua.dubbo.server.pojo.Visitors;
  3. import java.util.List;
  4. public interface VisitorsApi {
  5. /**
  6. * 保存访客数据
  7. *
  8. * @param userId 我的id
  9. * @param visitorUserId 访客id
  10. * @param from 来源
  11. * @return
  12. */
  13. String saveVisitor(Long userId, Long visitorUserId, String from);
  14. /**
  15. * 查询我的访客数据,存在2种情况:
  16. * 1. 我没有看过我的访客数据,返回前5个访客信息
  17. * 2. 之前看过我的访客,从上一次查看的时间点往后查询5个访客数据
  18. *
  19. * @param userId
  20. * @return
  21. */
  22. List<Visitors> queryMyVisitor(Long userId);
  23. }

5.1.3、编写实现

  1. package com.tanhua.dubbo.server.api;
  2. import cn.hutool.core.convert.Convert;
  3. import cn.hutool.core.date.DateUtil;
  4. import cn.hutool.core.util.ObjectUtil;
  5. import com.alibaba.dubbo.config.annotation.Service;
  6. import com.tanhua.dubbo.server.pojo.RecommendUser;
  7. import com.tanhua.dubbo.server.pojo.Visitors;
  8. import org.bson.types.ObjectId;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.data.domain.PageRequest;
  11. import org.springframework.data.domain.Sort;
  12. import org.springframework.data.mongodb.core.MongoTemplate;
  13. import org.springframework.data.mongodb.core.query.Criteria;
  14. import org.springframework.data.mongodb.core.query.Query;
  15. import org.springframework.data.redis.core.RedisTemplate;
  16. import java.util.List;
  17. @Service(version = "1.0.0")
  18. public class VisitorsApiImpl implements VisitorsApi {
  19. @Autowired
  20. private MongoTemplate mongoTemplate;
  21. private static final String VISITOR_REDIS_KEY = "VISITOR_USER";
  22. @Autowired
  23. private RedisTemplate<String, String> redisTemplate;
  24. @Override
  25. public String saveVisitor(Long userId, Long visitorUserId, String from) {
  26. //校验
  27. if (!ObjectUtil.isAllNotEmpty(userId, visitorUserId, from)) {
  28. return null;
  29. }
  30. //查询访客用户在今天是否已经记录过,如果已经记录过,不再记录
  31. String today = DateUtil.today();
  32. Long minDate = DateUtil.parseDateTime(today + " 00:00:00").getTime();
  33. Long maxDate = DateUtil.parseDateTime(today + " 23:59:59").getTime();
  34. Query query = Query.query(Criteria.where("userId").is(userId)
  35. .and("visitorUserId").is(visitorUserId)
  36. .andOperator(Criteria.where("date").gte(minDate),
  37. Criteria.where("date").lte(maxDate)
  38. )
  39. );
  40. long count = this.mongoTemplate.count(query, Visitors.class);
  41. if (count > 0) {
  42. //今天已经记录过的
  43. return null;
  44. }
  45. Visitors visitors = new Visitors();
  46. visitors.setFrom(from);
  47. visitors.setVisitorUserId(visitorUserId);
  48. visitors.setUserId(userId);
  49. visitors.setDate(System.currentTimeMillis());
  50. visitors.setId(ObjectId.get());
  51. //存储数据
  52. this.mongoTemplate.save(visitors);
  53. return visitors.getId().toHexString();
  54. }
  55. @Override
  56. public List<Visitors> queryMyVisitor(Long userId) {
  57. // 查询前5个访客数据,按照访问时间倒序排序
  58. // 如果用户已经查询过列表,记录查询时间,后续查询需要按照这个时间往后查询
  59. // 上一次查询列表的时间
  60. Long date = Convert.toLong(this.redisTemplate.opsForHash().get(VISITOR_REDIS_KEY, String.valueOf(userId)));
  61. PageRequest pageRequest = PageRequest.of(0, 5, Sort.by(Sort.Order.desc("date")));
  62. Query query = Query.query(Criteria.where("userId").is(userId))
  63. .with(pageRequest);
  64. if (ObjectUtil.isNotEmpty(date)) {
  65. query.addCriteria(Criteria.where("date").gte(date));
  66. }
  67. List<Visitors> visitorsList = this.mongoTemplate.find(query, Visitors.class);
  68. //查询每个来访用户的得分
  69. for (Visitors visitors : visitorsList) {
  70. Query queryScore = Query.query(Criteria.where("toUserId")
  71. .is(userId).and("userId").is(visitors.getVisitorUserId())
  72. );
  73. RecommendUser recommendUser = this.mongoTemplate.findOne(queryScore, RecommendUser.class);
  74. if(ObjectUtil.isNotEmpty(recommendUser)){
  75. visitors.setScore(recommendUser.getScore());
  76. }else {
  77. //默认得分
  78. visitors.setScore(90d);
  79. }
  80. }
  81. return visitorsList;
  82. }
  83. }

5.1.4、单元测试

  1. package com.tanhua.dubbo.server.api;
  2. import org.junit.Test;
  3. import org.junit.runner.RunWith;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.boot.test.context.SpringBootTest;
  6. import org.springframework.test.context.junit4.SpringRunner;
  7. @RunWith(SpringRunner.class)
  8. @SpringBootTest
  9. public class TestVisitorsApi {
  10. @Autowired
  11. private VisitorsApi visitorsApi;
  12. @Test
  13. public void testSaveVisitor(){
  14. this.visitorsApi.saveVisitor(1L, 2L, "个人主页");
  15. this.visitorsApi.saveVisitor(1L, 3L, "个人主页");
  16. this.visitorsApi.saveVisitor(1L, 2L, "个人主页");
  17. }
  18. @Test
  19. public void testQueryMyVisitor(){
  20. this.visitorsApi.queryMyVisitor(1L)
  21. .forEach(visitors -> System.out.println(visitors));
  22. }
  23. }

5.2、APP接口服务

文档地址:https://mock-java.itheima.net/project/35/interface/api/743

  1. package com.tanhua.server.vo;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. @Data
  6. @NoArgsConstructor
  7. @AllArgsConstructor
  8. public class VisitorsVo {
  9. private Long id;
  10. private String avatar;
  11. private String nickname;
  12. private String gender;
  13. private Integer age;
  14. private String[] tags;
  15. private Integer fateValue;
  16. }

5.2.2、QuanZiController

  1. //com.tanhua.server.controller.QuanZiController
  2. /**
  3. * 谁看过我
  4. *
  5. * @return
  6. */
  7. @GetMapping("visitors")
  8. public ResponseEntity<List<VisitorsVo>> queryVisitorsList(){
  9. try {
  10. List<VisitorsVo> list = this.quanZiService.queryVisitorsList();
  11. return ResponseEntity.ok(list);
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. }
  15. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  16. }

5.2.3、QuanZiService

  1. //com.tanhua.server.service.QuanZiService
  2. public List<VisitorsVo> queryVisitorsList() {
  3. User user = UserThreadLocal.get();
  4. List<Visitors> visitorsList = this.visitorsApi.queryMyVisitor(user.getId());
  5. if (CollUtil.isEmpty(visitorsList)) {
  6. return Collections.emptyList();
  7. }
  8. List<Object> userIds = CollUtil.getFieldValues(visitorsList, "visitorUserId");
  9. List<UserInfo> userInfoList = this.userInfoService.queryUserInfoByUserIdList(userIds);
  10. List<VisitorsVo> visitorsVoList = new ArrayList<>();
  11. for (Visitors visitor : visitorsList) {
  12. for (UserInfo userInfo : userInfoList) {
  13. if (ObjectUtil.equals(visitor.getVisitorUserId(), userInfo.getUserId())) {
  14. VisitorsVo visitorsVo = new VisitorsVo();
  15. visitorsVo.setAge(userInfo.getAge());
  16. visitorsVo.setAvatar(userInfo.getLogo());
  17. visitorsVo.setGender(userInfo.getSex().name().toLowerCase());
  18. visitorsVo.setId(userInfo.getUserId());
  19. visitorsVo.setNickname(userInfo.getNickName());
  20. visitorsVo.setTags(StringUtils.split(userInfo.getTags(), ','));
  21. visitorsVo.setFateValue(visitor.getScore().intValue());
  22. visitorsVoList.add(visitorsVo);
  23. break;
  24. }
  25. }
  26. }
  27. return visitorsVoList;
  28. }

5.3、记录访客数据

  1. //com.tanhua.server.service.TanHuaService
  2. public TodayBest queryUserInfo(Long userId) {
  3. UserInfo userInfo = this.userInfoService.queryUserInfoByUserId(userId);
  4. if(ObjectUtil.isEmpty(userInfo)){
  5. return null;
  6. }
  7. TodayBest todayBest = new TodayBest();
  8. todayBest.setId(userId);
  9. todayBest.setAge(userInfo.getAge());
  10. todayBest.setGender(userInfo.getSex().name().toLowerCase());
  11. todayBest.setNickname(userInfo.getNickName());
  12. todayBest.setTags(Convert.toStrArray(StrUtil.split(userInfo.getTags(),',')));
  13. todayBest.setAvatar(userInfo.getLogo());
  14. //缘分值
  15. User user = UserThreadLocal.get();
  16. todayBest.setFateValue(this.recommendUserService.queryScore(userId, user.getId()).longValue());
  17. //记录来访用户
  18. this.visitorsApi.saveVisitor(userId, user.getId(), "个人主页");
  19. return todayBest;
  20. }

5.4、测试

day07-完善消息功能以及个人主页 - 图18