课程说明

  • 上报地位位置
  • 实现搜附近功能
  • 实现探花功能
  • 用户基本信息维护

    1、上报地理位置

    当客户端检测用户的地理位置,当变化大于500米时或每隔5分钟,向服务端上报地理位置。
    用户的地理位置存储到Elasticsearch中,需要使用环境提供的ES集群,如下:
    day08-搜附近以及探花功能实现 - 图3

    1.1、dubbo服务

    用户地理位置的服务独立一个新的工程来实现,名字为:my-tanhua-dubbo-es。

    1.1.1、创建工程

    pom.ml文件如下:
    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-es</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. <dependency>
    29. <groupId>org.springframework.boot</groupId>
    30. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    31. </dependency>
    32. <!--dubbo的springboot支持-->
    33. <dependency>
    34. <groupId>com.alibaba.boot</groupId>
    35. <artifactId>dubbo-spring-boot-starter</artifactId>
    36. </dependency>
    37. <!--dubbo框架-->
    38. <dependency>
    39. <groupId>com.alibaba</groupId>
    40. <artifactId>dubbo</artifactId>
    41. </dependency>
    42. <!--zk依赖-->
    43. <dependency>
    44. <groupId>org.apache.zookeeper</groupId>
    45. <artifactId>zookeeper</artifactId>
    46. </dependency>
    47. <dependency>
    48. <groupId>com.github.sgroschupf</groupId>
    49. <artifactId>zkclient</artifactId>
    50. </dependency>
    51. <dependency>
    52. <groupId>io.netty</groupId>
    53. <artifactId>netty-all</artifactId>
    54. </dependency>
    55. <dependency>
    56. <groupId>cn.hutool</groupId>
    57. <artifactId>hutool-all</artifactId>
    58. </dependency>
    59. </dependencies>
    60. </project>
    application.properties文件:
    1. # Spring boot application
    2. spring.application.name = itcast-tanhua-dubbo-es
    3. # dubbo 扫描包配置
    4. dubbo.scan.basePackages = com.tanhua.dubbo.es
    5. dubbo.application.name = dubbo-provider-es
    6. #dubbo 对外暴露的端口信息
    7. dubbo.protocol.name = dubbo
    8. dubbo.protocol.port = 20882
    9. #dubbo注册中心的配置
    10. dubbo.registry.address = zookeeper://192.168.31.81:2181
    11. dubbo.registry.client = zkclient
    12. dubbo.registry.timeout = 60000
    13. #ES集群配置
    14. spring.data.elasticsearch.cluster-name=es-tanhua-cluster
    15. spring.data.elasticsearch.cluster-nodes=192.168.31.81:9300,192.168.31.81:9301,192.168.31.81:9302
    启动类:
    1. package com.tanhua.dubbo.es;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
    5. import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
    6. @SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) //排除mongo的自动配置
    7. public class ESApplication {
    8. public static void main(String[] args) {
    9. SpringApplication.run(ESApplication.class, args);
    10. }
    11. }

    1.1.2、定义pojo

    在my-tanhua-dubbo-interface中创建:
    1. package com.tanhua.dubbo.server.pojo;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. import org.elasticsearch.common.geo.GeoPoint;
    6. import org.springframework.data.annotation.Id;
    7. import org.springframework.data.elasticsearch.annotations.Document;
    8. import org.springframework.data.elasticsearch.annotations.Field;
    9. import org.springframework.data.elasticsearch.annotations.FieldType;
    10. import org.springframework.data.elasticsearch.annotations.GeoPointField;
    11. @Data
    12. @NoArgsConstructor
    13. @AllArgsConstructor
    14. @Document(indexName = "tanhua", type = "user_location", shards = 6, replicas = 2)
    15. public class UserLocation {
    16. @Id
    17. private Long userId; //用户id
    18. @GeoPointField
    19. private GeoPoint location; //lon:经度 lat:纬度
    20. @Field(type = FieldType.Keyword)
    21. private String address; //位置描述
    22. @Field(type = FieldType.Long)
    23. private Long created; //创建时间
    24. @Field(type = FieldType.Long)
    25. private Long updated; //更新时间
    26. @Field(type = FieldType.Long)
    27. private Long lastUpdated; //上次更新时间
    28. }
    1. package com.tanhua.dubbo.server.vo;
    2. import cn.hutool.core.bean.BeanUtil;
    3. import com.tanhua.dubbo.server.pojo.UserLocation;
    4. import lombok.AllArgsConstructor;
    5. import lombok.Data;
    6. import lombok.NoArgsConstructor;
    7. import java.util.ArrayList;
    8. import java.util.List;
    9. @Data
    10. @NoArgsConstructor
    11. @AllArgsConstructor
    12. public class UserLocationVo implements java.io.Serializable {
    13. private static final long serialVersionUID = 4133419501260037769L;
    14. private Long userId; //用户id
    15. private Double longitude; //经度
    16. private Double latitude; //维度
    17. private String address; //位置描述
    18. private Long created; //创建时间
    19. private Long updated; //更新时间
    20. private Long lastUpdated; //上次更新时间
    21. public static final UserLocationVo format(UserLocation userLocation) {
    22. UserLocationVo userLocationVo = BeanUtil.toBean(userLocation, UserLocationVo.class);
    23. userLocationVo.setLongitude(userLocation.getLocation().getLon());
    24. userLocationVo.setLatitude(userLocation.getLocation().getLat());
    25. return userLocationVo;
    26. }
    27. public static final List<UserLocationVo> formatToList(List<UserLocation> userLocations) {
    28. List<UserLocationVo> list = new ArrayList<>();
    29. for (UserLocation userLocation : userLocations) {
    30. list.add(format(userLocation));
    31. }
    32. return list;
    33. }
    34. }

    由于UserLocation不能序列化,所以要再定义UserLocationVo进行返回数据。

