1.完善个人信息分析
用户在首次登录的时候要完善个人信息,包括性别,昵称,生日,城市,头像等。
其中头像数据需要做图片上传,这里使用的是阿里云的oss服务作为我们图片服务器,并且对头像要做人脸识别,非人脸照片不得上传。
包括连个步骤
填写用户基础信息
上传用户头像,更新用户的头像信息
用到的数据库表
用户表 (tb_user): id,mobile,password,created,updated
用户详情表(tb_info)
CREATE TABLE `tb_user_info` (
`id` bigint(20) NOT NULL,
`nickname` varchar(50) DEFAULT NULL COMMENT '昵称',
`avatar` varchar(200) DEFAULT NULL COMMENT '用户头像',
`tags` varchar(50) DEFAULT '单身,本科,年龄相仿' COMMENT '用户标签:多个用逗号分隔',
`gender` varchar(10) DEFAULT '3' COMMENT '性别,1-男,2-女,3-未知',
`age` int(11) DEFAULT NULL COMMENT '用户年龄',
`education` varchar(20) DEFAULT NULL COMMENT '学历',
`city` varchar(100) DEFAULT NULL COMMENT '居住城市',
`birthday` varchar(20) DEFAULT NULL COMMENT '生日',
`cover_pic` varchar(200) DEFAULT NULL COMMENT '封面图片',
`profession` varchar(20) DEFAULT NULL COMMENT '行业',
`income` varchar(20) DEFAULT NULL COMMENT '收入',
`created` datetime DEFAULT NULL,
`updated` datetime DEFAULT NULL,
`marriage` int(1) DEFAULT '0' COMMENT '0:未婚,1:已婚',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息表';
用户表和信息表:一对一关系
维护关系:公用主键的关系(用户id==1,用户信息id==1)
完善个人信息流程
移动端发起完善用户信息请求,tanhua-server消费者调用tanhua-dubbo服务提供者,消费者从token中获取用户信息,获取到user,完善用户信息,保存用户表信息,如果获取不到user,提示登录超时
上传头像的流程
移动端发请求,完善用户信息请求,消费者处理请求,调用服务提供者(处理数据库),消费者从token中获取用户信息,获取到user进行人脸检查,调用百度云,如果没有检查到人脸,提示重新上传头像,上传头像,调用阿里云,如果上传头像失败,则提示上传头像失败,请稍后在试,成功则更换头像
token的有效期分析
用户登录成功之后,服务端返回Token作为客户端和服务端间用户认证秘钥,已经将token存入到redis中,但是token的有效期如何实现
根据token获取用户
客户端发起请求,会在请求头header中携带Authorization参数。后端开发人员获取Authorization参数后,从redis中获取用户对象,并续期。
根据token获取用户信息
/**
* 根据token获取user对象
* @param token
* @return
*/
public User getUserByToken(String token) {
//a.根据请求头的token从redis查询user对象获取userId
String userStr = redisTemplate.opsForValue().get("TOKEN_" + token);
if (StringUtils.isEmpty(userStr)) {
return null;
}
redisTemplate.expire("TOKEN_" + token,1,TimeUnit.DAYS);
//将userStr转为User对象
return JSON.parseObject(userStr, User.class);
}
服务提供者
UserInfo与UserInfoVo
tanhua-domain模块中编写用户信息实体类UserInfo
package com.tanhua.domain.db;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class UserInfo extends BasePojo{
@TableId(type= IdType.INPUT)
private Long id; //用户id
private String nickname; //昵称
private String avatar; //用户头像
private String birthday; //生日
private String gender; //性别
private Integer age; //年龄
private String city; //城市
private String income; //收入
private String education; //学历
private String profession; //行业
private Integer marriage; //婚姻状态
private String tags; //用户标签:多个用逗号分隔
private String coverPic; // 封面图片
}
页面返回的数据
package com.tanhua.domain.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class UserInfoVo implements Serializable {
private Long id; //用户id
private String nickname; //昵称
private String avatar; //用户头像
private String birthday; //生日
private String gender; //性别
private String age; //年龄
private String city; //城市
private String income; //收入
private String education; //学历
private String profession; //行业
private Integer marriage; //婚姻状态
}
UserInfoApi
package com.tanhua.dubbo.api.db;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
/**
* 用户信息服务接口
*/
public interface UserInfoApi {
/**
* 完成用户信息保存
*/
void saveUserInfo(UserInfo userInfo);
/**
* 根据用户id更新头像
*/
void updateUserInfo(UserInfo userInfo);
/**
* 根据用户id查询用户信息
*/
UserInfo queryUserInfo(Long userId);
}
UserInfoMapper
package com.tanhua.dubbo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tanhua.domain.db.UserInfo;
/**
* 持久层接口
*/
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}
UserIfoApiImpl
package com.tanhua.dubbo.api.db;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.dubbo.mapper.UserInfoMapper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
/**
* 用户信息服务接口实现类
*/
@Service
public class UserInfoApiImpl implements UserInfoApi {
@Autowired
UserInfoMapper userInfoMapper;
/**
* 完成用户信息保存
*/
@Override
public void saveUserInfo(UserInfo userInfo) {
userInfoMapper.insert(userInfo);
}
/**
* 根据用户id更新头像
*/
@Override
public void updateUserInfo(UserInfo userInfo) {
//保证一定要传入用户id 用户头像
userInfoMapper.updateById(userInfo);
}
/**
* 根据用户id查询用户信息
*/
@Override
public UserInfo queryUserInfo(Long userId) {
return userInfoMapper.selectById(userId);
}
}
服务消费者
UserController
package com.tanhua.server.controller;
import com.tanhua.domain.vo.*;
import com.tanhua.server.service.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 用户信息控制层
*/
@RestController
@RequestMapping("/users")
public class UserInfoController {
@Autowired
private UserInfoService userInfoService;
/**
* 查询用户信息
*/
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity queryUserInfo(Long userID, Long huanxinID) {
UserInfoVo userInfoVo = userInfoService.queryUserInfo(userID, huanxinID);
return ResponseEntity.ok(userInfoVo);
}
/**
* 更新用户信息
*/
@RequestMapping(method = RequestMethod.PUT)
public ResponseEntity updateUserInfo(@RequestBody UserInfoVo userInfoVo) {
userInfoService.updateUserInfo(userInfoVo);
return ResponseEntity.ok(null);
}
/**
* 用户通用设置 - 查询
*/
@RequestMapping(value = "/settings", method = RequestMethod.GET)
public ResponseEntity querySettings() {
SettingsVo settingsVo = userInfoService.querySettings();
return ResponseEntity.ok(settingsVo);
}
/**
* 用户通用设置 - 修改
*/
@RequestMapping(value = "/notifications/setting", method = RequestMethod.POST)
public ResponseEntity updateSettings(@RequestBody Map<String, Boolean> params) {
Boolean likeNotification = params.get("likeNotification");
Boolean pinglunNotification = params.get("pinglunNotification");
Boolean gonggaoNotification = params.get("gonggaoNotification");
userInfoService.updateSettings(likeNotification,
pinglunNotification,
gonggaoNotification);
return ResponseEntity.ok(null);
}
}
UserInfoService
package com.tanhua.server.service;
import com.alibaba.fastjson.JSON;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.commons.templates.HuanXinTemplate;
import com.tanhua.domain.db.Question;
import com.tanhua.domain.db.Settings;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Friend;
import com.tanhua.domain.mongo.RecommendUser;
import com.tanhua.domain.vo.*;
import com.tanhua.dubbo.api.db.QuestionApi;
import com.tanhua.dubbo.api.db.SettingsApi;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.FriendApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.GetAgeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* 用户信息业务逻辑处理层
*/
@Service
@Slf4j
public class UserInfoService {
@Reference
private UserInfoApi userInfoApi;
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private UserService userService;
@Reference
private QuestionApi questionApi;
@Reference
private SettingsApi settingsApi;
@Reference
private FriendApi friendApi;//互相喜欢数量查询
@Reference
private UserLikeApi userLikeApi;//我的喜欢 、 粉丝 数量
@Autowired
private HuanXinTemplate huanXinTemplate;
/**
* 查询用户信息
*/
public UserInfoVo queryUserInfo(Long userID, Long huanxinID) {
Long currentUserId;
Long userId = UserHolder.getUserId();//用户id
//3.根据userID huanxinID如果不为空使用此值
if (!StringUtils.isEmpty(userID)) {
currentUserId = userID;
} else if (!StringUtils.isEmpty(huanxinID)) {
currentUserId = huanxinID;
} else {
//4.如果userID huanxinID则使用token中获取的userId
currentUserId = userId;
}
//5.根据userId调用服务根据用户id查询用户信息UserInfo
UserInfo userInfo = userInfoApi.queryUserInfo(currentUserId);
//6.将UserInfo转为UserInfoVo
UserInfoVo userInfoVo = new UserInfoVo();
BeanUtils.copyProperties(userInfo, userInfoVo);
//7.age处理下 Integer 转为String
userInfoVo.setAge(String.valueOf(userInfo.getAge()));
//8.返回
return userInfoVo;
}
/**
* 更新用户信息
*/
public void updateUserInfo(UserInfoVo userInfoVo) {
Long userId = UserHolder.getUserId();//用户id
//3.根据用户id调用用户信息服务方法更新
UserInfo userInfo = new UserInfo();
//将userInfoVo转为userInfo
BeanUtils.copyProperties(userInfoVo, userInfo);
userInfo.setId(userId);//当前用户id
//根据出生年月日 计算 年龄
if (!StringUtils.isEmpty(userInfoVo.getBirthday())) {
userInfo.setAge(GetAgeUtil.getAge(userInfoVo.getBirthday()));
}
userInfoApi.updateUserInfo(userInfo);
}
/**
* 用户通用设置 - 查询
*/
public SettingsVo querySettings() {
Long userId = UserHolder.getUserId();
//a.根据用户id查询问题
Question question = questionApi.queryByUserId(userId);
String txt = "";
if (question == null || StringUtils.isEmpty(question.getTxt())) {
//如果为空 设置默认问题
txt = "约吗?";
} else {
txt = question.getTxt();
}
//b.根据用户id查询手机号
String mobile = UserHolder.getUser().getMobile();
//c.根据用户id查询通知设置
Settings settings = settingsApi.queryByUserId(userId);
if (settings == null) {
//如果为空 设置默认值
settings = new Settings();
settings.setGonggaoNotification(false);
settings.setPinglunNotification(false);
settings.setLikeNotification(false);
}
// d.将以上调用服务结果封装Vo返回
SettingsVo settingsVo = new SettingsVo();
BeanUtils.copyProperties(settings,settingsVo);
settingsVo.setId(userId);//用户id
settingsVo.setStrangerQuestion(txt);//用户的问题
settingsVo.setPhone(mobile);//用户手机号
return settingsVo;
}
/**
* 用户通用设置 - 修改
*/
public void updateSettings(Boolean likeNotification, Boolean pinglunNotification, Boolean gonggaoNotification) {
//1.根据当前用户id查询通用设置表
Long userId = UserHolder.getUserId();
Settings settings = settingsApi.queryByUserId(userId);
//2.如果记录不存在,则保存通用设置表
if(settings == null){
settings = new Settings();
settings.setUserId(userId);//设置用户id
settings.setLikeNotification(likeNotification);//喜欢通知
settings.setPinglunNotification(pinglunNotification);//评论通知
settings.setGonggaoNotification(gonggaoNotification);//公告通知
settingsApi.saveSettings(settings);
}
//3.如果记录存在,更新通用设置表
else
{
settings.setLikeNotification(likeNotification);//喜欢通知
settings.setPinglunNotification(pinglunNotification);//评论通知
settings.setGonggaoNotification(gonggaoNotification);//公告通知
settingsApi.updateByUserId(settings);
}
}
}
总结
-
图片上传(OSS云存储),人脸检测(百度AI)
-
改造登录功能(重点)
-
登录成功,将用户对象存入到redis
-
客户端后续访问,在请求头中携带参数(Authorization),从redis中获取用户
-
-
完善个人信息(重点)
-
第一次注册访问:填写基础的用户信息(保存用户信息表)
-
客户端拍照,上传到服务端(人脸检测,上传到oss,更新用户信息)
-
-
个人信息管理(根据id查询,更新,更新用户头像)