课程说明

  • 首页功能说明
  • 系统架构说明
  • 实现今日佳人功能
  • 实现推荐用户的列表
  • 接口增加缓存功能
  • 整合前端联调测试

    1、首页

    在用户登录成功后,就会进入首页,首页中有今日佳人、推荐好友、探花、搜附近等功能。
    day03-今日佳人功能实现 - 图1

    2、系统架构

    在开发完SSO系统中的登录功能后,接下来就需要实现其他的功能,在整体架构中,完成与APP对接的服务工程叫my-tanhua-server,真正的核心业务逻辑使用dubbo完成,其工程名叫:my-tanhua-dubbo,它们的架构示意图如下:
    day03-今日佳人功能实现 - 图2
    说明:

  • 客户端APP发起请求到Nginx,在Nginx中对请求做出判断,将请求转发至sso系统或server系统。

  • sso系统中,将对接第三方平台以及完成数据的缓存、消息发送、用户的注册登录功能。
  • server系统为APP提供了接口服务的支撑

    • 用户请求中携带的token需要到sso系统中进行校验
    • 通过rpc调用dubbo中提供的服务,在dubbo服务中与MongoDB对接,完成数据的CRUD操作
    • 将一些数据缓存到Redis,从而提升数据查询性能
    • 用户数据的查询将基于MySQL数据库进行查询

      2.1、nginx服务

      2.1.1、部署安装

      安装包在资料中:nginx-1.17.3.zip
      安装在任意目录,通过命令:start nginx.exe 启动:
      day03-今日佳人功能实现 - 图3
      重启加载配置文件命令:nginx.exe -s reload
      day03-今日佳人功能实现 - 图4

      2.1.2、配置

      修改conf目录下的nginx.conf文件:
      1. #user nobody;
      2. worker_processes 1;
      3. #error_log logs/error.log;
      4. #error_log logs/error.log notice;
      5. #error_log logs/error.log info;
      6. #pid logs/nginx.pid;
      7. events {
      8. worker_connections 1024;
      9. }
      10. http {
      11. include mime.types;
      12. default_type application/octet-stream;
      13. #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
      14. # '$status $body_bytes_sent "$http_referer" '
      15. # '"$http_user_agent" "$http_x_forwarded_for"';
      16. #access_log logs/access.log main;
      17. sendfile on;
      18. #tcp_nopush on;
      19. #keepalive_timeout 0;
      20. keepalive_timeout 65;
      21. #gzip on;
      22. server {
      23. listen 80;
      24. server_name localhost;
      25. #charset koi8-r;
      26. #access_log logs/host.access.log main;
      27. #error_page 404 /404.html;
      28. # redirect server error pages to the static page /50x.html
      29. #
      30. error_page 500 502 503 504 /50x.html;
      31. location = /50x.html {
      32. root html;
      33. }
      34. location /user/ { #请求路径中凡是以/user/开头的请求,转发到sso系统
      35. client_max_body_size 300m; #设置最大的请求体大小,解决大文件上传不了的问题
      36. proxy_connect_timeout 300s; #代理连接超时时间
      37. proxy_send_timeout 300s; #代理发送数据的超时时间
      38. proxy_read_timeout 300s; #代理读取数据的超时时间
      39. proxy_pass http://127.0.0.1:18080; #转发请求
      40. }
      41. location / { #上面未匹配到的在这里处理
      42. client_max_body_size 300m;
      43. proxy_connect_timeout 300s;
      44. proxy_send_timeout 300s;
      45. proxy_read_timeout 300s;
      46. proxy_pass http://127.0.0.1:18081; #转发请求到server系统
      47. }
      48. }
      49. }

      2.1.3、测试

      day03-今日佳人功能实现 - 图5

      2.2、搭建server工程

      2.2.1、导入依赖

      pom.xml文件:
      1. <?xml version="1.0" encoding="UTF-8"?>
      2. <project xmlns="http://maven.apache.org/POM/4.0.0"
      3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      5. <parent>
      6. <artifactId>my-tanhua</artifactId>
      7. <groupId>cn.itcast.tanhua</groupId>
      8. <version>1.0-SNAPSHOT</version>
      9. </parent>
      10. <modelVersion>4.0.0</modelVersion>
      11. <artifactId>my-tanhua-server</artifactId>
      12. <dependencies>
      13. <dependency>
      14. <groupId>cn.itcast.tanhua</groupId>
      15. <artifactId>my-tanhua-dubbo-interface</artifactId>
      16. <version>1.0-SNAPSHOT</version>
      17. </dependency>
      18. <dependency>
      19. <groupId>org.springframework.boot</groupId>
      20. <artifactId>spring-boot-starter-web</artifactId>
      21. </dependency>
      22. <dependency>
      23. <groupId>org.springframework.boot</groupId>
      24. <artifactId>spring-boot-starter-test</artifactId>
      25. <scope>test</scope>
      26. </dependency>
      27. <dependency>
      28. <groupId>org.springframework.boot</groupId>
      29. <artifactId>spring-boot-starter-data-redis</artifactId>
      30. </dependency>
      31. <!--dubbo的springboot支持-->
      32. <dependency>
      33. <groupId>com.alibaba.boot</groupId>
      34. <artifactId>dubbo-spring-boot-starter</artifactId>
      35. </dependency>
      36. <!--dubbo框架-->
      37. <dependency>
      38. <groupId>com.alibaba</groupId>
      39. <artifactId>dubbo</artifactId>
      40. </dependency>
      41. <!--zk依赖-->
      42. <dependency>
      43. <groupId>org.apache.zookeeper</groupId>
      44. <artifactId>zookeeper</artifactId>
      45. </dependency>
      46. <dependency>
      47. <groupId>com.github.sgroschupf</groupId>
      48. <artifactId>zkclient</artifactId>
      49. </dependency>
      50. <dependency>
      51. <groupId>org.apache.commons</groupId>
      52. <artifactId>commons-lang3</artifactId>
      53. </dependency>
      54. <dependency>
      55. <groupId>org.apache.commons</groupId>
      56. <artifactId>commons-collections4</artifactId>
      57. <version>4.4</version>
      58. </dependency>
      59. <dependency>
      60. <groupId>com.baomidou</groupId>
      61. <artifactId>mybatis-plus</artifactId>
      62. </dependency>
      63. <dependency>
      64. <groupId>com.baomidou</groupId>
      65. <artifactId>mybatis-plus-boot-starter</artifactId>
      66. </dependency>
      67. <dependency>
      68. <groupId>mysql</groupId>
      69. <artifactId>mysql-connector-java</artifactId>
      70. </dependency>
      71. <dependency>
      72. <groupId>commons-io</groupId>
      73. <artifactId>commons-io</artifactId>
      74. <version>2.6</version>
      75. </dependency>
      76. <dependency>
      77. <groupId>commons-codec</groupId>
      78. <artifactId>commons-codec</artifactId>
      79. </dependency>
      80. </dependencies>
      81. </project>

      2.2.2、application.properties

      1. spring.application.name = itcast-tanhua-server
      2. server.port = 18081
      3. #数据库连接信息
      4. spring.datasource.driver-class-name=com.mysql.jdbc.Driver
      5. spring.datasource.url=jdbc:mysql://192.168.31.81:3306/mytanhua?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
      6. spring.datasource.username=root
      7. spring.datasource.password=root
      8. # 枚举包扫描
      9. mybatis-plus.type-enums-package=com.tanhua.server.enums
      10. # 表名前缀
      11. mybatis-plus.global-config.db-config.table-prefix=tb_
      12. # id策略为自增长
      13. mybatis-plus.global-config.db-config.id-type=auto
      14. #dubbo注册中心配置
      15. dubbo.application.name = itcast-tanhua-server
      16. dubbo.registry.address = zookeeper://192.168.31.81:2181
      17. dubbo.registry.client = zkclient
      18. dubbo.registry.timeout = 60000
      19. dubbo.consumer.timeout = 60000
      20. #sso系统服务地址
      21. tanhua.sso.url=http://127.0.0.1
      22. #默认今日佳人推荐用户
      23. tanhua.sso.default.user=2

      2.2.3、ServerApplication

      1. package com.tanhua.server;
      2. import org.mybatis.spring.annotation.MapperScan;
      3. import org.springframework.boot.SpringApplication;
      4. import org.springframework.boot.autoconfigure.SpringBootApplication;
      5. @MapperScan("com.tanhua.server.mapper") //设置mapper接口的扫描包
      6. @SpringBootApplication
      7. public class ServerApplication {
      8. public static void main(String[] args) {
      9. SpringApplication.run(ServerApplication.class, args);
      10. }
      11. }

      2.3、搭建dubbo工程

      my-tanhua-dubbo是dubbo工程的父工程:
      1. <?xml version="1.0" encoding="UTF-8"?>
      2. <project xmlns="http://maven.apache.org/POM/4.0.0"
      3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      5. <parent>
      6. <artifactId>my-tanhua</artifactId>
      7. <groupId>cn.itcast.tanhua</groupId>
      8. <version>1.0-SNAPSHOT</version>
      9. </parent>
      10. <modelVersion>4.0.0</modelVersion>
      11. <artifactId>my-tanhua-dubbo</artifactId>
      12. <packaging>pom</packaging>
      13. <modules>
      14. <module>my-tanhua-dubbo-interface</module>
      15. <module>my-tanhua-dubbo-service</module>
      16. </modules>
      17. </project>

      2.3.1、创建my-tanhua-dubbo-interface工程

      该工程中定义了dubbo服务中的interface与实体对象。
      1. <?xml version="1.0" encoding="UTF-8"?>
      2. <project xmlns="http://maven.apache.org/POM/4.0.0"
      3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      5. <parent>
      6. <artifactId>my-tanhua-dubbo</artifactId>
      7. <groupId>cn.itcast.tanhua</groupId>
      8. <version>1.0-SNAPSHOT</version>
      9. </parent>
      10. <modelVersion>4.0.0</modelVersion>
      11. <artifactId>my-tanhua-dubbo-interface</artifactId>
      12. <dependencies>
      13. <dependency>
      14. <groupId>org.projectlombok</groupId>
      15. <artifactId>lombok</artifactId>
      16. </dependency>
      17. <dependency>
      18. <groupId>org.springframework.boot</groupId>
      19. <artifactId>spring-boot-starter-data-mongodb</artifactId>
      20. </dependency>
      21. </dependencies>
      22. </project>

      2.3.2、创建my-tanhua-dubbo-service工程

      1. <?xml version="1.0" encoding="UTF-8"?>
      2. <project xmlns="http://maven.apache.org/POM/4.0.0"
      3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      5. <parent>
      6. <artifactId>my-tanhua-dubbo</artifactId>
      7. <groupId>cn.itcast.tanhua</groupId>
      8. <version>1.0-SNAPSHOT</version>
      9. </parent>
      10. <modelVersion>4.0.0</modelVersion>
      11. <artifactId>my-tanhua-dubbo-service</artifactId>
      12. <dependencies>
      13. <!--引入interface依赖-->
      14. <dependency>
      15. <groupId>cn.itcast.tanhua</groupId>
      16. <artifactId>my-tanhua-dubbo-interface</artifactId>
      17. <version>1.0-SNAPSHOT</version>
      18. </dependency>
      19. <dependency>
      20. <groupId>org.springframework.boot</groupId>
      21. <artifactId>spring-boot-starter</artifactId>
      22. </dependency>
      23. <dependency>
      24. <groupId>org.springframework.boot</groupId>
      25. <artifactId>spring-boot-starter-test</artifactId>
      26. <scope>test</scope>
      27. </dependency>
      28. <!--dubbo的springboot支持-->
      29. <dependency>
      30. <groupId>com.alibaba.boot</groupId>
      31. <artifactId>dubbo-spring-boot-starter</artifactId>
      32. </dependency>
      33. <!--dubbo框架-->
      34. <dependency>
      35. <groupId>com.alibaba</groupId>
      36. <artifactId>dubbo</artifactId>
      37. </dependency>
      38. <!--zk依赖-->
      39. <dependency>
      40. <groupId>org.apache.zookeeper</groupId>
      41. <artifactId>zookeeper</artifactId>
      42. </dependency>
      43. <dependency>
      44. <groupId>com.github.sgroschupf</groupId>
      45. <artifactId>zkclient</artifactId>
      46. </dependency>
      47. <!--MongoDB相关依赖-->
      48. <dependency>
      49. <groupId>org.springframework.boot</groupId>
      50. <artifactId>spring-boot-starter-data-mongodb</artifactId>
      51. </dependency>
      52. <dependency>
      53. <groupId>org.mongodb</groupId>
      54. <artifactId>mongodb-driver-sync</artifactId>
      55. </dependency>
      56. <!--其他工具包依赖-->
      57. <dependency>
      58. <groupId>org.apache.commons</groupId>
      59. <artifactId>commons-lang3</artifactId>
      60. </dependency>
      61. <dependency>
      62. <groupId>joda-time</groupId>
      63. <artifactId>joda-time</artifactId>
      64. </dependency>
      65. <dependency>
      66. <groupId>io.netty</groupId>
      67. <artifactId>netty-all</artifactId>
      68. </dependency>
      69. </dependencies>
      70. </project>
      application.properties:
      1. # Spring boot application
      2. spring.application.name = itcast-tanhua-dubbo-service
      3. # dubbo 扫描包配置
      4. dubbo.scan.basePackages = com.tanhua.dubbo.server
      5. dubbo.application.name = dubbo-provider-tanhua
      6. #dubbo 对外暴露的端口信息
      7. dubbo.protocol.name = dubbo
      8. dubbo.protocol.port = 20880
      9. #dubbo注册中心的配置
      10. dubbo.registry.address = zookeeper://192.168.31.81:2181
      11. dubbo.registry.client = zkclient
      12. dubbo.registry.timeout = 60000
      13. #springboot MongoDB配置
      14. spring.data.mongodb.username=tanhua
      15. spring.data.mongodb.password=l3SCjl0HvmSkTtiSbN0Swv40spYnHhDV
      16. spring.data.mongodb.authentication-database=admin
      17. spring.data.mongodb.database=tanhua
      18. spring.data.mongodb.port=27017
      19. spring.data.mongodb.host=192.168.31.81
      编写启动类:
      1. package com.tanhua.dubbo.server;
      2. import org.springframework.boot.SpringApplication;
      3. import org.springframework.boot.autoconfigure.SpringBootApplication;
      4. @SpringBootApplication
      5. public class DubboApplication {
      6. public static void main(String[] args) {
      7. SpringApplication.run(DubboApplication.class, args);
      8. }
      9. }

      2.4、工程结构

      最终搭建完成的效果如下:
      day03-今日佳人功能实现 - 图6
      各工程之间的关系如下:

      3、今日佳人

      今日佳人,会推荐缘分值最大的用户,进行展现出来。缘分值的计算是由用户的行为进行打分,如:点击、点赞、评论、学历、婚姻状态等信息组合而成的。
      实现:我们先不考虑推荐的逻辑,假设现在已经有推荐的结果,我们只需要从结果中查询到缘分值最高的用户就可以了。至于推荐的逻辑以及实现,我们将后面的课程中讲解。
      流程:
      day03-今日佳人功能实现 - 图7

      3.1、表结构

      1. #表结构,表名:recommend_user
      2. {
      3. "userId":1001, #推荐的用户id
      4. "toUserId":1002, #用户id
      5. "score":90, #推荐得分
      6. "date":"2019/1/1" #日期
      7. }
      已经提供的测试数据(4855条数据):
      day03-今日佳人功能实现 - 图8

      3.2、编写dubbo服务

      3.2.1、编写接口

      在my-tanhua-dubbo-interface工程中定义接口:
      1. package com.tanhua.dubbo.server.api;
      2. import com.tanhua.dubbo.server.vo.PageInfo;
      3. import com.tanhua.dubbo.server.pojo.RecommendUser;
      4. public interface RecommendUserApi {
      5. /**
      6. * 查询一位得分最高的推荐用户
      7. *
      8. * @param userId
      9. * @return
      10. */
      11. RecommendUser queryWithMaxScore(Long userId);
      12. /**
      13. * 按照得分倒序
      14. *
      15. * @param userId
      16. * @param pageNum
      17. * @param pageSize
      18. * @return
      19. */
      20. PageInfo<RecommendUser> queryPageInfo(Long userId, Integer pageNum, Integer pageSize);
      21. }
      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.annotation.Id;
      7. import org.springframework.data.mongodb.core.index.Indexed;
      8. import org.springframework.data.mongodb.core.mapping.Document;
      9. @Data
      10. @NoArgsConstructor
      11. @AllArgsConstructor
      12. @Document(collection = "recommend_user")
      13. public class RecommendUser implements java.io.Serializable{
      14. private static final long serialVersionUID = -4296017160071130962L;
      15. @Id
      16. private ObjectId id; //主键id
      17. @Indexed
      18. private Long userId; //推荐的用户id
      19. private Long toUserId; //用户id
      20. @Indexed
      21. private Double score; //推荐得分
      22. private String date; //日期
      23. }
      1. package com.tanhua.dubbo.server.vo;
      2. import lombok.AllArgsConstructor;
      3. import lombok.Data;
      4. import java.util.Collections;
      5. import java.util.List;
      6. @Data
      7. @AllArgsConstructor
      8. public class PageInfo<T> implements java.io.Serializable {
      9. private static final long serialVersionUID = -2105385689859184204L;
      10. /**
      11. * 总条数
      12. */
      13. private Integer total = 0;
      14. /**
      15. * 当前页
      16. */
      17. private Integer pageNum = 0;
      18. /**
      19. * 一页显示的大小
      20. */
      21. private Integer pageSize = 0;
      22. /**
      23. * 数据列表
      24. */
      25. private List<T> records = Collections.emptyList();
      26. }

      3.2.2、编写实现

      1. package com.tanhua.dubbo.server.api;
      2. import com.alibaba.dubbo.config.annotation.Service;
      3. import com.tanhua.dubbo.server.pojo.RecommendUser;
      4. import com.tanhua.dubbo.server.vo.PageInfo;
      5. import org.springframework.beans.factory.annotation.Autowired;
      6. import org.springframework.data.domain.PageRequest;
      7. import org.springframework.data.domain.Sort;
      8. import org.springframework.data.mongodb.core.MongoTemplate;
      9. import org.springframework.data.mongodb.core.query.Criteria;
      10. import org.springframework.data.mongodb.core.query.Query;
      11. import java.util.List;
      12. @Service(version = "1.0.0") //申明这是一个dubbo服务
      13. public class RecommendUserApiImpl implements RecommendUserApi {
      14. @Autowired
      15. private MongoTemplate mongoTemplate;
      16. @Override
      17. public RecommendUser queryWithMaxScore(Long userId) {
      18. //查询得分最高的用户,按照得分倒序排序
      19. Query query = Query.query(Criteria.where("toUserId").is(userId))
      20. .with(Sort.by(Sort.Order.desc("score"))).limit(1);
      21. return this.mongoTemplate.findOne(query, RecommendUser.class);
      22. }
      23. @Override
      24. public PageInfo<RecommendUser> queryPageInfo(Long userId, Integer pageNum, Integer pageSize) {
      25. //分页并且排序参数
      26. PageRequest pageRequest = PageRequest.of(pageNum - 1, pageSize, Sort.by(Sort.Order.desc("score")));
      27. //查询参数
      28. Query query = Query.query(Criteria.where("toUserId").is(userId)).with(pageRequest);
      29. List<RecommendUser> recommendUserList = this.mongoTemplate.find(query, RecommendUser.class);
      30. //暂时不提供数据总数
      31. return new PageInfo<>(0, pageNum, pageSize, recommendUserList);
      32. }
      33. }

      3.2.3、测试

      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 TestRecommendUserApi {
      10. @Autowired
      11. private RecommendUserApi recommendUserApi;
      12. @Test
      13. public void testQueryWithMaxScore(){
      14. System.out.println(this.recommendUserApi.queryWithMaxScore(1L));
      15. System.out.println(this.recommendUserApi.queryWithMaxScore(8L));
      16. System.out.println(this.recommendUserApi.queryWithMaxScore(26L));
      17. }
      18. @Test
      19. public void testQueryPageInfo(){
      20. System.out.println(this.recommendUserApi.queryPageInfo(1L,1,5));
      21. System.out.println(this.recommendUserApi.queryPageInfo(1L,2,5));
      22. System.out.println(this.recommendUserApi.queryPageInfo(1L,3,5));
      23. }
      24. }

      3.3、实现今日佳人服务

      3.3.1、mock服务

      地址:https://mock-java.itheima.net/project/35/interface/api/617
      day03-今日佳人功能实现 - 图9
      day03-今日佳人功能实现 - 图10

      3.3.2、基础代码

      3.3.2.1、SexEnum
      1. package com.tanhua.server.enums;
      2. import com.baomidou.mybatisplus.core.enums.IEnum;
      3. public enum SexEnum implements IEnum<Integer> {
      4. MAN(1,"男"),
      5. WOMAN(2,"女"),
      6. UNKNOWN(3,"未知");
      7. private int value;
      8. private String desc;
      9. SexEnum(int value, String desc) {
      10. this.value = value;
      11. this.desc = desc;
      12. }
      13. @Override
      14. public Integer getValue() {
      15. return this.value;
      16. }
      17. @Override
      18. public String toString() {
      19. return this.desc;
      20. }
      21. }
      3.3.2.2、BasePojo
      1. package com.tanhua.server.pojo;
      2. import com.baomidou.mybatisplus.annotation.FieldFill;
      3. import com.baomidou.mybatisplus.annotation.TableField;
      4. import java.util.Date;
      5. public abstract class BasePojo {
      6. @TableField(fill = FieldFill.INSERT)
      7. private Date created;
      8. @TableField(fill = FieldFill.INSERT_UPDATE)
      9. private Date updated;
      10. }
      3.3.2.3、User
      1. package com.tanhua.server.pojo;
      2. import com.fasterxml.jackson.annotation.JsonIgnore;
      3. import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
      4. import lombok.AllArgsConstructor;
      5. import lombok.Data;
      6. import lombok.NoArgsConstructor;
      7. @Data
      8. @NoArgsConstructor
      9. @AllArgsConstructor
      10. @JsonIgnoreProperties(ignoreUnknown = true)
      11. public class User extends BasePojo {
      12. private Long id;
      13. private String mobile; //手机号
      14. @JsonIgnore
      15. private String password; //密码,json序列化时忽略
      16. }
      3.3.2.4、UserInfo
      1. package com.tanhua.server.pojo;
      2. import com.tanhua.server.enums.SexEnum;
      3. import lombok.AllArgsConstructor;
      4. import lombok.Data;
      5. import lombok.NoArgsConstructor;
      6. @Data
      7. @NoArgsConstructor
      8. @AllArgsConstructor
      9. public class UserInfo extends BasePojo {
      10. private Long id;
      11. private Long userId; //用户id
      12. private String nickName; //昵称
      13. private String logo; //用户头像
      14. private String tags; //用户标签:多个用逗号分隔
      15. private SexEnum sex; //性别
      16. private Integer age; //年龄
      17. private String edu; //学历
      18. private String city; //城市
      19. private String birthday; //生日
      20. private String coverPic; // 封面图片
      21. private String industry; //行业
      22. private String income; //收入
      23. private String marriage; //婚姻状态
      24. }

      3.3.3、实现功能

      实现描述:
  • 需要根据前端定义的结构定义java对象

  • 根据sso系统提供的接口查询当前登录用户的信息
  • 根据dubbo系统提供的服务进行查询今日佳人数据
    3.3.3.1、TodayBest
    1. package com.tanhua.server.vo;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. /**
    6. * 今日佳人
    7. */
    8. @Data
    9. @NoArgsConstructor
    10. @AllArgsConstructor
    11. public class TodayBest {
    12. private Long id;
    13. private String avatar;
    14. private String nickname;
    15. private String gender; //性别 man woman
    16. private Integer age;
    17. private String[] tags;
    18. private Long fateValue; //缘分值
    19. }
    3.3.3.2、TodayBestController
    1. package com.tanhua.server.controller;
    2. import com.tanhua.server.service.TodayBestService;
    3. import com.tanhua.server.vo.TodayBest;
    4. import lombok.extern.slf4j.Slf4j;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.http.HttpStatus;
    7. import org.springframework.http.ResponseEntity;
    8. import org.springframework.web.bind.annotation.GetMapping;
    9. import org.springframework.web.bind.annotation.RequestHeader;
    10. import org.springframework.web.bind.annotation.RequestMapping;
    11. import org.springframework.web.bind.annotation.RestController;
    12. @RestController
    13. @RequestMapping("tanhua")
    14. @Slf4j
    15. public class TodayBestController {
    16. @Autowired
    17. private TodayBestService todayBestService;
    18. /**
    19. * 查询今日佳人
    20. *
    21. * @param token
    22. * @return
    23. */
    24. @GetMapping("todayBest")
    25. public ResponseEntity<TodayBest> queryTodayBest(@RequestHeader("Authorization") String token) {
    26. try {
    27. TodayBest todayBest = this.todayBestService.queryTodayBest(token);
    28. if (null != todayBest) {
    29. return ResponseEntity.ok(todayBest);
    30. }
    31. } catch (Exception e) {
    32. log.error("查询今日佳人出错~ token = " + token, e);
    33. }
    34. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
    35. }
    36. }
    3.3.3.3、TodayBestService
    1. package com.tanhua.server.service;
    2. import com.tanhua.server.pojo.User;
    3. import com.tanhua.server.pojo.UserInfo;
    4. import com.tanhua.server.vo.TodayBest;
    5. import org.apache.commons.lang3.StringUtils;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.beans.factory.annotation.Value;
    8. import org.springframework.stereotype.Service;
    9. @Service
    10. public class TodayBestService {
    11. @Autowired
    12. private UserService userService;
    13. @Autowired
    14. private RecommendUserService recommendUserService;
    15. @Autowired
    16. private UserInfoService userInfoService;
    17. @Value("${tanhua.sso.default.user}")
    18. private Long defaultUser;
    19. public TodayBest queryTodayBest(String token) {
    20. //校验token是否有效,通过SSO的接口进行校验
    21. User user = this.userService.queryUserByToken(token);
    22. if (null == user) {
    23. //token非法或已经过期
    24. return null;
    25. }
    26. //查询推荐用户(今日佳人)
    27. TodayBest todayBest = this.recommendUserService.queryTodayBest(user.getId());
    28. if(null == todayBest){
    29. //给出默认的推荐用户
    30. todayBest = new TodayBest();
    31. todayBest.setId(defaultUser);
    32. todayBest.setFateValue(80L); //固定值
    33. }
    34. //补全个人信息
    35. UserInfo userInfo = this.userInfoService.queryUserInfoByUserId(todayBest.getId());
    36. if(null == userInfo){
    37. return null;
    38. }
    39. todayBest.setAvatar(userInfo.getLogo());
    40. todayBest.setNickname(userInfo.getNickName());
    41. todayBest.setTags(StringUtils.split(userInfo.getTags(), ','));
    42. todayBest.setGender(userInfo.getSex().getValue() == 1 ? "man" : "woman");
    43. todayBest.setAge(userInfo.getAge());
    44. return todayBest;
    45. }
    46. }
    3.3.3.4、UserService
    1. package com.tanhua.server.service;
    2. import com.fasterxml.jackson.databind.ObjectMapper;
    3. import com.tanhua.server.pojo.User;
    4. import lombok.extern.slf4j.Slf4j;
    5. import org.apache.commons.lang3.StringUtils;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.beans.factory.annotation.Value;
    8. import org.springframework.stereotype.Service;
    9. import org.springframework.web.client.RestTemplate;
    10. @Service
    11. @Slf4j
    12. public class UserService {
    13. @Autowired
    14. private RestTemplate restTemplate;
    15. @Value("${tanhua.sso.url}")
    16. private String ssoUrl;
    17. private static final ObjectMapper MAPPER = new ObjectMapper();
    18. /**
    19. * 通过sso的rest接口查询
    20. *
    21. * @param token
    22. * @return
    23. */
    24. public User queryUserByToken(String token) {
    25. String url = ssoUrl + "/user/" + token;
    26. try {
    27. String data = this.restTemplate.getForObject(url, String.class);
    28. if (StringUtils.isEmpty(data)) {
    29. return null;
    30. }
    31. return MAPPER.readValue(data, User.class);
    32. } catch (Exception e) {
    33. log.error("校验token出错,token = " + token, e);
    34. }
    35. return null;
    36. }
    37. }
    1. package com.tanhua.server.config;
    2. import org.springframework.context.annotation.Bean;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.http.client.ClientHttpRequestFactory;
    5. import org.springframework.http.client.SimpleClientHttpRequestFactory;
    6. import org.springframework.http.converter.StringHttpMessageConverter;
    7. import org.springframework.web.client.RestTemplate;
    8. import java.nio.charset.Charset;
    9. @Configuration
    10. public class RestTemplateConfig {
    11. @Bean
    12. public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
    13. RestTemplate restTemplate = new RestTemplate(factory);
    14. // 支持中文编码
    15. restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8")));
    16. return restTemplate;
    17. }
    18. @Bean
    19. public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
    20. SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    21. factory.setReadTimeout(5000);//单位为ms
    22. factory.setConnectTimeout(5000);//单位为ms
    23. return factory;
    24. }
    25. }
    3.3.3.5、RecommendUserService
    1. package com.tanhua.server.service;
    2. import com.alibaba.dubbo.config.annotation.Reference;
    3. import com.tanhua.dubbo.server.api.RecommendUserApi;
    4. import com.tanhua.dubbo.server.pojo.RecommendUser;
    5. import com.tanhua.server.vo.TodayBest;
    6. import org.springframework.stereotype.Service;
    7. /**
    8. * 负责与dubbo服务进行交互
    9. */
    10. @Service
    11. public class RecommendUserService {
    12. @Reference(version = "1.0.0")
    13. private RecommendUserApi recommendUserApi;
    14. public TodayBest queryTodayBest(Long userId) {
    15. RecommendUser recommendUser = this.recommendUserApi.queryWithMaxScore(userId);
    16. if(null == recommendUser){
    17. return null;
    18. }
    19. TodayBest todayBest = new TodayBest();
    20. todayBest.setId(recommendUser.getUserId());
    21. //缘分值
    22. double score = Math.floor(recommendUser.getScore());//取整,98.2 -> 98
    23. todayBest.setFateValue(Double.valueOf(score).longValue());
    24. return todayBest;
    25. }
    26. }
    3.3.3.6、UserInfoService
    1. package com.tanhua.server.service;
    2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    3. import com.tanhua.server.mapper.UserInfoMapper;
    4. import com.tanhua.server.pojo.UserInfo;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.stereotype.Service;
    7. @Service
    8. public class UserInfoService {
    9. @Autowired
    10. private UserInfoMapper userInfoMapper;
    11. public UserInfo queryUserInfoByUserId(Long userId) {
    12. QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
    13. queryWrapper.eq("user_id", userId);
    14. return this.userInfoMapper.selectOne(queryWrapper);
    15. }
    16. }
    3.3.3.7、UserInfoMapper
    ```java package com.tanhua.server.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.tanhua.common.pojo.UserInfo; public interface UserInfoMapper extends BaseMapper {

}

  1. <a name="f54ec100"></a>
  2. #### 3.3.4、测试
  3. 单元测试,测试dubbo服务:
  4. ```java
  5. package com.tanhua.server;
  6. import com.tanhua.server.service.RecommendUserService;
  7. import com.tanhua.server.vo.TodayBest;
  8. import org.junit.Test;
  9. import org.junit.runner.RunWith;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.boot.test.context.SpringBootTest;
  12. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  13. @SpringBootTest
  14. @RunWith(SpringJUnit4ClassRunner.class)
  15. public class TestRecommendUserApi {
  16. @Autowired
  17. private RecommendUserService recommendUserService;
  18. @Test
  19. public void testQueryTodayBest(){
  20. TodayBest todayBest = this.recommendUserService.queryTodayBest(1L);
  21. System.out.println(todayBest);
  22. }
  23. }

