Browse Source

feat: 更新业务逻辑

master
xc-yjs 8 months ago
parent
commit
11be7d6090
  1. 6
      nla-common/pom.xml
  2. 33
      nla-common/src/main/java/cn/nla/common/config/WebConfig.java
  3. 8
      nla-common/src/main/java/cn/nla/common/constant/CacheKey.java
  4. 22
      nla-common/src/main/java/cn/nla/common/enums/AddressStatusEnum.java
  5. 8
      nla-common/src/main/java/cn/nla/common/enums/SendCodeEnum.java
  6. 16
      nla-common/src/main/java/cn/nla/common/exception/CustomExceptionHandler.java
  7. 60
      nla-common/src/main/java/cn/nla/common/interceptor/LoginInterceptor.java
  8. 17
      nla-common/src/main/java/cn/nla/common/model/LoginUser.java
  9. 35
      nla-common/src/main/java/cn/nla/common/util/CommonUtil.java
  10. 62
      nla-common/src/main/java/cn/nla/common/util/JWTUtil.java
  11. 4
      nla-common/src/test/java/tools/MyBatisPlusGenerator.java
  12. 50
      nla-user-service/src/main/java/cn/nla/user/controller/AddressController.java
  13. 14
      nla-user-service/src/main/java/cn/nla/user/controller/FileController.java
  14. 51
      nla-user-service/src/main/java/cn/nla/user/controller/NotifyController.java
  15. 41
      nla-user-service/src/main/java/cn/nla/user/controller/UserController.java
  16. 4
      nla-user-service/src/main/java/cn/nla/user/mapper/AddressMapper.java
  17. 4
      nla-user-service/src/main/java/cn/nla/user/mapper/UserMapper.java
  18. 6
      nla-user-service/src/main/java/cn/nla/user/model/DO/StudentDO.java
  19. 5
      nla-user-service/src/main/java/cn/nla/user/model/DO/TeacherDO.java
  20. 48
      nla-user-service/src/main/java/cn/nla/user/model/VO/AddressVO.java
  21. 38
      nla-user-service/src/main/java/cn/nla/user/model/VO/UserVO.java
  22. 17
      nla-user-service/src/main/java/cn/nla/user/model/entity/AddressEntity.java
  23. 4
      nla-user-service/src/main/java/cn/nla/user/model/entity/UserEntity.java
  24. 52
      nla-user-service/src/main/java/cn/nla/user/model/request/AddressAddRequest.java
  25. 16
      nla-user-service/src/main/java/cn/nla/user/model/request/UserLoginRequest.java
  26. 27
      nla-user-service/src/main/java/cn/nla/user/model/request/UserRegisterRequest.java
  27. 24
      nla-user-service/src/main/java/cn/nla/user/service/AddressService.java
  28. 21
      nla-user-service/src/main/java/cn/nla/user/service/NotifyService.java
  29. 14
      nla-user-service/src/main/java/cn/nla/user/service/UserService.java
  30. 67
      nla-user-service/src/main/java/cn/nla/user/service/impl/AddressServiceImpl.java
  31. 75
      nla-user-service/src/main/java/cn/nla/user/service/impl/NotifyServiceImpl.java
  32. 118
      nla-user-service/src/main/java/cn/nla/user/service/impl/UserServiceImpl.java
  33. 2
      nla-user-service/src/main/resources/mapper/AddressMapper.xml
  34. 2
      nla-user-service/src/main/resources/mapper/UserMapper.xml
  35. 4
      nla-user-service/src/test/java/AddressTest.java

6
nla-common/pom.xml

@ -72,6 +72,12 @@
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- JWT相关 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
</dependencies>
</project>

33
nla-common/src/main/java/cn/nla/common/config/WebConfig.java

@ -1,9 +1,11 @@
package cn.nla.common.config;
import cn.nla.common.interceptor.LoginInterceptor;
import cn.nla.common.interceptor.ResponseResultInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
/**
@ -11,10 +13,41 @@ import javax.annotation.Resource;
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Resource
private LoginInterceptor loginInterceptor;
@Resource
private ResponseResultInterceptor responseResultInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(responseResultInterceptor);
registry.addInterceptor(loginInterceptor)
//拦截的路径
.addPathPatterns("/user/*/**", "/address/*/**")
//排查不拦截的路径
.excludePathPatterns(
"/user/**/send",
"/user/**/captcha",
"/user/**/register",
"/user/**/login",
"/user/**/uploadFile");
}
/**
* 交换MappingJackson2HttpMessageConverter与第一位元素
* 让返回值类型为String的接口能正常返回包装结果
*
* @param converters initially an empty list of converters
*/
// @Override
// public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// for (int i = 0; i < converters.size(); i++) {
// if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
// MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter =
// (MappingJackson2HttpMessageConverter) converters.get(i);
// converters.set(i, converters.get(0));
// converters.set(0, mappingJackson2HttpMessageConverter);
// break;
// }
// }
// }
}

8
nla-common/src/main/java/cn/nla/common/constant/CacheKey.java