在my-tanhua-dubbo-interface中添加依赖:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>cn.hutool</groupId>
  7. <artifactId>hutool-all</artifactId>
  8. </dependency>

1.1.3、定义dubbo接口

在my-tanhua-dubbo-interface工程中。

  1. package com.tanhua.dubbo.server.api;
  2. public interface UserLocationApi {
  3. /**
  4. * 更新用户地理位置
  5. *
  6. * @param userId 用户id
  7. * @param longitude 经度
  8. * @param latitude 纬度
  9. * @param address 地址名称
  10. * @return
  11. */
  12. Boolean updateUserLocation(Long userId, Double longitude, Double latitude, String address);
  13. }

1.1.4、编写实现

  1. package com.tanhua.dubbo.es.api;
  2. import cn.hutool.core.util.ObjectUtil;
  3. import com.alibaba.dubbo.config.annotation.Service;
  4. import com.tanhua.dubbo.server.api.UserLocationApi;
  5. import com.tanhua.dubbo.server.pojo.UserLocation;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.elasticsearch.action.update.UpdateRequest;
  8. import org.elasticsearch.common.geo.GeoPoint;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
  11. import org.springframework.data.elasticsearch.core.query.*;
  12. import javax.annotation.PostConstruct;
  13. import java.util.HashMap;
  14. import java.util.Map;
  15. @Service(version = "1.0.0")
  16. @Slf4j
  17. public class UserLocationApiImpl implements UserLocationApi {
  18. @Autowired
  19. private ElasticsearchTemplate elasticsearchTemplate;
  20. /**
  21. * 初始化索引库
  22. *
  23. */
  24. @PostConstruct
  25. public void initIndex(){
  26. //判断索引库是否存在,如果不存在,需要创建
  27. if(!this.elasticsearchTemplate.indexExists("tanhua")){
  28. this.elasticsearchTemplate.createIndex(UserLocation.class);
  29. }
  30. //判断表是否存在,如果不存在,需要创建
  31. if(!this.elasticsearchTemplate.typeExists("tanhua", "user_location")){
  32. this.elasticsearchTemplate.putMapping(UserLocation.class);
  33. }
  34. }
  35. @Override
  36. public Boolean updateUserLocation(Long userId, Double longitude, Double latitude, String address) {
  37. //查询个人的地理位置数据,如果不存在,需要新增,如果是存在数据,更新数据
  38. this.initIndex();
  39. try {
  40. GetQuery getQuery = new GetQuery();
  41. getQuery.setId(String.valueOf(userId));
  42. UserLocation userLocation = this.elasticsearchTemplate.queryForObject(getQuery, UserLocation.class);
  43. if(ObjectUtil.isEmpty(userLocation)){
  44. //新增数据
  45. userLocation = new UserLocation();
  46. userLocation.setUserId(userId);
  47. userLocation.setAddress(address);
  48. userLocation.setCreated(System.currentTimeMillis());
  49. userLocation.setUpdated(userLocation.getCreated());
  50. userLocation.setLastUpdated(userLocation.getCreated());
  51. userLocation.setLocation(new GeoPoint(latitude, longitude));
  52. IndexQuery indexQuery = new IndexQueryBuilder().withObject(userLocation).build();
  53. //保存数据到ES中
  54. this.elasticsearchTemplate.index(indexQuery);
  55. }else {
  56. //更新数据
  57. //更新的字段
  58. Map<String,Object> map = new HashMap<>();
  59. map.put("location", new GeoPoint(latitude, longitude));
  60. map.put("updated", System.currentTimeMillis());
  61. map.put("lastUpdated", userLocation.getUpdated());
  62. map.put("address", address);
  63. UpdateRequest updateRequest = new UpdateRequest();
  64. updateRequest.doc(map);
  65. UpdateQuery updateQuery = new UpdateQueryBuilder()
  66. .withId(String.valueOf(userId))
  67. .withClass(UserLocation.class)
  68. .withUpdateRequest(updateRequest).build();
  69. //更新数据
  70. this.elasticsearchTemplate.update(updateQuery);
  71. }
  72. return true;
  73. } catch (Exception e) {
  74. log.error("更新地理位置失败~ userId = " + userId + ", longitude = " + longitude + ", latitude = " + latitude + ", address = " + address, e);
  75. }
  76. return false;
  77. }
  78. }

1.1.5、单元测试

  1. package com.tanhua.dubbo.es;
  2. import com.tanhua.dubbo.server.api.UserLocationApi;
  3. import com.tanhua.dubbo.server.vo.PageInfo;
  4. import com.tanhua.dubbo.server.vo.UserLocationVo;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. @RunWith(SpringRunner.class)
  11. @SpringBootTest
  12. public class TestUserLocationApi {
  13. @Autowired
  14. private UserLocationApi userLocationApi;
  15. @Test
  16. public void testUpdateUserLocation() {
  17. this.userLocationApi.updateUserLocation(1L, 121.512253, 31.24094, "金茂大厦");
  18. this.userLocationApi.updateUserLocation(2L, 121.506377, 31.245105, "东方明珠广播电视塔");
  19. this.userLocationApi.updateUserLocation(10L, 121.508815, 31.243844, "陆家嘴地铁站");
  20. this.userLocationApi.updateUserLocation(12L, 121.511999, 31.239185, "上海中心大厦");
  21. this.userLocationApi.updateUserLocation(25L, 121.493444, 31.240513, "上海市公安局");
  22. this.userLocationApi.updateUserLocation(27L, 121.494108, 31.247011, "上海外滩美术馆");
  23. this.userLocationApi.updateUserLocation(30L, 121.462452, 31.253463, "上海火车站");
  24. this.userLocationApi.updateUserLocation(32L, 121.81509, 31.157478, "上海浦东国际机场");
  25. this.userLocationApi.updateUserLocation(34L, 121.327908, 31.20033, "虹桥火车站");
  26. this.userLocationApi.updateUserLocation(38L, 121.490155, 31.277476, "鲁迅公园");
  27. this.userLocationApi.updateUserLocation(40L, 121.425511, 31.227831, "中山公园");
  28. this.userLocationApi.updateUserLocation(43L, 121.594194, 31.207786, "张江高科");
  29. }
  30. }