整合功能测试,需要将sso、dubbo服务启动完成后进行测试。
day03-今日佳人功能实现 - 图11

3.3.5、解决MongoDB启动bug

在项目中,添加了mongo的依赖的话,springboot就会自动去连接本地的mongo,由于他连接不上会导致出错。
day03-今日佳人功能实现 - 图12
解决:
springboot中添加排除自动配置的注解

  1. package com.tanhua.server;
  2. import org.mybatis.spring.annotation.MapperScan;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
  6. import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
  7. @MapperScan("com.tanhua.server.mapper") //设置mapper接口的扫描包
  8. @SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) //排除mongo的自动配置
  9. public class ServerApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(ServerApplication.class, args);
  12. }
  13. }

4、推荐列表

day03-今日佳人功能实现 - 图13

4.1、mock接口

地址:https://mock-java.itheima.net/project/35/interface/api/623
day03-今日佳人功能实现 - 图14
day03-今日佳人功能实现 - 图15

4.2、查询参数对象

  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 RecommendUserQueryParam {
  9. private Integer page = 1; //当前页数
  10. private Integer pagesize = 10; //页尺寸
  11. private String gender; //性别 man woman
  12. private String lastLogin; //近期登陆时间
  13. private Integer age; //年龄
  14. private String city; //居住地
  15. private String education; //学历
  16. }