@ -0,0 +1,8 @@
package cn.nla.common.constant;
public class CacheKey {
/**
* 注册验证码第一个是类型第二个是接收号码
*/
public static final String CHECK_CODE_KEY = "code:%s:%s";
}

22
nla-common/src/main/java/cn/nla/common/enums/AddressStatusEnum.java

@ -0,0 +1,22 @@
package cn.nla.common.enums;
/**
* 收货地址状态
*/
public enum AddressStatusEnum {
/**
* 是默认收货地址
*/
DEFAULT_STATUS(1),
/**
* 非默认收货地址
*/
COMMON_STATUS(0);
private final int status;
AddressStatusEnum(int status) {
this.status = status;
}
public int getStatus() {
return status;
}
}

8
nla-common/src/main/java/cn/nla/common/enums/SendCodeEnum.java

@ -0,0 +1,8 @@
package cn.nla.common.enums;
public enum SendCodeEnum {
/**
* 用户注册
*/
USER_REGISTER;
}

16
nla-common/src/main/java/cn/nla/common/exception/CustomExceptionHandler.java

@ -2,6 +2,8 @@ package cn.nla.common.exception;
import cn.nla.common.annotation.ResponseResult;
import cn.nla.common.util.JsonData;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
@ -20,12 +22,17 @@ import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
@Slf4j
@ControllerAdvice
public class CustomExceptionHandler implements ResponseBodyAdvice<Object> {
@Resource
private ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
@ -45,6 +52,15 @@ public class CustomExceptionHandler implements ResponseBodyAdvice<Object> {
if (body instanceof JsonData) {
return body;
}
// 对于一般的类型都没有问题,当处理字符串类型时,会抛出 xxx.包装类 cannot be cast to java.lang.String 的类型转换的异常
if (body == null || body instanceof String) {
try {
return objectMapper.writeValueAsString(JsonData.buildSuccess(body));
} catch (JsonProcessingException e) {
log.error("JsonProcessingException", e);
}
}
return JsonData.buildSuccess(body);
}

60
nla-common/src/main/java/cn/nla/common/interceptor/LoginInterceptor.java

@ -0,0 +1,60 @@
package cn.nla.common.interceptor;
import cn.nla.common.model.LoginUser;
import cn.nla.common.util.CommonUtil;
import cn.nla.common.util.JWTUtil;
import cn.nla.common.util.JsonData;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 登录拦截器
*/
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
public static ThreadLocal<LoginUser> threadLocal = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
try {
String accessToken = request.getHeader("token");
if (accessToken == null) {
accessToken = request.getParameter("token");
}
if (StringUtils.isNotBlank(accessToken)) {
Claims claims = JWTUtil.checkJWT(accessToken);
if (claims == null) {
//告诉登录过期,新登录
CommonUtil.sendJsonMessage(response, JsonData.buildError("登录过期,请重新登录"));
return false;
}
Long id = Long.valueOf(claims.get("id").toString());
String headImg = (String) claims.get("head_img");
String mail = (String) claims.get("mail");
String name = (String) claims.get("name");
LoginUser loginUser = new LoginUser();
loginUser.setName(name);
loginUser.setHeadImg(headImg);
loginUser.setId(id);
loginUser.setMail(mail);
log.info("用户信息:{}", loginUser);
//通过threadLocal传递用户登录信息
threadLocal.set(loginUser);
return true;
}
} catch (Exception e) {
log.error("拦截器错误", e);
}
CommonUtil.sendJsonMessage(response, JsonData.buildError("token不存在,请重新登录"));
return false;
}
}

17
nla-common/src/main/java/cn/nla/common/model/LoginUser.java

@ -0,0 +1,17 @@
package cn.nla.common.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class LoginUser {
// 主键
private Long id;
// 名称
private String name;
// 头像
@JsonProperty("head_img")
private String headImg;
// 邮箱
private String mail;
}

35
nla-common/src/main/java/cn/nla/common/util/CommonUtil.java

@ -1,8 +1,12 @@
package cn.nla.common.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
@ -14,6 +18,8 @@ import java.util.Random;
@Slf4j
public class CommonUtil {
private static final String ALL_CHAR_NUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/**
* 获取请求的ip地址
*/
@ -89,4 +95,33 @@ public class CommonUtil {
}
return sb.toString();
}
/**
* 获取随机长度的串
*
* @param length 长度
*/
public static String getStringNumRandom(int length) {
//生成随机数字和字母,
Random random = new Random();
StringBuilder saltString = new StringBuilder(length);
for (int i = 1; i <= length; ++i) {
saltString.append(ALL_CHAR_NUM.charAt(random.nextInt(ALL_CHAR_NUM.length())));
}
return saltString.toString();
}
/**
* 响应json数据给前端
*/
public static void sendJsonMessage(HttpServletResponse response, Object obj) {
ObjectMapper objectMapper = new ObjectMapper();
response.setContentType("application/json; charset=utf-8");
try (PrintWriter writer = response.getWriter()) {
writer.print(objectMapper.writeValueAsString(obj));
response.flushBuffer();
} catch (IOException e) {
log.error("响应json数据给前端异常", e);
}
}
}

62
nla-common/src/main/java/cn/nla/common/util/JWTUtil.java