1.2、APP接口

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

1.2.1、BaiduController

  1. package com.tanhua.server.controller;
  2. import com.tanhua.server.service.BaiduService;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.http.HttpStatus;
  5. import org.springframework.http.ResponseEntity;
  6. import org.springframework.web.bind.annotation.PostMapping;
  7. import org.springframework.web.bind.annotation.RequestBody;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import org.springframework.web.bind.annotation.RestController;
  10. import java.util.Map;
  11. @RestController
  12. @RequestMapping("baidu")
  13. public class BaiduController {
  14. @Autowired
  15. private BaiduService baiduService;
  16. /**
  17. * 更新位置
  18. *
  19. * @param param
  20. * @return
  21. */
  22. @PostMapping("location")
  23. public ResponseEntity<Void> updateLocation(@RequestBody Map<String, Object> param) {
  24. try {
  25. Double longitude = Double.valueOf(param.get("longitude").toString());
  26. Double latitude = Double.valueOf(param.get("latitude").toString());
  27. String address = param.get("addrStr").toString();
  28. Boolean bool = this.baiduService.updateLocation(longitude, latitude, address);
  29. if (bool) {
  30. return ResponseEntity.ok(null);
  31. }
  32. } catch (Exception e) {
  33. e.printStackTrace();
  34. }
  35. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  36. }
  37. }

1.2.2、BaiduService

  1. package com.tanhua.server.service;
  2. import com.alibaba.dubbo.config.annotation.Reference;
  3. import com.tanhua.common.pojo.User;
  4. import com.tanhua.common.utils.UserThreadLocal;
  5. import com.tanhua.dubbo.server.api.UserLocationApi;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.springframework.stereotype.Service;
  8. @Service
  9. @Slf4j
  10. public class BaiduService {
  11. @Reference(version = "1.0.0")
  12. private UserLocationApi userLocationApi;
  13. public Boolean updateLocation(Double longitude, Double latitude, String address) {
  14. User user = UserThreadLocal.get();
  15. try {
  16. return this.userLocationApi.updateUserLocation(user.getId(), longitude, latitude, address);
  17. } catch (Exception e) {
  18. log.error("更新地理位置失败~ userId = " + user.getId() + ", longitude = " + longitude + ", latitude = " + latitude + ", address = " + address, e);
  19. }
  20. return false;
  21. }
  22. }

1.3、测试

day08-搜附近以及探花功能实现 - 图4

2、搜附近

在首页中点击“搜附近”可以搜索附近的好友,效果如下:
day08-搜附近以及探花功能实现 - 图5
实现思路:根据当前用户的位置,查询附近范围内的用户。范围是可以设置的。

2.1、dubbo服务

2.1.1、定义接口方法

  1. //com.tanhua.dubbo.server.api.UserLocationApi
  2. /**
  3. * 查询用户地理位置
  4. *
  5. * @param userId
  6. * @return
  7. */
  8. UserLocationVo queryByUserId(Long userId);
  9. /**
  10. * 根据位置搜索
  11. *
  12. * @param longitude 经度
  13. * @param latitude 纬度
  14. * @param distance 距离(米)
  15. * @param page 页数
  16. * @param pageSize 页面大小
  17. */
  18. PageInfo<UserLocationVo> queryUserFromLocation(Double longitude, Double latitude, Double distance, Integer page, Integer pageSize);

2.1.2、编写实现

  1. //com.tanhua.dubbo.es.api.UserLocationApiImpl
  2. /**
  3. * 查询用户的位置信息
  4. *
  5. * @param userId
  6. * @return
  7. */
  8. @Override
  9. public UserLocationVo queryByUserId(Long userId) {
  10. GetQuery getQuery = new GetQuery();
  11. getQuery.setId(String.valueOf(userId));
  12. UserLocation userLocation = this.elasticsearchTemplate.queryForObject(getQuery, UserLocation.class);
  13. if(ObjectUtil.isNotEmpty(userLocation)){
  14. return UserLocationVo.format(userLocation);
  15. }
  16. return null;
  17. }
  18. /**
  19. * 根据位置搜索
  20. *
  21. * @param longitude 经度
  22. * @param latitude 纬度
  23. * @param distance 距离(米)
  24. * @param page 页数
  25. * @param pageSize 页面大小
  26. */
  27. @Override
  28. public PageInfo<UserLocationVo> queryUserFromLocation(Double longitude, Double latitude, Double distance, Integer page, Integer pageSize) {
  29. PageInfo<UserLocationVo> pageInfo = new PageInfo<>();
  30. pageInfo.setPageNum(page);
  31. pageInfo.setPageSize(pageSize);
  32. String fieldName = "location";
  33. //实现了SearchQuery接口,构造分页、排序
  34. NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
  35. //分页
  36. PageRequest pageRequest = PageRequest.of(page - 1, pageSize);
  37. searchQueryBuilder.withPageable(pageRequest);
  38. BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
  39. //以一个点为中心,指定范围查询
  40. GeoDistanceQueryBuilder geoDistanceQueryBuilder = new GeoDistanceQueryBuilder(fieldName);
  41. //中心点
  42. geoDistanceQueryBuilder.point(new GeoPoint(latitude, longitude));
  43. //距离(画圆的半径)单位:公里
  44. geoDistanceQueryBuilder.distance(distance / 1000, DistanceUnit.KILOMETERS);
  45. boolQueryBuilder.must(geoDistanceQueryBuilder);
  46. searchQueryBuilder.withQuery(boolQueryBuilder);
  47. //排序,由近到远排序
  48. GeoDistanceSortBuilder geoDistanceSortBuilder = new GeoDistanceSortBuilder(fieldName, latitude, longitude);
  49. geoDistanceSortBuilder.order(SortOrder.ASC); //正序排序
  50. geoDistanceSortBuilder.unit(DistanceUnit.KILOMETERS); //设置单位
  51. searchQueryBuilder.withSort(geoDistanceSortBuilder);
  52. AggregatedPage<UserLocation> aggregatedPage = this.elasticsearchTemplate.queryForPage(searchQueryBuilder.build(), UserLocation.class);
  53. if(CollUtil.isEmpty(aggregatedPage.getContent())){
  54. return pageInfo;
  55. }
  56. pageInfo.setRecords(UserLocationVo.formatToList(aggregatedPage.getContent()));
  57. return pageInfo;
  58. }