4.3、结果对象

  1. package com.tanhua.server.vo;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. import java.util.Collections;
  6. import java.util.List;
  7. @Data
  8. @AllArgsConstructor
  9. @NoArgsConstructor
  10. public class PageResult {
  11. private Integer counts = 0;//总记录数
  12. private Integer pagesize = 0;//页大小
  13. private Integer pages = 0;//总页数
  14. private Integer page = 0;//当前页码
  15. private List<?> items = Collections.emptyList(); //列表
  16. }

4.4、Controller

  1. /**
  2. * 查询推荐用户列表
  3. *
  4. * @param token
  5. * @param queryParam
  6. * @return
  7. */
  8. @GetMapping("recommendation")
  9. public ResponseEntity<PageResult> queryRecommendation(@RequestHeader("Authorization") String token,
  10. RecommendUserQueryParam queryParam){
  11. try {
  12. PageResult pageResult = this.todayBestService.queryRecommendation(token, queryParam);
  13. if (null != pageResult) {
  14. return ResponseEntity.ok(pageResult);
  15. }
  16. } catch (Exception e) {
  17. log.error("查询推荐用户列表出错~ token = " + token, e);
  18. }
  19. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
  20. }

4.5、Service

  1. /**
  2. * 查询推荐用户列表
  3. *
  4. * @param queryParam
  5. * @param token
  6. * @return
  7. */
  8. public PageResult queryRecommendation(String token, RecommendUserQueryParam queryParam) {
  9. //校验token是否有效,通过SSO的接口进行校验
  10. User user = this.userService.queryUserByToken(token);
  11. if (null == user) {
  12. //token非法或已经过期
  13. return null;
  14. }
  15. PageResult pageResult = new PageResult();
  16. pageResult.setPage(queryParam.getPage());
  17. pageResult.setPagesize(queryParam.getPagesize());
  18. PageInfo<RecommendUser> pageInfo = this.recommendUserService.queryRecommendUserList(user.getId(), queryParam.getPage(), queryParam.getPagesize());
  19. List<RecommendUser> records = pageInfo.getRecords();
  20. if (CollectionUtils.isEmpty(records)) {
  21. //没有查询到推荐的用户列表
  22. return pageResult;
  23. }
  24. //填充个人信息
  25. //收集推荐用户的id
  26. Set<Long> userIds = new HashSet<>();
  27. for (RecommendUser record : records) {
  28. userIds.add(record.getUserId());
  29. }
  30. QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
  31. //用户id参数
  32. queryWrapper.in("user_id", userIds);
  33. if (StringUtils.isNotEmpty(queryParam.getGender())) {
  34. //需要性别参数查询
  35. queryWrapper.eq("sex", StringUtils.equals(queryParam.getGender(), "man") ? 1 : 2);
  36. }
  37. if (StringUtils.isNotEmpty(queryParam.getCity())) {
  38. //需要城市参数查询
  39. queryWrapper.like("city", queryParam.getCity());
  40. }
  41. if (queryParam.getAge() != null) {
  42. //设置年龄参数,条件:小于等于
  43. queryWrapper.le("age", queryParam.getAge());
  44. }
  45. List<UserInfo> userInfoList = this.userInfoService.queryUserInfoList(queryWrapper);
  46. if(CollectionUtils.isEmpty(userInfoList)){
  47. //没有查询到用户的基本信息
  48. return pageResult;
  49. }
  50. List<TodayBest> todayBests = new ArrayList<>();
  51. for (UserInfo userInfo : userInfoList) {
  52. TodayBest todayBest = new TodayBest();
  53. todayBest.setId(userInfo.getUserId());
  54. todayBest.setAvatar(userInfo.getLogo());
  55. todayBest.setNickname(userInfo.getNickName());
  56. todayBest.setTags(StringUtils.split(userInfo.getTags(), ','));
  57. todayBest.setGender(userInfo.getSex().getValue() == 1 ? "man" : "woman");
  58. todayBest.setAge(userInfo.getAge());
  59. //缘分值
  60. for (RecommendUser record : records) {
  61. if(record.getUserId().longValue() == userInfo.getUserId().longValue()){
  62. double score = Math.floor(record.getScore());//取整,98.2 -> 98
  63. todayBest.setFateValue(Double.valueOf(score).longValue());
  64. break;
  65. }
  66. }
  67. todayBests.add(todayBest);
  68. }
  69. //按照缘分值进行倒序排序
  70. Collections.sort(todayBests, (o1, o2) -> new Long(o2.getFateValue() - o1.getFateValue()).intValue());
  71. pageResult.setItems(todayBests);
  72. return pageResult;
  73. }
  1. //RecommendUserService
  2. public PageInfo<RecommendUser> queryRecommendUserList(Long id, Integer page, Integer pagesize) {
  3. return this.recommendUserApi.queryPageInfo(id, page, pagesize);
  4. }
  1. //UserInfoService
  2. /**
  3. * 查询用户信息列表
  4. *
  5. * @param queryWrapper
  6. * @return
  7. */
  8. public List<UserInfo> queryUserInfoList(QueryWrapper queryWrapper) {
  9. return this.userInfoMapper.selectList(queryWrapper);
  10. }