@ -0,0 +1,62 @@
package cn.nla.common.util;
import cn.nla.common.model.LoginUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
@Slf4j
public class JWTUtil {
/**
* token 过期时间正常是7天方便测试我们改为70
*/
private static final long EXPIRE = 1000L * 60 * 60 * 24 * 7 * 10;
/**
* 加密的秘钥
*/
private static final String SECRET = "yuan.net666";
/**
* 令牌前缀
*/
private static final String TOKEN_PREFIX = "yuan1024shop";
/**
* subject
*/
private static final String SUBJECT = "yuan";
/**
* 根据用户信息生成令牌
*/
public static String geneJsonWebToken(LoginUser loginUser) {
if (loginUser == null) {
throw new NullPointerException("loginUser对象为空");
}
String token = Jwts.builder().setSubject(SUBJECT)
//payload
.claim("head_img", loginUser.getHeadImg())
.claim("id", loginUser.getId())
.claim("name", loginUser.getName())
.claim("mail", loginUser.getMail())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
.signWith(SignatureAlgorithm.HS256, SECRET).compact();
token = TOKEN_PREFIX + token;
return token;
}
/**
* 校验token的方法
*/
public static Claims checkJWT(String token) {
try {
return Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody();
} catch (Exception e) {
log.info("jwt token解密失败");
return null;
}
}
}

4
nla-common/src/test/java/tools/MyBatisPlusGenerator.java