2.1.3、单元测试

  1. //com.tanhua.dubbo.es.TestUserLocationApi
  2. @Test
  3. public void testQueryByUserId(){
  4. UserLocationVo userLocationVo = this.userLocationApi.queryByUserId(1L);
  5. System.out.println(userLocationVo);
  6. }
  7. @Test
  8. public void testQueryUserFromLocation(){
  9. UserLocationVo userLocationVo = this.userLocationApi.queryByUserId(1L);
  10. PageInfo<UserLocationVo> pageInfo = this.userLocationApi
  11. .queryUserFromLocation(userLocationVo.getLongitude(),
  12. userLocationVo.getLatitude(), 5000d, 1, 10);
  13. pageInfo.getRecords().forEach(vo -> System.out.println(vo));
  14. }

2.2、APP接口服务

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

2.2.1、NearUserVo

  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 NearUserVo {
  9. private Long userId;
  10. private String avatar;
  11. private String nickname;
  12. }

2.2.2、TanHuaController

  1. //com.tanhua.server.controller.TanHuaController
  2. /**
  3. * 搜附近
  4. *
  5. * @param gender
  6. * @param distance
  7. * @return
  8. */
  9. @GetMapping("search")
  10. public ResponseEntity<List<NearUserVo>> queryNearUser(@RequestParam(value = "gender", required = false) String gender,
  11. @RequestParam(value = "distance", defaultValue = "2000") String distance) {
  12. try {
  13. List<NearUserVo> list = this.tanHuaService.queryNearUser(gender, distance);
  14. return ResponseEntity.ok(list);
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. }
  18. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  19. }

2.2.3、TanHuaService

  1. //com.tanhua.server.service.TanHuaService
  2. public List<NearUserVo> queryNearUser(String gender, String distance) {
  3. //查询当前用户的位置
  4. User user = UserThreadLocal.get();
  5. UserLocationVo userLocationVo = this.userLocationApi.queryByUserId(user.getId());
  6. if(ObjectUtil.isEmpty(userLocationVo)){
  7. return ListUtil.empty();
  8. }
  9. PageInfo<UserLocationVo> pageInfo = this.userLocationApi.queryUserFromLocation(userLocationVo.getLongitude(),
  10. userLocationVo.getLatitude(),
  11. Convert.toDouble(distance),
  12. 1,
  13. 50
  14. );
  15. List<UserLocationVo> records = pageInfo.getRecords();
  16. if(CollUtil.isEmpty(records)){
  17. return ListUtil.empty();
  18. }
  19. //构造筛选条件
  20. List<Object> userIdList = CollUtil.getFieldValues(records, "userId");
  21. QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
  22. queryWrapper.in("user_id", userIdList);
  23. if(StrUtil.equalsIgnoreCase(gender, "man")){
  24. queryWrapper.eq("sex", SexEnum.MAN);
  25. }else if(StrUtil.equalsIgnoreCase(gender, "woman")){
  26. queryWrapper.eq("sex", SexEnum.WOMAN);
  27. }
  28. List<UserInfo> userInfoList = this.userInfoService.queryUserInfoList(queryWrapper);
  29. List<NearUserVo> result = new ArrayList<>();
  30. for (UserLocationVo locationVo : records) {
  31. //排除自己
  32. if(ObjectUtil.equals(locationVo.getUserId(), user.getId())){
  33. continue;
  34. }
  35. for (UserInfo userInfo : userInfoList) {
  36. if(ObjectUtil.equals(locationVo.getUserId(), userInfo.getUserId())){
  37. NearUserVo nearUserVo = new NearUserVo();
  38. nearUserVo.setUserId(userInfo.getUserId());
  39. nearUserVo.setAvatar(userInfo.getLogo());
  40. nearUserVo.setNickname(userInfo.getNickName());
  41. result.add(nearUserVo);
  42. break;
  43. }
  44. }
  45. }
  46. return result;
  47. }

2.2.4、测试

day08-搜附近以及探花功能实现 - 图6

3、探花

探花功能是将推荐的好友随机的通过卡片的形式展现出来,用户可以选择左滑、右滑操作,左滑:“不喜欢”,右滑:“喜欢”。
喜欢:如果双方喜欢,那么就会成为好友。
day08-搜附近以及探花功能实现 - 图7
如果已经喜欢或不喜欢的用户在列表中不再显示。

