文章目录
- 前言
- [一、B 端用户服务](#一、B 端用户服务)
-
- [1.1 在 admin-service 下创建 user 包](#1.1 在 admin-service 下创建 user 包)
-
- [1.1.1 在 user 包下创建 config、controller、domain、mapper、service 包](#1.1.1 在 user 包下创建 config、controller、domain、mapper、service 包)
- [1.1.2 在 domain 包下创建 dto、vo、entity](#1.1.2 在 domain 包下创建 dto、vo、entity)
- [1.1.3 在 mapper 下创建数据库接口](#1.1.3 在 mapper 下创建数据库接口)
- [1.1.4 在 controller 包下创建控制器](#1.1.4 在 controller 包下创建控制器)
- [1.1.5 在 service 包下创建接口及其实体类](#1.1.5 在 service 包下创建接口及其实体类)
- [1.1.6 在 config 包下创建配置类](#1.1.6 在 config 包下创建配置类)
- [二、验证用户登录和 B 端用户登录](#二、验证用户登录和 B 端用户登录)
- END
鸡汤:
● 代码会过时,但解决问题的思维永远闪光。
● 记得:关掉屏幕时,窗外的夕阳、家人的笑脸、散步的微风------这些"非代码变量",才是生活的主函数。
前言
前面实现了登录认证服务,现在开始实现用户服务。
一、B 端用户服务
因为 B 端用户流量小、改动少,所以可以将 B 端用户登录服务放在 admin 基础管理服务里
1.1 在 admin-service 下创建 user 包

1.1.1 在 user 包下创建 config、controller、domain、mapper、service 包

1.1.2 在 domain 包下创建 dto、vo、entity

dto:
PasswordLoginDTO:
java
package com.my.adminservice.user.domain.dto;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* 账号密码登录信息
*/
@Getter
@Setter
public class PasswordLoginDTO implements Serializable {
/**
* 手机号
*/
@NotBlank(message = "手机号不能为空")
private String phone;
/**
* 密码
*/
@NotBlank(message = "密码不能为空")
private String password;
}
SysLoginUserDTO:
java
package com.my.adminservice.user.domain.dto;
import com.my.adminservice.user.domain.vo.SysLoginUserVO;
import com.my.commoncore.utils.BeanCopyUtil;
import com.my.commonsecurity.domain.dto.LoginUserDTO;
import lombok.Data;
@Data
public class SysLoginUserDTO extends LoginUserDTO {
/**
* 昵称
*/
private String nickName;
/**
* 身份
*/
private String identity;
/**
* 状态
*/
private String status;
/**
* B端用户登录信息DTO转VO
* @return B端用户登录信息VO
*/
public SysLoginUserVO convertToVO() {
SysLoginUserVO sysLoginUserVO = new SysLoginUserVO();
BeanCopyUtil.copyProperties(this, sysLoginUserVO);
return sysLoginUserVO;
}
}
SysUserDTO:
java
package com.my.adminservice.user.domain.dto;
import com.my.adminservice.user.domain.vo.SysUserVO;
import com.my.commoncore.utils.BeanCopyUtil;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
/**
* B端用户信息
*/
@Data
public class SysUserDTO {
/**
* B端人员用户ID
*/
private Long id;
/**
* 用户昵称
*/
@NotBlank(message = "昵称不能为空")
private String nickName;
/**
* 手机号
*/
private String phoneNumber;
/**
* 密码
*/
private String password;
/**
* 身份
*/
private String identity;
/**
* 备注
*/
private String remark;
/**
* 状态
*/
@NotBlank(message = "状态不能为空")
private String status;
/**
* 校验密码是否合理
* @return 布尔类型
*/
public boolean checkPassword() {
if(!StringUtils.isNotBlank(password)){
return false;
}
if(password.length() > 20 || password.length() < 6){
return false;
}
return password.matches("^[a-zA-Z0-9]+$");
}
/**
* DTO转换VO
* @return B端用户VO
*/
public SysUserVO convertToVO() {
SysUserVO sysUserVo = new SysUserVO();
sysUserVo.setId(this.id);
sysUserVo.setIdentity(this.identity);
sysUserVo.setPhoneNumber(this.phoneNumber);
sysUserVo.setNickName(this.nickName);
sysUserVo.setStatus(this.status);
sysUserVo.setRemark(this.remark);
return sysUserVo;
}
}
SysUserListReqDTO:
java
package com.my.adminservice.user.domain.dto;
import lombok.Data;
import java.io.Serializable;
/**
* B端用户查询DTO
*/
@Data
public class SysUserListReqDTO implements Serializable {
/**
* 用户ID
*/
private Long id;
/**
* 手机号
*/
private String phoneNumber;
/**
* 状态
*/
private String status;
}
vo:
SysLoginUserVO:
java
package com.my.adminservice.user.domain.vo;
import com.my.commonsecurity.domain.vo.LoginUserVO;
import lombok.Data;
/**
* B端用户登录信息
*/
@Data
public class SysLoginUserVO extends LoginUserVO {
/**
* 昵称
*/
private String nickName;
/**
* 身份
*/
private String identity;
/**
* 状态
*/
private String status;
}
SysUserVO:
java
package com.my.adminservice.user.domain.vo;
import lombok.Data;
import java.io.Serializable;
/**
* B端用户查询VO
*/
@Data
public class SysUserVO implements Serializable {
/**
* 用户ID
*/
private Long id;
/**
* 用户昵称
*/
private String nickName;
/**
* 手机号
*/
private String phoneNumber;
/**
* 身份
*/
private String identity;
/**
* 备注
*/
private String remark;
/**
* 状态
*/
private String status;
}
entity:
SysUser:
java
package com.my.adminservice.user.domain.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.my.commondomain.domain.dataobject.BaseDO;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 系统用户对象 sys_user
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "sys_user")
public class SysUser extends BaseDO{
/**
* 用户昵称
*/
private String nickName;
/**
* 手机号
*/
private String phoneNumber;
/**
* 密码
*/
private String password;
/**
* 身份
*/
private String identity;
/**
* 备注
*/
private String remark;
/**
* 状态
*/
private String status;
}
1.1.3 在 mapper 下创建数据库接口

SysUserMapper:
java
package com.my.adminservice.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.my.adminservice.user.domain.entity.SysUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 处理sys_user表
*/
@Mapper
public interface SysUserMapper extends BaseMapper<SysUser> {
SysUser selectByPhoneNumber(@Param("phoneNumber") String phone);
List<SysUser> selectUserList(SysUser selectList);
}
实现的 xml 文件
SysUserMapper.xml:
xml
<select id="selectByPhoneNumber" resultType="com.my.adminservice.user.domain.entity.SysUser">
select * from sys_user where phone_number = #{phoneNumber}
</select>
<select id="selectUserList" resultType="com.my.adminservice.user.domain.entity.SysUser">
select * from sys_user
<where>
<if test="id != null and id != ''">
and id = #{id}
</if>
<if test="phoneNumber != null and phoneNumber != ''">
and phone_number = #{phoneNumber}
</if>
<if test="status != null and status != ''">
and status = #{status}
</if>
</where>
</select>
<!-- <select id="selectList" resultType="com.my.adminservice.user.domain.entity.SysUser">-->
<!-- select * from sys_user-->
<!-- <where>-->
<!-- <if test="selectList.id != null and selectList.id != ''">-->
<!-- and id = #{id}-->
<!-- </if>-->
<!-- <if test="selectList.phoneNumber != null and selectList.phoneNumber != ''">-->
<!-- and phone_number = #{selectList.phoneNumber}-->
<!-- </if>-->
<!-- <if test="selectList.status != null and selectList.status != ''">-->
<!-- and status = #{selectList.status}-->
<!-- </if>-->
<!-- </where>-->
<!-- </select>-->
1.1.4 在 controller 包下创建控制器

SysUserController:
java
package com.my.adminservice.user.controller;
import com.my.adminservice.user.domain.dto.PasswordLoginDTO;
import com.my.adminservice.user.domain.dto.SysLoginUserDTO;
import com.my.adminservice.user.domain.dto.SysUserDTO;
import com.my.adminservice.user.domain.dto.SysUserListReqDTO;
import com.my.adminservice.user.domain.vo.SysLoginUserVO;
import com.my.adminservice.user.domain.vo.SysUserVO;
import com.my.adminservice.user.service.ISysUserService;
import com.my.commondomain.domain.R;
import com.my.commonsecurity.domain.dto.TokenDTO;
import com.my.commonsecurity.domain.vo.TokenVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* B端用户服务控制器类
*/
@RestController
@RequestMapping("/sys_user")
public class SysUserController {
@Autowired
private ISysUserService sysUserService;
/**
* B端用户登录
*
* @param passwordLoginDTO B端用户登录DTO
* @return token信息
*/
@PostMapping("/login/password")
public R<TokenVO> login(@Validated @RequestBody PasswordLoginDTO passwordLoginDTO) {
TokenDTO login = sysUserService.login(passwordLoginDTO);
return R.success(login.convertTokenVO());
}
/**
* 新增或编辑用户
* @param sysUserDTO B端用户信息
* @return 用户ID
*/
@PostMapping("/add_edit")
public R<Long> addOrEditUser(@Validated @RequestBody SysUserDTO sysUserDTO) {
return R.success(sysUserService.addOrEditUser(sysUserDTO));
}
/**
* 查询B端用户
* @param listReqDTO 用户查询DTO
* @return B用户列表
*/
@PostMapping("/list")
public R<List<SysUserVO>> getUserList(@RequestBody SysUserListReqDTO listReqDTO) {
List<SysUserDTO> voList = sysUserService.getUserList(listReqDTO);
return R.success(voList.stream().map(SysUserDTO::convertToVO).toList());
}
/**
* 获取B端登录用户信息
* @return B端用户信息VO
*/
@GetMapping("/login_info/get")
public R<SysLoginUserVO> getLoginUser() {
SysLoginUserDTO sysLoginUserDTO = sysUserService.getLoginUser();
return R.success(sysLoginUserDTO.convertToVO());
}
}
1.1.5 在 service 包下创建接口及其实体类

ISysUserService:
java
package com.my.adminservice.user.service;
import com.my.adminservice.user.domain.dto.PasswordLoginDTO;
import com.my.adminservice.user.domain.dto.SysLoginUserDTO;
import com.my.adminservice.user.domain.dto.SysUserDTO;
import com.my.adminservice.user.domain.dto.SysUserListReqDTO;
import com.my.adminservice.user.domain.vo.SysUserVO;
import com.my.commonsecurity.domain.dto.TokenDTO;
import java.util.List;
public interface ISysUserService {
/**
* B端用户登录
*
* @param passwordLoginDTO B端用户登录DTO
* @return token信息
*/
TokenDTO login(PasswordLoginDTO passwordLoginDTO);
/**
* 新增或编辑用户
* @param sysUserDTO B端用户信息
* @return 用户ID
*/
Long addOrEditUser(SysUserDTO sysUserDTO);
/**
* 查询B端用户
* @param listReqDTO 用户查询DTO
* @return B用户列表
*/
List<SysUserDTO> getUserList(SysUserListReqDTO listReqDTO);
/**
* 获取B端登录用户信息
* @return B端用户信息VO
*/
SysLoginUserDTO getLoginUser();
}
SysUserServiceImpl:
java
package com.my.adminservice.user.service.Impl;
import cn.hutool.crypto.digest.DigestUtil;
import com.my.adminservice.config.service.ISysDictionaryService;
import com.my.adminservice.user.domain.dto.PasswordLoginDTO;
import com.my.adminservice.user.domain.dto.SysLoginUserDTO;
import com.my.adminservice.user.domain.dto.SysUserDTO;
import com.my.adminservice.user.domain.dto.SysUserListReqDTO;
import com.my.adminservice.user.domain.entity.SysUser;
import com.my.adminservice.user.mapper.SysUserMapper;
import com.my.adminservice.user.service.ISysUserService;
import com.my.commoncore.utils.AESUtil;
import com.my.commoncore.utils.BeanCopyUtil;
import com.my.commoncore.utils.VerifyUtil;
import com.my.commondomain.constants.DictionaryConstants;
import com.my.commondomain.constants.UserStatusConstants;
import com.my.commondomain.domain.ResultCode;
import com.my.commondomain.exception.ServiceException;
import com.my.commonsecurity.domain.dto.LoginUserDTO;
import com.my.commonsecurity.domain.dto.TokenDTO;
import com.my.commonsecurity.service.TokenService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class SysUserServiceImpl implements ISysUserService {
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private TokenService tokenService;
@Autowired
private ISysDictionaryService iSysDictionaryService;
/**
* B端用户登录
*
* @param passwordLoginDTO B端用户登录DTO
* @return token信息
*/
@Override
public TokenDTO login(PasswordLoginDTO passwordLoginDTO) {
// 1. 校验手机号是否,符合规范
if(!VerifyUtil.checkPhone(passwordLoginDTO.getPhone())) {
throw new ServiceException("手机号校验失败", ResultCode.ERROR_PHONE_FORMAT.getCode());
}
// 2. 检查数据库中是否存在
SysUser sysUser = sysUserMapper.selectByPhoneNumber(AESUtil.encryptHex(passwordLoginDTO.getPhone()));
if(sysUser == null) {
throw new ServiceException("手机号不存在", ResultCode.INVALID_PARA.getCode());
}
// 3. 校验密码
String password = AESUtil.decryptHex(passwordLoginDTO.getPassword());
if(!StringUtils.isNotBlank(password)) {
throw new ServiceException("密码解析为空", ResultCode.INVALID_PARA.getCode());
}
// 4. 加密比较 数据库返回密码
if(!sysUser.getPassword().equals(DigestUtil.sha256Hex(password))) {
throw new ServiceException("密码不正确", ResultCode.INVALID_PARA.getCode());
}
// 5. 校验用户状态
if(sysUser.getStatus().equals(UserStatusConstants.DISABLE)) {
throw new ServiceException(ResultCode.USER_DISABLE);
}
// 6. 需要用户登录的生命周期LoginUserDTO
LoginUserDTO loginUserDTO = new LoginUserDTO();
// 7. 设置登录信息
loginUserDTO.setUserId(sysUser.getId());
loginUserDTO.setUserName(sysUser.getNickName());
loginUserDTO.setUserFrom("sys");
// 8. 返回token,并注册到redis
return tokenService.createToken(loginUserDTO);
}
/**
* 新增或编辑用户
* @param sysUserDTO B端用户信息
* @return 用户ID
*/
@Override
public Long addOrEditUser(SysUserDTO sysUserDTO) {
// 创建一个空的SysUser对象
SysUser sysUser = new SysUser();
// 1. 处理新增逻辑
if(sysUserDTO.getId() == null) {
// 2. 首先校验手机号
if(!VerifyUtil.checkPhone(sysUserDTO.getPhoneNumber())) {
throw new ServiceException("手机号格式错误", ResultCode.INVALID_PARA.getCode());
}
// 3. 校验密码
if(!sysUserDTO.checkPassword()) {
throw new ServiceException("密码格式错误", ResultCode.INVALID_PARA.getCode());
}
// 4. 校验手机号唯一性
SysUser existUser = sysUserMapper.selectByPhoneNumber(AESUtil.encryptHex(sysUserDTO.getPhoneNumber()));
if(existUser != null) {
throw new ServiceException("手机号已被占用", ResultCode.INVALID_PARA.getCode());
}
// 5. 使用字典服务,校验身份信息
if(StringUtils.isBlank(sysUserDTO.getIdentity())) {
throw new ServiceException("用户身份不能为空", ResultCode.INVALID_PARA.getCode());
}
if(iSysDictionaryService.getDicDataByKey(DictionaryConstants.IDENTITY_TYPE_KEY, sysUserDTO.getIdentity()) == null) {
throw new ServiceException("无效的用户身份", ResultCode.INVALID_PARA.getCode());
}
// 6. 校验成功,执行新增用户逻辑
// 先填写 新增用户独有的字段
// 其他字段放在 修改逻辑里添加
sysUser.setPhoneNumber(AESUtil.encryptHex(sysUserDTO.getPhoneNumber()));
sysUser.setPassword(DigestUtil.sha256Hex(sysUserDTO.getPassword()));
sysUser.setIdentity(sysUserDTO.getIdentity());
}
// 7. 放入修改逻辑的字段
sysUser.setId(sysUserDTO.getId());
sysUser.setNickName(sysUserDTO.getNickName());
// 8. 判断修改或添加用户的状态
if(iSysDictionaryService.getDicDataByKey(DictionaryConstants.COMMON_STATUS,sysUserDTO.getStatus()) == null) {
throw new ServiceException("用户状态错误", ResultCode.INVALID_PARA.getCode());
}
sysUser.setStatus(sysUserDTO.getStatus());
sysUser.setRemark(sysUserDTO.getRemark());
// 9. 使用 mybatis-plus 的方法, 添加或修改
sysUserMapper.insertOrUpdate(sysUser);
// 10. 踢人
if (sysUserDTO.getId() != null && sysUserDTO.getStatus().equals("disable")) {
tokenService.delLoginUser(sysUserDTO.getId(), "sys");
}
return sysUser.getId();
}
/**
* 查询B端用户
* @param listReqDTO 用户查询DTO
* @return B用户列表
*/
@Override
public List<SysUserDTO> getUserList(SysUserListReqDTO listReqDTO) {
// 1. 构建查询参数
SysUser searchSysUser = new SysUser();
searchSysUser.setId(listReqDTO.getId());
searchSysUser.setPhoneNumber(AESUtil.encryptHex(listReqDTO.getPhoneNumber()));
searchSysUser.setStatus(listReqDTO.getStatus());
// 2. 调用 mapper 查询
List<SysUser> sysUserList = sysUserMapper.selectUserList(searchSysUser);
// 3. 返回结果
return sysUserList.stream().map(entity -> {
SysUserDTO dto = new SysUserDTO();
dto.setId(entity.getId());
dto.setNickName(entity.getNickName());
dto.setPhoneNumber(AESUtil.decryptHex(entity.getPhoneNumber()));
dto.setRemark(entity.getRemark());
dto.setIdentity(entity.getIdentity());
dto.setStatus(entity.getStatus());
return dto;
}).toList();
}
/**
* 获取B端登录用户信息
* @return B端用户信息VO
*/
@Override
public SysLoginUserDTO getLoginUser() {
// 1 获取当前登录用户
// 这是通过 ServletUtil 先获取 request 请求
// 在通过 SecurityUtil 获得token
// 在用 tokenService.getLoginUser() 获得当前用户信息
LoginUserDTO loginUser = tokenService.getLoginUser();
// 2. 对象判断
if(loginUser == null || loginUser.getUserId() == null) {
throw new ServiceException("用户令牌有误", ResultCode.INVALID_PARA.getCode());
}
// 3. 查数据库
SysUser sysUser = sysUserMapper.selectById(loginUser.getUserId());
if(sysUser == null) {
throw new ServiceException("用户不存在", ResultCode.INVALID_PARA.getCode());
}
// 4 封装结果
SysLoginUserDTO sysUserLoginDTO = new SysLoginUserDTO();
BeanCopyUtil.copyProperties(loginUser, sysUserLoginDTO);
BeanCopyUtil.copyProperties(sysUser, sysUserLoginDTO);
return sysUserLoginDTO;
}
}
1.1.6 在 config 包下创建配置类

修改用户信息,并通知其他服务修改信息
RabbitConfig:
java
package com.my.adminservice.user.config;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
// 交换机的名称
public final static String EXCHANGE_NAME = "edit_user_exchange";
// 队列名称
public final static String QUEUE_NAME = "edit_user_queue";
@Bean
public FanoutExchange editUserExchange() {
return ExchangeBuilder.fanoutExchange(EXCHANGE_NAME).durable(true).build();
}
@Bean
public Queue editUserQueue() {
return QueueBuilder.durable(QUEUE_NAME).build();
}
@Bean
public Binding editUserBinding(@Qualifier("editUserQueue") Queue editUserQueue
,@Qualifier("editUserExchange") FanoutExchange editUserExchange) {
return BindingBuilder.bind(editUserQueue).to(editUserExchange);
}
}
二、验证用户登录和 B 端用户登录
未登录时:

我之前的登录token,因为过期了,被网关鉴权服务拦截结果:

B 端用户登录:

添加 token:

结果:

END
B 端用户登录服务完成。