一、接口设计
1. 请求参数:封装添加队伍参数 TeamAddRequest
package com.example.usercenter.model.request;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;import java.io.Serializable;
import java.util.Date;/*** 用户登录请求参数* @author Ghost* @version 1.0*/
@Data
public class TeamAddRequest implements Serializable{private static final long serialVersionUID = 6993746803531411917L;/*** id*/@TableId(type = IdType.AUTO)private Long id;/*** 队伍名称*/private String name;/*** 描述*/private String description;/*** 最大人数*/private Integer maxNum;/*** 过期时间*/private Date expireTime;/*** 用户id*/private Long userId;/*** 0 - 公开,1 - 私有,2 - 加密*/private Integer status;/*** 密码*/private String password;
}
2. 请求路径:/team/add
3. 请求方式:POST
4. 响应数据:添加成功的队伍 id
二、业务逻辑
1. 请求参数是否为空?
2. 是否登录,未登录不允许创建
3. 校验信息
- 队伍人数 > 1 且 <= 20
- 队伍标题 <= 20
- 描述 <= 512
- status 是否公开(int)不传默认为 0(公开)
- 如果 status 是加密状态,一定要有密码,且密码 <= 32
- 超时时间 > 当前时间
- 校验用户最多创建 5 个队伍
4. 插入队伍信息到队伍表
5. 插入用户 => 队伍关系到关系表
注意❗
- 操作两张表(队伍表和用户队伍关系表)时需要开启事务功能,使用 @Transactional 注解在方法上开启事务
- 如果添加队伍和添加用户队伍关系中间出现异常,添加队伍也失败,回滚到方法执行之前
- Controller
@PostMapping("/add")public BaseResponse<Long> addTeam(@RequestBody TeamAddRequest teamAddRequest, HttpServletRequest request) {if (teamAddRequest == null) {throw new BusinessException(ErrorCode.PARAMS_ERROR);}User loginUser = userService.getLoginUser(request);Team team = new Team();BeanUtils.copyProperties(teamAddRequest, team);long teamId = teamService.addTeam(team, loginUser);return ResultUtils.success(teamId);}
- Service
package com.example.usercenter.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.usercenter.common.ErrorCode;
import com.example.usercenter.constant.enums.TeamStatusEnum;
import com.example.usercenter.exception.BusinessException;
import com.example.usercenter.model.domain.Team;
import com.example.usercenter.model.domain.User;
import com.example.usercenter.model.domain.UserTeam;
import com.example.usercenter.service.TeamService;
import com.example.usercenter.mapper.TeamMapper;
import com.example.usercenter.service.UserTeamService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.util.Date;
import java.util.Optional;/**
* @author 20890
* @description 针对表【team(队伍)】的数据库操作Service实现
* @createDate 2024-01-22 18:27:55
*/
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>implements TeamService{@Resourceprivate UserTeamService userTeamService;@Override@Transactional(rollbackFor = Exception.class)public Long addTeam(Team team, User loginUser) {// 1. 请求参数是否为空?if (team == null) {throw new BusinessException(ErrorCode.PARAMS_ERROR);}// 2. 是否登录,未登录不允许创建if (loginUser == null) {throw new BusinessException(ErrorCode.NOT_LOGIN);}final long userId = loginUser.getId();// 3. 校验信息// 1. 队伍人数 > 1 且 <= 20int maxNum = Optional.ofNullable(team.getMaxNum()).orElse(0);if (maxNum < 1 || maxNum > 20) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍人数不符合要求");}// 2. 队伍标题 <= 20String name = team.getName();if (StringUtils.isBlank(name) || name.length() > 20) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍标题不符合要求");}// 3. 描述 <= 512String description = team.getDescription();if (StringUtils.isNotBlank(description) && description.length() > 512) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍描述不符合要求");}// 4. status 是否公开(int)不传默认为 0(公开)int status = Optional.ofNullable(team.getStatus()).orElse(0);TeamStatusEnum teamStatus = TeamStatusEnum.getTeamEnumByValue(status);if (teamStatus == null) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍状态不符合要求");}// 5. 如果 status 是加密状态,一定要有密码,且密码 <= 32String password = team.getPassword();if (status == TeamStatusEnum.SECRET.getValue() && (StringUtils.isBlank(password) || password.length() > 32)) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍密码不符合要求");}// 6. 超时时间 > 当前时间Date expireTime = team.getExpireTime();if (new Date().after(expireTime)) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "超时时间已到,队伍失效");}// 7. 校验用户最多创建 5 个队伍// TODO 有 bug,用户可能同时创建很多个队伍QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();queryWrapper.eq("user_id", userId);long hasTeamNum = userTeamService.count(queryWrapper);if (hasTeamNum >= 5) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "每个用户最多创建 5 个队伍");}// 4. 插入队伍信息到队伍表team.setId(null);team.setUserId(userId);boolean result = this.save(team);Long teamId = team.getId();if (!result || teamId == null) {throw new BusinessException(ErrorCode.SYSTEM_ERROR,"创建队伍失败");}// 5. 插入用户 => 队伍关系到关系表UserTeam userTeam = new UserTeam();userTeam.setUserId(userId);userTeam.setTeamId(teamId);userTeam.setJoinTime(new Date());result = userTeamService.save(userTeam);if (!result) {throw new BusinessException(ErrorCode.SYSTEM_ERROR,"创建队伍失败");}return teamId;}
}
三、接口测试
1. 使用 Knife4j 接口文档进行测试
2. 查看数据库