3.1、喜欢的dubbo服务

用户的喜欢与不喜欢列表需要保存在redis中,为了防止redis中的数据丢失,同时需要将数据保存到mongodb进行持久化保存。

3.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.index.Indexed;
  7. import org.springframework.data.mongodb.core.mapping.Document;
  8. @Data
  9. @NoArgsConstructor
  10. @AllArgsConstructor
  11. @Document(collection = "user_like")
  12. public class UserLike implements java.io.Serializable {
  13. private static final long serialVersionUID = 6739966698394686523L;
  14. private ObjectId id;
  15. @Indexed
  16. private Long userId; //用户id,自己
  17. @Indexed
  18. private Long likeUserId; //喜欢的用户id,对方
  19. private Long created; //创建时间
  20. }

3.1.2、定义接口

  1. package com.tanhua.dubbo.server.api;
  2. import java.util.List;
  3. public interface UserLikeApi {
  4. /**
  5. * 喜欢
  6. *
  7. * @param userId
  8. * @param likeUserId
  9. * @return
  10. */
  11. Boolean likeUser(Long userId, Long likeUserId);
  12. /**
  13. * 不喜欢
  14. *
  15. * @param userId
  16. * @param likeUserId
  17. * @return
  18. */
  19. Boolean notLikeUser(Long userId, Long likeUserId);
  20. /**
  21. * 是否相互喜欢
  22. *
  23. * @param userId
  24. * @param likeUserId
  25. * @return
  26. */
  27. Boolean isMutualLike(Long userId, Long likeUserId);
  28. /**
  29. * 查询喜欢列表
  30. *
  31. * @param userId
  32. * @return
  33. */
  34. List<Long> queryLikeList(Long userId);
  35. /**
  36. * 查询不喜欢列表
  37. *
  38. * @param userId
  39. * @return
  40. */
  41. List<Long> queryNotLikeList(Long userId);
  42. }

3.1.3、编写实现

  1. package com.tanhua.dubbo.server.api;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.collection.ListUtil;
  4. import cn.hutool.core.convert.Convert;
  5. import com.alibaba.dubbo.config.annotation.Service;
  6. import com.tanhua.dubbo.server.pojo.UserLike;
  7. import org.bson.types.ObjectId;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.data.mongodb.core.MongoTemplate;
  10. import org.springframework.data.mongodb.core.query.Criteria;
  11. import org.springframework.data.mongodb.core.query.Query;
  12. import org.springframework.data.redis.core.RedisTemplate;
  13. import java.util.ArrayList;
  14. import java.util.List;
  15. import java.util.Set;
  16. @Service(version = "1.0.0")
  17. public class UserLikeApiImpl implements UserLikeApi {
  18. @Autowired
  19. private MongoTemplate mongoTemplate;
  20. @Autowired
  21. private RedisTemplate<String,String> redisTemplate;
  22. public static final String LIKE_REDIS_KEY_PREFIX = "USER_LIKE_";
  23. public static final String NOT_LIKE_REDIS_KEY_PREFIX = "USER_NOT_LIKE_";
  24. /**
  25. * 喜欢
  26. *
  27. * @param userId
  28. * @param likeUserId
  29. * @return
  30. */
  31. @Override
  32. public Boolean likeUser(Long userId, Long likeUserId) {
  33. //判断该用户是否已经喜欢,如果已经喜欢就返回
  34. if(this.isLike(userId, likeUserId)){
  35. return false;
  36. }
  37. UserLike userLike = new UserLike();
  38. userLike.setId(ObjectId.get());
  39. userLike.setUserId(userId);
  40. userLike.setLikeUserId(likeUserId);
  41. userLike.setCreated(System.currentTimeMillis());
  42. //将数据存储到MongoDB
  43. this.mongoTemplate.save(userLike);
  44. //用户的喜欢数据保存到redis
  45. //用户1:key -> USER_LIKE_1 , value -> 2, "1"
  46. //用户1:key -> USER_LIKE_1 , value -> 3, "1"
  47. //用户2:key -> USER_LIKE_2 , value -> 4, "1"
  48. String redisKey = this.getLikeRedisKey(userId);
  49. String hashKey = String.valueOf(likeUserId);
  50. this.redisTemplate.opsForHash().put(redisKey, hashKey, "1");
  51. //判断,喜欢的用户是否在不喜欢的列表中,如果在,就需要删除数据
  52. if(this.isNotLike(userId, likeUserId)){
  53. redisKey = this.getNotLikeRedisKey(userId);
  54. this.redisTemplate.opsForHash().delete(redisKey, hashKey);
  55. }
  56. return true;
  57. }
  58. /**
  59. * 获取喜欢数据的redis key
  60. *
  61. * @param userId
  62. * @return
  63. */
  64. private String getLikeRedisKey(Long userId){
  65. return LIKE_REDIS_KEY_PREFIX + userId;
  66. }
  67. /**
  68. * 获取不喜欢数据的redis key
  69. *
  70. * @param userId
  71. * @return
  72. */
  73. private String getNotLikeRedisKey(Long userId){
  74. return NOT_LIKE_REDIS_KEY_PREFIX + userId;
  75. }
  76. /**
  77. * 是否喜欢
  78. *
  79. * @param userId
  80. * @param likeUserId
  81. * @return
  82. */
  83. private Boolean isLike(Long userId, Long likeUserId){
  84. String redisKey = this.getLikeRedisKey(userId);
  85. String hashKey = String.valueOf(likeUserId);
  86. return this.redisTemplate.opsForHash().hasKey(redisKey, hashKey);
  87. }
  88. /**
  89. * 是否不喜欢
  90. *
  91. * @param userId
  92. * @param likeUserId
  93. * @return
  94. */
  95. private Boolean isNotLike(Long userId, Long likeUserId){
  96. String redisKey = this.getNotLikeRedisKey(userId);
  97. String hashKey = String.valueOf(likeUserId);
  98. return this.redisTemplate.opsForHash().hasKey(redisKey, hashKey);
  99. }
  100. @Override
  101. public Boolean notLikeUser(Long userId, Long likeUserId) {
  102. //判断用户是否已经不喜欢,如果已经不喜欢,就返回
  103. if(this.isNotLike(userId, likeUserId)){
  104. return false;
  105. }
  106. //将用户保存到不喜欢列表中
  107. String redisKey = this.getNotLikeRedisKey(userId);
  108. String hashKey = String.valueOf(likeUserId);
  109. this.redisTemplate.opsForHash().put(redisKey, hashKey, "1");
  110. //判断用户是否在喜欢列表中,如果存在的话,需要删除数据
  111. if(this.isLike(userId, likeUserId)){
  112. //删除MongoDB数据
  113. Query query = Query.query(Criteria
  114. .where("userId").is(userId)
  115. .and("likeUserId").is(likeUserId)
  116. );
  117. this.mongoTemplate.remove(query, UserLike.class);
  118. //删除redis中的数据
  119. redisKey = this.getLikeRedisKey(userId);
  120. this.redisTemplate.opsForHash().delete(redisKey, hashKey);
  121. }
  122. return true;
  123. }
  124. @Override
  125. public Boolean isMutualLike(Long userId, Long likeUserId) {
  126. return this.isLike(userId, likeUserId)
  127. && this.isLike(likeUserId, userId);
  128. }
  129. @Override
  130. public List<Long> queryLikeList(Long userId) {
  131. // 查询redis
  132. String redisKey = this.getLikeRedisKey(userId);
  133. Set<Object> keys = this.redisTemplate.opsForHash().keys(redisKey);
  134. if(CollUtil.isEmpty(keys)){
  135. return ListUtil.empty();
  136. }
  137. List<Long> result = new ArrayList<>(keys.size());
  138. keys.forEach(o -> result.add(Convert.toLong(o)));
  139. return result;
  140. }
  141. @Override
  142. public List<Long> queryNotLikeList(Long userId) {
  143. // 查询redis
  144. String redisKey = this.getNotLikeRedisKey(userId);
  145. Set<Object> keys = this.redisTemplate.opsForHash().keys(redisKey);
  146. if(CollUtil.isEmpty(keys)){
  147. return ListUtil.empty();
  148. }
  149. List<Long> result = new ArrayList<>(keys.size());
  150. keys.forEach(o -> result.add(Convert.toLong(o)));
  151. return result;
  152. }
  153. }