@ -31,7 +31,7 @@ public class MyBatisPlusGenerator {
// 设置⽣成的service接⼝的名字的⾸字⺟是否为I,默认Service是以I开头的
.setServiceName("%sService")
//实体类结尾名称
.setEntityName("%sDO")
.setEntityName("%sEntity")
//⽣成基本的resultMap
.setBaseResultMap(true)
//不使⽤AR模式
@ -66,7 +66,7 @@ public class MyBatisPlusGenerator {
.setMapper("mapper")
.setService("service")
.setController("controller")
.setEntity("model")
.setEntity("model.entity")
.setXml("mapper");
//5. 整合配置

50
nla-user-service/src/main/java/cn/nla/user/controller/AddressController.java

@ -2,13 +2,17 @@ package cn.nla.user.controller;
import cn.nla.common.annotation.ResponseResult;
import cn.nla.common.enums.BizCodeEnum;
import cn.nla.common.util.JsonData;
import cn.nla.user.model.request.AddressAddRequest;
import cn.nla.user.service.AddressService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
@ -17,19 +21,47 @@ import java.util.Map;
* @author YJs
* @since 2024-07-29
*/
@Api(tags = "收货地址控制器")
@Slf4j
@ResponseResult
@RestController
@RequestMapping("/addressDO")
@RequestMapping("/user/address/v1")
public class AddressController {
@Resource
private AddressService addressService;
@PostMapping("query")
@ResponseResult
public Object query(@RequestHeader Map<String, String> headers) {
log.info("请求参数:{}", headers.get("token"));
return List.of();
@ApiOperation("根据id查找地址详情")
@GetMapping("/find/{address_id}")
public Object detail(
@ApiParam(value = "地址id", required = true)
@PathVariable("address_id") long addressId) {
return JsonData.buildSuccess(addressService.detail(addressId));
}
@ApiOperation("新增收货地址")
@PostMapping("add")
public JsonData add(@ApiParam("地址对象") @RequestBody AddressAddRequest addressAddRequest) {
addressService.add(addressAddRequest);
return JsonData.buildSuccess();
}
}
/**
* 删除指定收货地址
*/
@ApiOperation("删除指定收货地址")
@DeleteMapping("/del/{address_id}")
public JsonData del(
@ApiParam(value = "地址id", required = true)
@PathVariable("address_id") int addressId) {
int rows = addressService.del(addressId);
return rows == 1 ? JsonData.buildSuccess() : JsonData.buildResult(BizCodeEnum.ADDRESS_DEL_FAIL);
}
/**
* 查询用户的全部收货地址
*/
@ApiOperation("查询用户的全部收货地址")
@GetMapping("/list")
public JsonData findUserAllAddress() {
return JsonData.buildSuccess(addressService.listUserAllAddress());
}
}

14
nla-user-service/src/main/java/cn/nla/user/controller/FileController.java

@ -2,22 +2,30 @@ package cn.nla.user.controller;
import cn.nla.common.util.JsonData;
import cn.nla.user.service.FileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
@Api(tags = "文件相关控制器")
@RestController
@RequestMapping("/file/v1")
@RequestMapping("/user/file/v1")
@Slf4j
public class FileController {
@Resource
private FileService fileService;
@PostMapping(value = "/uploadFile", name = "上传文件")
public JsonData uploadImage(MultipartFile file) {
@ApiOperation("用户头像上传")
@PostMapping(value = "/uploadFile")
public JsonData uploadHeaderImg(@ApiParam(value = "文件上传", required = true) @RequestPart("file") MultipartFile file) {
return JsonData.buildSuccess(fileService.uploadUserHeadImg(file));
}
}

51
nla-user-service/src/main/java/cn/nla/user/controller/NotifyController.java

@ -1,14 +1,14 @@
package cn.nla.user.controller;
import cn.nla.common.enums.BizCodeEnum;
import cn.nla.common.util.CheckUtil;
import cn.nla.common.enums.SendCodeEnum;
import cn.nla.common.util.CommonUtil;
import cn.nla.common.util.JsonData;
import cn.nla.user.service.MailService;
import cn.nla.user.service.NotifyService;
import com.google.code.kaptcha.Producer;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
@ -24,17 +24,16 @@ import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
*
*/
@Api(tags = "消息通知控制器")
@RestController
@RequestMapping("/user/v1")
@RequestMapping("/user/notify/v1")
@Slf4j
public class NotifyController {
@Resource
private Producer captchaProducer;
@Resource
private MailService mailService;
private NotifyService notifyService;
@Autowired
private StringRedisTemplate redisTemplate;
/**
@ -66,37 +65,11 @@ public class NotifyController {
}
}
@ApiOperation("获取图形验证码")
@GetMapping("send")
public JsonData sendCode(String from, String to) {
String cacheKey = String.format(from + "_%s", to);
String cacheValue = redisTemplate.opsForValue().get(cacheKey);
//如果不为空,则判断是否60秒内重复发送
if (StringUtils.isNotBlank(cacheValue)) {
long ttl = Long.parseLong(cacheValue.split("_")[1]);
//当前时间戳-验证码发送时间戳,如果小于60秒,则不给重复发送
if (System.currentTimeMillis() - ttl < 1000 * 60) {
log.info("重复发送验证码,时间间隔:{} 秒", (System.currentTimeMillis() - ttl) / 1000);
return JsonData.buildResult(BizCodeEnum.CODE_LIMITED);
}
}
//拼接验证码: 验证码+时间戳: 2322_324243232424324
String code = CommonUtil.getRandomCode(6);
String value = code + "_" + System.currentTimeMillis();
redisTemplate.opsForValue().set(cacheKey, value, CAPTCHA_CODE_EXPIRED, TimeUnit.MILLISECONDS);
if (CheckUtil.isEmail(to)) {
//邮箱验证码
mailService.sendMail(to, "电商验证码", code);
log.info("发送邮箱验证码[{}]成功!", code);
return JsonData.buildSuccess();
} else if (CheckUtil.isPhone(to)) {
//短信验证码
log.info("要发送短信验证码[{}]", code);
}
return JsonData.buildResult(BizCodeEnum.CODE_TO_ERROR);
@ApiOperation("邮件发送验证码")
@GetMapping("send_code")
public JsonData sendCode(@ApiParam(value = "接受者邮箱", required = true) String to) {
return notifyService.sendCode(SendCodeEnum.USER_REGISTER, to);
}
/**
* 获取缓存的key
*/

41
nla-user-service/src/main/java/cn/nla/user/controller/UserController.java

@ -1,21 +1,48 @@
package cn.nla.user.controller;
import cn.nla.common.util.JsonData;
import cn.nla.user.model.request.UserLoginRequest;
import cn.nla.user.model.request.UserRegisterRequest;
import cn.nla.user.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* <p>
* 电商-用户表 前端控制器
* </p>
*
* @author YJs
* @since 2024-07-29
*/
@Api(tags = "用户中心控制器")
@RestController
@RequestMapping("/userDO")
@RequestMapping("/user/center/v1")
public class UserController {
@Resource
private UserService userService;
@ApiOperation("用户注册")
@PostMapping("register")
public JsonData register(@ApiParam("用户注册对象") @RequestBody UserRegisterRequest registerRequest) {
return userService.register(registerRequest);
}
@ApiOperation("用户登录")
@PostMapping("login")
public JsonData login(@ApiParam("用户登录对象") @RequestBody UserLoginRequest userLoginRequest){
return userService.login(userLoginRequest);
}
/**
* 用户个人信息查询
*/
@ApiOperation("个人信息查询")
@GetMapping("detail")
public JsonData detail(){
return JsonData.buildSuccess(userService.findUserDetail());
}
}

4
nla-user-service/src/main/java/cn/nla/user/mapper/AddressMapper.java

@ -1,6 +1,6 @@
package cn.nla.user.mapper;
import cn.nla.user.model.AddressDO;
import cn.nla.user.model.entity.AddressEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
@ -11,6 +11,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* @author YJs
* @since 2024-07-29
*/
public interface AddressMapper extends BaseMapper<AddressDO> {
public interface AddressMapper extends BaseMapper<AddressEntity> {
}

4
nla-user-service/src/main/java/cn/nla/user/mapper/UserMapper.java

@ -1,6 +1,6 @@
package cn.nla.user.mapper;
import cn.nla.user.model.UserDO;
import cn.nla.user.model.entity.UserEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
@ -11,6 +11,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* @author YJs
* @since 2024-07-29
*/
public interface UserMapper extends BaseMapper<UserDO> {
public interface UserMapper extends BaseMapper<UserEntity> {
}

6
nla-user-service/src/main/java/cn/nla/user/model/StudentBean.java → nla-user-service/src/main/java/cn/nla/user/model/DO/StudentDO.java

@ -1,4 +1,4 @@
package cn.nla.user.model;
package cn.nla.user.model.DO;
import cn.nla.common.annotation.EncryptId;
import cn.nla.user.goup.Save;
@ -10,7 +10,7 @@ import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.List;
@Data
public class StudentBean implements Serializable {
public class StudentDO implements Serializable {
@NotBlank(message = "用户名不能为空")
private String name;
@NotNull(groups = {Save.class, Update.class})
@ -26,7 +26,7 @@ public class StudentBean implements Serializable {
@Valid
@NotNull(message = "任课老师不能为空")
@Size(min = 1, message = "至少有一个老师")
private List<TeacherBean> teacherBeans;
private List<TeacherDO> teacherDOS;
@EncryptId(message = "密码格式错误")
private String password;
}

5
nla-user-service/src/main/java/cn/nla/user/model/TeacherBean.java → nla-user-service/src/main/java/cn/nla/user/model/DO/TeacherDO.java

@ -1,10 +1,11 @@
package cn.nla.user.model;
package cn.nla.user.model.DO;
import lombok.Data;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
@Data
public class TeacherBean {
public class TeacherDO {
@NotEmpty(message = "老师姓名不能为空")
private String teacherName;
@Min(value = 1, message = "学科类型从1开始计算")

48
nla-user-service/src/main/java/cn/nla/user/model/VO/AddressVO.java

@ -0,0 +1,48 @@
package cn.nla.user.model.VO;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 收货地址返回对象
*/
@Data
public class AddressVO {
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 是否默认收货地址0->1->
*/
@JsonProperty("default_status")
private Integer defaultStatus;
/**
* 收发货人姓名
*/
@JsonProperty("receive_name")
private String receiveName;
/**
* 收货人电话
*/
private String phone;
/**
* /直辖市
*/
private String province;
/**
*
*/
private String city;
/**
*
*/
private String region;
/**
* 详细地址
*/
@JsonProperty("detail_address")
private String detailAddress;
}

38
nla-user-service/src/main/java/cn/nla/user/model/VO/UserVO.java

@ -0,0 +1,38 @@
package cn.nla.user.model.VO;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 用户响应对象
*/
@Data
public class UserVO {
private Long id;
/**
* 昵称
*/
private String name;
/**
* 头像
*/
@JsonProperty("head_img")
private String headImg;
/**
* 用户签名
*/
private String slogan;
/**
* 0表示女1表示男
*/
private Integer sex;
/**
* 积分
*/
private Integer points;
/**
* 邮箱
*/
private String mail;
}

17
nla-user-service/src/main/java/cn/nla/user/model/AddressDO.java → nla-user-service/src/main/java/cn/nla/user/model/entity/AddressEntity.java

@ -1,4 +1,4 @@
package cn.nla.user.model;
package cn.nla.user.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
@ -23,54 +23,41 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("address")
public class AddressDO implements Serializable {
public class AddressEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 是否默认收货地址0-1-
*/
private Integer defaultStatus;
/**
* 收发货人姓名
*/
private String receiveName;
/**
* 收货人电话
*/
private String phone;
/**
* /直辖市
*/
private String province;
/**
*
*/
private String city;
/**
*
*/
private String region;
/**
* 详细地址
*/
private String detailAddress;
private Date createTime;
}

4
nla-user-service/src/main/java/cn/nla/user/model/UserDO.java → nla-user-service/src/main/java/cn/nla/user/model/entity/UserEntity.java

@ -1,4 +1,4 @@
package cn.nla.user.model;
package cn.nla.user.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
@ -23,7 +23,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("user")
public class UserDO implements Serializable {
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;

52
nla-user-service/src/main/java/cn/nla/user/model/request/AddressAddRequest.java

@ -0,0 +1,52 @@
package cn.nla.user.model.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "地址对象", description = "新增收货地址对象")
public class AddressAddRequest {
/**
* 是否默认收货地址0->1->
*/
@ApiModelProperty(value = "是否是否默认收货地址,0->否;1->是", example = "0")
@JsonProperty("default_status")
private Integer defaultStatus;
/**
* 收发货人姓名
*/
@ApiModelProperty(value = "收发货人姓名", example = "yuan-paas")
@JsonProperty("receive_name")
private String receiveName;
/**
* 收货人电话
*/
@ApiModelProperty(value = "收货人电话", example = "11111111111")
private String phone;
/**
* /直辖市
*/
@ApiModelProperty(value = "省/直辖市", example = "四川省")
private String province;
/**
*
*/
@ApiModelProperty(value = "城市", example = "成都市")
private String city;
/**
*
*/
@ApiModelProperty(value = "区", example = "武侯区")
private String region;
/**
* 详细地址
*/
@ApiModelProperty(value = "详细地址", example = "天府新区18号")
@JsonProperty("detail_address")
private String detailAddress;
}

16
nla-user-service/src/main/java/cn/nla/user/model/request/UserLoginRequest.java

@ -0,0 +1,16 @@
package cn.nla.user.model.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "登录对象", description = "用户登录请求对象")
public class UserLoginRequest {
@ApiModelProperty(value = "邮箱", example = "794666918@qq.com")
private String mail;
@ApiModelProperty(value = "密码", example = "123456")
private String pwd;
}

27
nla-user-service/src/main/java/cn/nla/user/model/request/UserRegisterRequest.java

@ -0,0 +1,27 @@
package cn.nla.user.model.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "用户注册对象", description = "用户注册请求对象")
@Data
public class UserRegisterRequest {
@ApiModelProperty(value = "昵称", example = "Anna小姐姐")
private String name;
@ApiModelProperty(value = "密码", example = "12345")
private String pwd;
@ApiModelProperty(value = "头像", example = "xx")
@JsonProperty("head_img")
private String headImg;
@ApiModelProperty(value = "用户个人性签名", example = "人生需要动态规划,学习需要贪心算法")
private String slogan;
@ApiModelProperty(value = "0表示女,1表示男", example = "1")
private Integer sex;
@ApiModelProperty(value = "邮箱", example = "794666918@qq.com")
private String mail;
@ApiModelProperty(value = "验证码", example = "232343")
private String code;
}

24
nla-user-service/src/main/java/cn/nla/user/service/AddressService.java

@ -1,7 +1,13 @@
package cn.nla.user.service;
import cn.nla.user.model.AddressDO;
import cn.nla.user.model.VO.AddressVO;
import cn.nla.user.model.entity.AddressEntity;
import cn.nla.user.model.request.AddressAddRequest;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
@ -11,6 +17,20 @@ import com.baomidou.mybatisplus.extension.service.IService;
* @author YJs
* @since 2024-07-29
*/
public interface AddressService extends IService<AddressDO> {
@Service
public interface AddressService extends IService<AddressEntity> {
AddressEntity detail(Long id);
void add(AddressAddRequest addressAddRequest);
/**
* 根据id删除地址
*/
int del(int addressId);
/**
* 查找用全部收货地址
*/
List<AddressVO> listUserAllAddress();
}

21
nla-user-service/src/main/java/cn/nla/user/service/NotifyService.java

@ -0,0 +1,21 @@
package cn.nla.user.service;
import cn.nla.common.enums.SendCodeEnum;
import cn.nla.common.util.JsonData;
public interface NotifyService {
/**
* 邮件发送验证码
*/
JsonData sendCode(SendCodeEnum sendCodeEnum, String to);
/**
* 判断验证码是否一样
* @param sendCodeEnum 验证码类型
* @param to 接收者
* @param code 验证码
*/
boolean checkCode(SendCodeEnum sendCodeEnum, String to, String code);
}

14
nla-user-service/src/main/java/cn/nla/user/service/UserService.java

@ -1,7 +1,11 @@
package cn.nla.user.service;
import cn.nla.user.model.UserDO;
import cn.nla.common.util.JsonData;
import cn.nla.user.model.VO.UserVO;
import cn.nla.user.model.entity.UserEntity;
import cn.nla.user.model.request.UserLoginRequest;
import com.baomidou.mybatisplus.extension.service.IService;
import cn.nla.user.model.request.UserRegisterRequest;
/**
* <p>
@ -11,6 +15,12 @@ import com.baomidou.mybatisplus.extension.service.IService;
* @author YJs
* @since 2024-07-29
*/
public interface UserService extends IService<UserDO> {
public interface UserService extends IService<UserEntity> {
JsonData register(UserRegisterRequest registerRequest);
JsonData login(UserLoginRequest loginRequest);
UserVO findUserDetail();
}

67
nla-user-service/src/main/java/cn/nla/user/service/impl/AddressServiceImpl.java

@ -1,10 +1,25 @@
package cn.nla.user.service.impl;
import cn.nla.user.model.AddressDO;
import cn.nla.common.enums.AddressStatusEnum;
import cn.nla.common.interceptor.LoginInterceptor;
import cn.nla.common.model.LoginUser;
import cn.nla.user.model.VO.AddressVO;
import cn.nla.user.model.entity.AddressEntity;
import cn.nla.user.mapper.AddressMapper;
import cn.nla.user.model.request.AddressAddRequest;
import cn.nla.user.service.AddressService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
@ -14,7 +29,55 @@ import org.springframework.stereotype.Service;
* @author YJs
* @since 2024-07-29
*/
@Slf4j
@Service
public class AddressServiceImpl extends ServiceImpl<AddressMapper, AddressDO> implements AddressService {
public class AddressServiceImpl extends ServiceImpl<AddressMapper, AddressEntity> implements AddressService {
@Override
public AddressEntity detail(Long id) {
//new QueryWrapper<AddressEntity>().eq("id", id)
return baseMapper.selectOne(Wrappers.<AddressEntity>lambdaQuery()
.eq(AddressEntity::getId, id));
}
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
@Override
public void add(AddressAddRequest addressAddRequest) {
LoginUser loginUser = LoginInterceptor.threadLocal.get();
AddressEntity address = new AddressEntity();
address.setCreateTime(new Date());
address.setUserId(loginUser.getId());
BeanUtils.copyProperties(addressAddRequest, address);
//是否有默认收货地址
if (address.getDefaultStatus() == AddressStatusEnum.DEFAULT_STATUS.getStatus()) {
//查找数据库是否有默认地址
AddressEntity defaultAddressDO = baseMapper.selectOne(
Wrappers.<AddressEntity>lambdaQuery()
.eq(AddressEntity::getId, loginUser.getId())
.eq(AddressEntity::getDefaultStatus, AddressStatusEnum.DEFAULT_STATUS.getStatus()));
if (defaultAddressDO != null) {
//修改为非默认收货地址
defaultAddressDO.setDefaultStatus(AddressStatusEnum.COMMON_STATUS.getStatus());
baseMapper.update(defaultAddressDO, Wrappers.<AddressEntity>lambdaQuery()
.eq(AddressEntity::getId, defaultAddressDO.getId()));
}
}
int rows = baseMapper.insert(address);
log.info("新增收货地址:rows={},data={}", rows, address);
}
@Override
public int del(int addressId) {
return baseMapper.delete(Wrappers.<AddressEntity>lambdaQuery().eq(AddressEntity::getId, addressId));
}
@Override
public List<AddressVO> listUserAllAddress() {
LoginUser loginUser = LoginInterceptor.threadLocal.get();
List<AddressEntity> list = baseMapper.selectList(Wrappers.<AddressEntity>lambdaQuery().eq(AddressEntity::getUserId, loginUser.getId()));
return list.stream().map(obj -> {
AddressVO addressVO = new AddressVO();
BeanUtils.copyProperties(obj, addressVO);
return addressVO;
}).collect(Collectors.toList());
}
}

75
nla-user-service/src/main/java/cn/nla/user/service/impl/NotifyServiceImpl.java

@ -0,0 +1,75 @@
package cn.nla.user.service.impl;
import cn.nla.common.constant.CacheKey;
import cn.nla.common.enums.BizCodeEnum;
import cn.nla.common.enums.SendCodeEnum;
import cn.nla.common.util.CheckUtil;
import cn.nla.common.util.CommonUtil;
import cn.nla.common.util.JsonData;
import cn.nla.user.service.MailService;
import cn.nla.user.service.NotifyService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Service
@Slf4j
public class NotifyServiceImpl implements NotifyService {
/**
* 图形验证码有效期10分钟
*/
private static final long CAPTCHA_CODE_EXPIRED = 60 * 1000 * 10;
@Resource
private MailService mailService;
@Autowired
private StringRedisTemplate redisTemplate;
public JsonData sendCode(SendCodeEnum sendCodeEnum, String to) {
String cacheKey = String.format(CacheKey.CHECK_CODE_KEY, sendCodeEnum.name(), to);
String cacheValue = redisTemplate.opsForValue().get(cacheKey);
//如果不为空,则判断是否60秒内重复发送
if (StringUtils.isNotBlank(cacheValue)) {
long ttl = Long.parseLong(cacheValue.split("_")[1]);
//当前时间戳-验证码发送时间戳,如果小于60秒,则不给重复发送
if (System.currentTimeMillis() - ttl < 1000 * 60) {
log.info("重复发送验证码,时间间隔:{} 秒", (System.currentTimeMillis() - ttl) / 1000);
return JsonData.buildResult(BizCodeEnum.CODE_LIMITED);
}
}
//拼接验证码: 验证码+时间戳: 2322_324243232424324
String code = CommonUtil.getRandomCode(6);
String value = code + "_" + System.currentTimeMillis();
redisTemplate.opsForValue().set(cacheKey, value, CAPTCHA_CODE_EXPIRED, TimeUnit.MILLISECONDS);
if (CheckUtil.isEmail(to)) {
//邮箱验证码
mailService.sendMail(to, "电商验证码", code);
log.info("发送邮箱验证码[{}]成功!", code);
return JsonData.buildSuccess();
} else if (CheckUtil.isPhone(to)) {
//短信验证码
log.info("要发送短信验证码[{}]", code);
}
return JsonData.buildResult(BizCodeEnum.CODE_TO_ERROR);
}
public boolean checkCode(SendCodeEnum sendCodeEnum, String to, String code) {
String cacheKey = String.format(CacheKey.CHECK_CODE_KEY, sendCodeEnum.name(), to);
String cacheValue = redisTemplate.opsForValue().get(cacheKey);
if (StringUtils.isNotBlank(cacheValue)) {
String cacheCode = cacheValue.split("_")[0];
if (cacheCode.equals(code)) {
//删除验证码
redisTemplate.delete(cacheKey);
return true;
}
}
return false;
}
}

118
nla-user-service/src/main/java/cn/nla/user/service/impl/UserServiceImpl.java

@ -1,10 +1,30 @@
package cn.nla.user.service.impl;
import cn.nla.user.model.UserDO;
import cn.nla.common.enums.BizCodeEnum;
import cn.nla.common.enums.SendCodeEnum;
import cn.nla.common.interceptor.LoginInterceptor;
import cn.nla.common.model.LoginUser;
import cn.nla.common.util.CommonUtil;
import cn.nla.common.util.JWTUtil;
import cn.nla.common.util.JsonData;
import cn.nla.user.model.VO.UserVO;
import cn.nla.user.model.entity.UserEntity;
import cn.nla.user.mapper.UserMapper;
import cn.nla.user.model.request.UserLoginRequest;
import cn.nla.user.service.NotifyService;
import cn.nla.user.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import cn.nla.user.model.request.UserRegisterRequest;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* <p>
@ -15,6 +35,100 @@ import org.springframework.stereotype.Service;
* @since 2024-07-29
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements UserService {
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {
@Resource
private NotifyService notifyService;
@Resource
private UserMapper userMapper;
/**
* 用户注册<br>
* 邮箱验证码验证 <br>
* 密码加密TODO<br>
* 账号唯一性检查(TODO)<br>
* 插入数据库<br>
* 新注册用户福利发放(TODO)
*/
@Override
public JsonData register(UserRegisterRequest registerRequest) {
boolean checkCode = false;
//校验验证码
if (StringUtils.isNotBlank(registerRequest.getMail())) {
checkCode = notifyService.checkCode(SendCodeEnum.USER_REGISTER, registerRequest.getMail(), registerRequest.getCode());
}
if (!checkCode) {
return JsonData.buildResult(BizCodeEnum.CODE_ERROR);
}
UserEntity userEntity = new UserEntity();
BeanUtils.copyProperties(registerRequest, userEntity);
userEntity.setCreateTime(new Date());
userEntity.setSlogan("人生需要动态规划,学习需要贪心算法");
//设置密码 生成秘钥 盐
userEntity.setSecret("$1$" + CommonUtil.getStringNumRandom(8));
//密码+盐处理
String cryptPwd = Md5Crypt.md5Crypt(registerRequest.getPwd().getBytes(), userEntity.getSecret());
userEntity.setPwd(cryptPwd);
//账号唯一性检查 794666918@qq.com
if (checkUnique(userEntity.getMail())) {
int rows = userMapper.insert(userEntity);
log.info("rows:{},注册成功:{}", rows, userEntity);
//新用户注册成功,初始化信息,发放福利等 TODO
userRegisterInitTask(userEntity);
return JsonData.buildSuccess();
} else {
return JsonData.buildResult(BizCodeEnum.ACCOUNT_REPEAT);
}
}
@Override
public JsonData login(UserLoginRequest loginRequest) {
List<UserEntity> list = userMapper.selectList(new QueryWrapper<UserEntity>().eq("mail", loginRequest.getMail()));
if (list != null && list.size() == 1) {
UserEntity userEntity = list.get(0);
String cryptPwd = Md5Crypt.md5Crypt(loginRequest.getPwd().getBytes(), userEntity.getSecret());
if (cryptPwd.equals(userEntity.getPwd())) {
//生成token令牌
LoginUser loginUser = new LoginUser();
BeanUtils.copyProperties(userEntity, loginUser);
String accessToken = JWTUtil.geneJsonWebToken(loginUser);
return JsonData.buildSuccess(accessToken);
}
//密码错误
return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
} else {
//未注册
return JsonData.buildResult(BizCodeEnum.ACCOUNT_UNREGISTER);
}
}
@Override
public UserVO findUserDetail() {
LoginUser loginUser = LoginInterceptor.threadLocal.get();
UserEntity user = userMapper.selectOne(new QueryWrapper<UserEntity>().eq("id", loginUser.getId()));
UserVO userVO = new UserVO();
BeanUtils.copyProperties(user, userVO);
return userVO;
}
/**
* 校验用户账号唯一
*
* @param mail 邮箱地址
*/
private boolean checkUnique(String mail) {
return userMapper.selectList(
new QueryWrapper<UserEntity>().eq("mail", mail))
.size() <= 0;
}
/**
* 用户注册初始化福利信息 TODO
*
* @param userEntity 用户对象信息
*/
private void userRegisterInitTask(UserEntity userEntity) {
log.info("初始化福利信息 TODO... {}", userEntity);
}
}

2
nla-user-service/src/main/resources/mapper/AddressMapper.xml

@ -3,7 +3,7 @@
<mapper namespace="cn.nla.user.mapper.AddressMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.nla.user.model.AddressDO">
<resultMap id="BaseResultMap" type="cn.nla.user.model.entity.AddressEntity">
<id column="id" property="id" />
<result column="user_id" property="userId" />
<result column="default_status" property="defaultStatus" />

2
nla-user-service/src/main/resources/mapper/UserMapper.xml

@ -3,7 +3,7 @@
<mapper namespace="cn.nla.user.mapper.UserMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.nla.user.model.UserDO">
<resultMap id="BaseResultMap" type="cn.nla.user.model.entity.UserEntity">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="pwd" property="pwd" />

4
nla-user-service/src/test/java/AddressTest.java

@ -1,5 +1,5 @@
import cn.nla.user.UserApplication;
import cn.nla.user.model.AddressDO;
import cn.nla.user.model.entity.AddressEntity;
import cn.nla.user.service.AddressService;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONArray;
@ -20,7 +20,7 @@ public class AddressTest {
private AddressService addressService;
@Test
public void testAddressDetail() {
List<AddressDO> list = addressService.list();
List<AddressEntity> list = addressService.list();
log.info(JSONArray.toJSONString(list));
}
}

Loading…
Cancel
Save