4.6、测试

day03-今日佳人功能实现 - 图16
day03-今日佳人功能实现 - 图17

5、缓存

在接口服务中,有必要对于接口进行缓存处理,尤其是GET请求,如果每个接口单独添加的话会存在很多的重复的逻辑,所以可以编写一套通用的解决方案。
实现思路:

  • 通过拦截器实现对请求的拦截,在拦截器中实现缓存的命中。
  • 通过ResponseBodyAdvice进行对响应的拦截,可以将数据缓存到Redis中。
  • 考虑到,不能对于所有的请求都一刀切,所以需要创建@Cache注解进行标记,只有标记的Controller才进行缓存处理。
  • 缓存的处理中,仅针对GET请求处理,其他的请求均不做处理。

    5.1、自定义注解

    1. package com.tanhua.server.utils;
    2. import java.lang.annotation.*;
    3. /**
    4. * 被标记为Cache的Controller进行缓存,其他情况不进行缓存
    5. */
    6. @Target(ElementType.METHOD)
    7. @Retention(RetentionPolicy.RUNTIME)
    8. @Documented //标记注解
    9. public @interface Cache {
    10. /**
    11. * 缓存时间,默认为60秒
    12. * @return
    13. */
    14. String time() default "60";
    15. }

    5.2、采用拦截器进行缓存命中

    编写拦截器:RedisCacheInterceptor。
    1. package com.tanhua.server.interceptor;
    2. import com.fasterxml.jackson.databind.ObjectMapper;
    3. import com.tanhua.server.utils.Cache;
    4. import org.apache.commons.codec.digest.DigestUtils;
    5. import org.apache.commons.lang3.StringUtils;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.beans.factory.annotation.Value;
    8. import org.springframework.data.redis.core.RedisTemplate;
    9. import org.springframework.stereotype.Component;
    10. import org.springframework.web.bind.annotation.GetMapping;
    11. import org.springframework.web.method.HandlerMethod;
    12. import org.springframework.web.servlet.HandlerInterceptor;
    13. import javax.servlet.http.HttpServletRequest;
    14. import javax.servlet.http.HttpServletResponse;
    15. @Component
    16. public class RedisCacheInterceptor implements HandlerInterceptor {
    17. @Value("${tanhua.cache.enable}")
    18. private Boolean enable;
    19. @Autowired
    20. private RedisTemplate<String, String> redisTemplate;
    21. private static final ObjectMapper MAPPER = new ObjectMapper();
    22. @Override
    23. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    24. //缓存的全局开关的校验
    25. if (!enable) {
    26. return true;
    27. }
    28. //校验handler是否是HandlerMethod
    29. if (!(handler instanceof HandlerMethod)) {
    30. return true;
    31. }
    32. //判断是否为get请求
    33. if (!((HandlerMethod) handler).hasMethodAnnotation(GetMapping.class)) {
    34. return true;
    35. }
    36. //判断是否添加了@Cache注解
    37. if (!((HandlerMethod) handler).hasMethodAnnotation(Cache.class)) {
    38. return true;
    39. }
    40. //缓存命中
    41. String redisKey = createRedisKey(request);
    42. String cacheData = this.redisTemplate.opsForValue().get(redisKey);
    43. if(StringUtils.isEmpty(cacheData)){
    44. //缓存未命中
    45. return true;
    46. }
    47. // 将data数据进行响应
    48. response.setCharacterEncoding("UTF-8");
    49. response.setContentType("application/json; charset=utf-8");
    50. response.getWriter().write(cacheData);
    51. return false;
    52. }
    53. /**
    54. * 生成redis中的key,规则:SERVER_CACHE_DATA_MD5(url + param + token)
    55. *
    56. * @param request
    57. * @return
    58. */
    59. public static String createRedisKey(HttpServletRequest request) throws Exception {
    60. String url = request.getRequestURI();
    61. String param = MAPPER.writeValueAsString(request.getParameterMap());
    62. String token = request.getHeader("Authorization");
    63. String data = url + "_" + param + "_" + token;
    64. return "SERVER_CACHE_DATA_" + DigestUtils.md5Hex(data);
    65. }
    66. }
    application.properties:
    1. #是否开启数据缓存
    2. tanhua.cache.enable=false
    3. # Redis相关配置
    4. spring.redis.jedis.pool.max-wait = 5000ms
    5. spring.redis.jedis.pool.max-Idle = 100
    6. spring.redis.jedis.pool.min-Idle = 10
    7. spring.redis.timeout = 10s
    8. spring.redis.cluster.nodes = 192.168.31.81:6379,192.168.31.81:6380,192.168.31.81:6381
    9. spring.redis.cluster.max-redirects=5
    注册拦截器到Spring容器:
    1. package com.tanhua.server.config;
    2. import com.tanhua.server.interceptor.RedisCacheInterceptor;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.context.annotation.Configuration;
    5. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    7. @Configuration
    8. public class WebConfig implements WebMvcConfigurer {
    9. @Autowired
    10. private RedisCacheInterceptor redisCacheInterceptor;
    11. @Override
    12. public void addInterceptors(InterceptorRegistry registry) {
    13. registry.addInterceptor(this.redisCacheInterceptor).addPathPatterns("/**");
    14. }
    15. }

    4.3、响应结果写入到缓存

    使用ResponseBodyAdvice进行对响应结果处理,将结果写入到Redis中:
    具体实现:
    1. package com.tanhua.server.interceptor;
    2. import com.fasterxml.jackson.databind.ObjectMapper;
    3. import com.tanhua.server.utils.Cache;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.beans.factory.annotation.Value;
    6. import org.springframework.core.MethodParameter;
    7. import org.springframework.data.redis.core.RedisTemplate;
    8. import org.springframework.http.MediaType;
    9. import org.springframework.http.server.ServerHttpRequest;
    10. import org.springframework.http.server.ServerHttpResponse;
    11. import org.springframework.http.server.ServletServerHttpRequest;
    12. import org.springframework.web.bind.annotation.ControllerAdvice;
    13. import org.springframework.web.bind.annotation.GetMapping;
    14. import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
    15. import java.util.concurrent.TimeUnit;
    16. @ControllerAdvice
    17. public class MyResponseBodyAdvice implements ResponseBodyAdvice {
    18. @Value("${tanhua.cache.enable}")
    19. private Boolean enable;
    20. @Autowired
    21. private RedisTemplate<String, String> redisTemplate;
    22. private static final ObjectMapper MAPPER = new ObjectMapper();
    23. @Override
    24. public boolean supports(MethodParameter returnType, Class converterType) {
    25. // 开关处于开启状态 是get请求 包含了@Cache注解
    26. return enable && returnType.hasMethodAnnotation(GetMapping.class)
    27. && returnType.hasMethodAnnotation(Cache.class);
    28. }
    29. @Override
    30. public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType,
    31. ServerHttpRequest request, ServerHttpResponse response) {
    32. if (null == body) {
    33. return null;
    34. }
    35. try {
    36. String redisValue = null;
    37. if (body instanceof String) {
    38. redisValue = (String) body;
    39. } else {
    40. redisValue = MAPPER.writeValueAsString(body);
    41. }
    42. String redisKey = RedisCacheInterceptor.createRedisKey(((ServletServerHttpRequest) request).getServletRequest());
    43. Cache cache = returnType.getMethodAnnotation(Cache.class);
    44. //缓存的时间单位是秒
    45. this.redisTemplate.opsForValue().set(redisKey, redisValue, Long.valueOf(cache.time()), TimeUnit.SECONDS);
    46. } catch (Exception e) {
    47. e.printStackTrace();
    48. }
    49. return body;
    50. }
    51. }

    4.4、测试

    day03-今日佳人功能实现 - 图18
    可以看到数据已经缓存到Redis中,并且其缓存时间也是30秒,与预期一致。
    day03-今日佳人功能实现 - 图19

    6、整合测试

    测试时需要注意,由于用户数据较少,所以测试时需要把条件注释掉,否则查询不到数据:
    day03-今日佳人功能实现 - 图20
    效果:
    day03-今日佳人功能实现 - 图21
    day03-今日佳人功能实现 - 图22