3.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 TestUserLikeApi {
  10. @Autowired
  11. private UserLikeApi userLikeApi;
  12. @Test
  13. public void testUserLike() {
  14. System.out.println(this.userLikeApi.likeUser(1L, 2L));
  15. System.out.println(this.userLikeApi.likeUser(1L, 3L));
  16. System.out.println(this.userLikeApi.likeUser(1L, 4L));
  17. System.out.println(this.userLikeApi.notLikeUser(1L, 5L));
  18. System.out.println(this.userLikeApi.notLikeUser(1L, 6L));
  19. System.out.println(this.userLikeApi.likeUser(1L, 5L));
  20. System.out.println(this.userLikeApi.notLikeUser(1L, 2L));
  21. }
  22. @Test
  23. public void testQueryList(){
  24. this.userLikeApi.queryLikeList(1L).forEach(a -> System.out.println(a));
  25. System.out.println("-------");
  26. this.userLikeApi.queryNotLikeList(1L).forEach(a -> System.out.println(a));
  27. }
  28. }

3.2、查询推荐列表dubbo服务

3.2.1、定义接口

  1. //com.tanhua.dubbo.server.api.RecommendUserApi
  2. /**
  3. * 查询探花列表,查询时需要排除不喜欢列表用户
  4. *
  5. * @param userId
  6. * @param count
  7. * @return
  8. */
  9. List<RecommendUser> queryCardList(Long userId, Integer count);

3.2.2、编写实现

  1. //com.tanhua.dubbo.server.api.RecommendUserApiImpl
  2. @Override
  3. public List<RecommendUser> queryCardList(Long userId, Integer count) {
  4. //设置分页以及排序,按照得分倒序排序
  5. PageRequest pageRequest = PageRequest.of(0, count, Sort.by(Sort.Order.desc("score")));
  6. //排除已喜欢或不喜欢的用户
  7. List<Long> userIds = new ArrayList<>();
  8. //查询喜欢列表
  9. userIds.addAll(this.userLikeApi.queryLikeList(userId));
  10. //查询不喜欢列表
  11. userIds.addAll(this.userLikeApi.queryNotLikeList(userId));
  12. //构造查询条件
  13. Criteria criteria = Criteria.where("toUserId").is(userId);
  14. if(CollUtil.isNotEmpty(userIds)){
  15. //加入到查询条件中,排除这些用户
  16. criteria.andOperator(Criteria.where("userId").nin(userIds));
  17. }
  18. Query query = Query.query(criteria).with(pageRequest);
  19. List<RecommendUser> recommendUserList = this.mongoTemplate.find(query, RecommendUser.class);
  20. return recommendUserList;
  21. }

3.2.3、单元测试

  1. //com.tanhua.dubbo.server.api.TestRecommendUserApi
  2. @Test
  3. public void testQueryCardList(){
  4. this.recommendUserApi.queryCardList(2L, 20)
  5. .forEach(recommendUser -> System.out.println(recommendUser));
  6. }

3.3、查询推荐列表APP接口实现

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

3.3.1、TanHuaController

  1. /**
  2. * 探花
  3. *
  4. * @return
  5. */
  6. @GetMapping("cards")
  7. public ResponseEntity<List<TodayBest>> queryCardsList() {
  8. try {
  9. List<TodayBest> list = this.tanHuaService.queryCardsList();
  10. return ResponseEntity.ok(list);
  11. } catch (Exception e) {
  12. e.printStackTrace();
  13. }
  14. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  15. }

3.3.2、TanHuaService

  1. #默认推荐列表
  2. tanhua.default.recommend.users=2,3,8,10,18,20,24,29,27,32,36,37,56,64,75,88
  1. @Reference(version = "1.0.0")
  2. private RecommendUserApi recommendUserApi;
  3. @Value("${tanhua.default.recommend.users}")
  4. private String defaultRecommendUsers;
  5. @Reference(version = "1.0.0")
  6. private UserLikeApi userLikeApi;
  7. /**
  8. * 查询推荐卡片列表,从推荐列表中随机选取10个用户
  9. *
  10. * @return
  11. */
  12. public List<TodayBest> queryCardsList() {
  13. User user = UserThreadLocal.get();
  14. int count = 50;
  15. //查询到的50条数据,并不是用来直接展现,需要从这50条数据中随机返回一些数据
  16. List<RecommendUser> recommendUserList = this.recommendUserApi.queryCardList(user.getId(), count);
  17. if (CollUtil.isEmpty(recommendUserList)) {
  18. recommendUserList = new ArrayList<>();
  19. //默认推荐列表
  20. List<String> list = StrUtil.split(defaultRecommendUsers, ',');
  21. for (String userId : list) {
  22. RecommendUser recommendUser = new RecommendUser();
  23. recommendUser.setToUserId(user.getId());
  24. recommendUser.setUserId(Convert.toLong(userId));
  25. recommendUserList.add(recommendUser);
  26. }
  27. }
  28. //计算展现的数量,默认展现10个
  29. int showCount = Math.min(10, recommendUserList.size());
  30. List<RecommendUser> result = new ArrayList<>();
  31. for (int i = 0; i < showCount; i++) {
  32. //TODO 可能重复
  33. int index = RandomUtil.randomInt(0, recommendUserList.size());
  34. RecommendUser recommendUser = recommendUserList.get(index);
  35. result.add(recommendUser);
  36. }
  37. List<Object> userIdList = CollUtil.getFieldValues(result, "userId");
  38. List<UserInfo> userInfoList = this.userInfoService.queryUserInfoByUserIdList(userIdList);
  39. List<TodayBest> todayBests = new ArrayList<>();
  40. for (UserInfo userInfo : userInfoList) {
  41. TodayBest todayBest = new TodayBest();
  42. todayBest.setId(userInfo.getUserId());
  43. todayBest.setAge(userInfo.getAge());
  44. todayBest.setAvatar(userInfo.getLogo());
  45. todayBest.setGender(userInfo.getSex().name().toLowerCase());
  46. todayBest.setNickname(userInfo.getNickName());
  47. todayBest.setTags(Convert.toStrArray(StrUtil.split(userInfo.getTags(), ',')));
  48. todayBest.setFateValue(0L);
  49. todayBests.add(todayBest);
  50. }
  51. return todayBests;
  52. }

3.3.3、测试

day08-搜附近以及探花功能实现 - 图8
day08-搜附近以及探花功能实现 - 图9
效果:
day08-搜附近以及探花功能实现 - 图10

3.4、左滑右滑

左滑:“不喜欢”,右滑:“喜欢”,如果双方喜欢,那么就会成为好友。
喜欢的接口文档:https://mock-java.itheima.net/project/35/interface/api/599
不喜欢的接口文档:https://mock-java.itheima.net/project/35/interface/api/605

3.4.1、TanHuaController

  1. /**
  2. * 喜欢
  3. *
  4. * @param likeUserId
  5. * @return
  6. */
  7. @GetMapping("{id}/love")
  8. public ResponseEntity<Void> likeUser(@PathVariable("id") Long likeUserId) {
  9. try {
  10. this.tanHuaService.likeUser(likeUserId);
  11. return ResponseEntity.ok(null);
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. }
  15. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  16. }
  17. /**
  18. * 不喜欢
  19. *
  20. * @param likeUserId
  21. * @return
  22. */
  23. @GetMapping("{id}/unlove")
  24. public ResponseEntity<Void> notLikeUser(@PathVariable("id") Long likeUserId) {
  25. try {
  26. this.tanHuaService.notLikeUser(likeUserId);
  27. return ResponseEntity.ok(null);
  28. } catch (Exception e) {
  29. e.printStackTrace();
  30. }
  31. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  32. }

3.4.2、TanHuaService

  1. //com.tanhua.server.service.TanHuaService
  2. public Boolean likeUser(Long likeUserId) {
  3. User user = UserThreadLocal.get();
  4. Boolean result = this.userLikeApi.likeUser(user.getId(), likeUserId);
  5. if (!result) {
  6. return false;
  7. }
  8. if (this.userLikeApi.isMutualLike(user.getId(), likeUserId)) {
  9. //相互喜欢成为好友
  10. this.imService.contactUser(likeUserId);
  11. }
  12. return true;
  13. }
  14. public Boolean notLikeUser(Long likeUserId) {
  15. User user = UserThreadLocal.get();
  16. return this.userLikeApi.notLikeUser(user.getId(), likeUserId);
  17. }

3.4.3、测试

day08-搜附近以及探花功能实现 - 图11
day08-搜附近以及探花功能实现 - 图12
user_like表,可以看到已经相互喜欢了:
day08-搜附近以及探花功能实现 - 图13
tanhua_users表,可以看到相互是好友了:
day08-搜附近以及探花功能实现 - 图14
环信平台:
day08-搜附近以及探花功能实现 - 图15

4、用户资料

在我的中心模块中,可以对个人信息做修改。
day08-搜附近以及探花功能实现 - 图16

4.1、基本信息

在前面实现的查询个人信息接口中,已经返回个人基本数据,所以可以直接展现出个人信息,下面只需要进行实现数据的保存即可。

4.4.1、接口信息

接口地址:https://mock-java.itheima.net/project/35/interface/api/887
day08-搜附近以及探花功能实现 - 图17
请求参数:

day08-搜附近以及探花功能实现 - 图18

4.4.2、MyCenterController

  1. //com.tanhua.server.controller.MyCenterController
  2. /**
  3. * 更新用户信息
  4. *
  5. * @param userInfoVo
  6. * @return
  7. */
  8. @PutMapping
  9. public ResponseEntity<Void> updateUserInfo(@RequestBody UserInfoVo userInfoVo){
  10. try {
  11. Boolean bool = this.myCenterService.updateUserInfo(userInfoVo);
  12. if(bool){
  13. return ResponseEntity.ok(null);
  14. }
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. }
  18. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  19. }

4.4.3、MyCenterService

  1. //com.tanhua.server.service.MyCenterService
  2. public Boolean updateUserInfo(UserInfoVo userInfoVo) {
  3. User user = UserThreadLocal.get();
  4. UserInfo userInfo = new UserInfo();
  5. userInfo.setUserId(user.getId());
  6. userInfo.setAge(Integer.valueOf(userInfoVo.getAge()));
  7. userInfo.setSex(StringUtils.equalsIgnoreCase(userInfoVo.getGender(), "man") ? SexEnum.MAN : SexEnum.WOMAN);
  8. userInfo.setBirthday(userInfoVo.getBirthday());
  9. userInfo.setCity(userInfoVo.getCity());
  10. userInfo.setEdu(userInfoVo.getEducation());
  11. userInfo.setIncome(StringUtils.replaceAll(userInfoVo.getIncome(), "K", ""));
  12. userInfo.setIndustry(userInfoVo.getProfession());
  13. userInfo.setMarriage(userInfoVo.getMarriage() == 1 ? "已婚" : "未婚");
  14. return this.userInfoService.updateUserInfoByUserId(userInfo);
  15. }

4.4.4、UserInfoService

  1. //com.tanhua.server.service.UserInfoService
  2. public boolean updateUserInfoByUserId(UserInfo userInfo) {
  3. QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
  4. queryWrapper.eq("user_id", userInfo.getUserId());
  5. return this.userInfoMapper.update(userInfo, queryWrapper) > 0;
  6. }

4.4.5、bug修复

在之前的查询个人信息中接口中,返回数据中的性别数据有误,需要返回man或woman。
如下:

  1. //com.tanhua.server.service.MyCenterService
  2. public UserInfoVo queryUserInfoByUserId(Long userId) {
  3. if (ObjectUtil.isEmpty(userId)) {
  4. //如果查询id为null,就表示查询当前用户信息
  5. userId = UserThreadLocal.get().getId();
  6. }
  7. //查询用户信息
  8. UserInfo userInfo = this.userInfoService.queryUserInfoByUserId(userId);
  9. if (ObjectUtil.isEmpty(userInfo)) {
  10. return null;
  11. }
  12. UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class, "marriage");
  13. userInfoVo.setGender(userInfo.getSex().getValue() == 1 ? "man" : "women");
  14. userInfoVo.setMarriage(StrUtil.equals("已婚", userInfo.getMarriage()) ? 1 : 0);
  15. return userInfoVo;
  16. }

4.2、更新头像

上传头像使用sso中的上传逻辑即可,只是路径不同,所以我们只需要修改nginx配置和在sso中定义Controller即可。
接口文档:https://mock-java.itheima.net/project/35/interface/api/881

  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 /users/header { #请求路径中凡是以/user/header开头的请求,转发到sso系统
  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:18080; #转发请求
  47. }
  48. location / { #上面未匹配到的在这里处理
  49. client_max_body_size 300m;
  50. proxy_connect_timeout 300s;
  51. proxy_send_timeout 300s;
  52. proxy_read_timeout 300s;
  53. proxy_pass http://127.0.0.1:18081; #转发请求到server系统
  54. }
  55. }
  56. }

4.2.2、MyCenterController

在sso工程中定义MyCenterController。

  1. package com.tanhua.sso.controller;
  2. import com.tanhua.sso.vo.ErrorResult;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.http.HttpStatus;
  5. import org.springframework.http.ResponseEntity;
  6. import org.springframework.web.bind.annotation.*;
  7. import org.springframework.web.multipart.MultipartFile;
  8. @RestController
  9. @RequestMapping("users")
  10. public class MyCenterController {
  11. @Autowired
  12. private UserInfoController userInfoController;
  13. /**
  14. * 上传头像
  15. *
  16. * @param file
  17. * @param token
  18. * @return
  19. */
  20. @PostMapping("header")
  21. public ResponseEntity<Object> saveLogo(@RequestParam("headPhoto") MultipartFile file, @RequestHeader("Authorization") String token) {
  22. return this.userInfoController.saveUserLogo(file, token);
  23. }
  24. }