From 56f7d4a8a59c1a69b6f83e8776ce199075c97493 Mon Sep 17 00:00:00 2001 From: bunny <1319900154@qq.com> Date: Sat, 23 Mar 2024 14:35:02 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=96=B0=E5=A2=9E):=20knife4j=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E8=AE=BF=E9=97=AE=E9=97=AE=E9=A2=98=EF=BC=8C=E5=B0=86?= =?UTF-8?q?=E6=8E=92=E5=87=BA=E9=80=89=E9=A1=B9=E6=94=BE=E5=85=A5=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=87=E4=BB=B6=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spzx-common/common-service/pom.xml | 8 +- .../atguigu/config/ResourceConfiguration.java | 15 ++++ .../atguigu/config/WebMvcConfiguration.java | 61 +++++++++++-- .../interceptor/LoginAuthInterceptor.java | 83 ++++++++++++++++++ .../atguigu/config/RedisConfiguration.class | Bin 0 -> 7362 bytes .../config/ResourceConfiguration.class | Bin 0 -> 1589 bytes spzx-common/common-util/pom.xml | 10 +-- spzx-manager/pom.xml | 12 +-- .../manger/controller/IndexController.java | 5 +- .../spzx/manger/service/SysUserService.java | 9 -- .../service/impl/SysUserServiceImpl.java | 37 +++----- .../service/impl/ValidateCodeServiceImpl.java | 2 +- .../src/main/resources/application-dev.yml | 5 ++ .../target/classes/application-dev.yml | 5 ++ .../spzx/manger/MangerApplication.class | Bin 911 -> 970 bytes .../manger/controller/IndexController.class | Bin 3398 -> 3366 bytes .../spzx/manger/service/SysUserService.class | Bin 451 -> 349 bytes .../service/impl/SysUserServiceImpl.class | Bin 4475 -> 4371 bytes .../impl/ValidateCodeServiceImpl.class | Bin 2578 -> 2589 bytes spzx-model/pom.xml | 2 +- .../spzx/model/entity/base/BaseEntity.java | 6 +- .../spzx/model/vo/result/ResultCodeEnum.java | 2 +- .../spzx/model/entity/base/BaseEntity.class | Bin 3650 -> 3518 bytes .../system/SysUser$SysUserBuilder.class | Bin 0 -> 2529 bytes .../spzx/model/entity/system/SysUser.class | Bin 4902 -> 5505 bytes .../spzx/model/vo/result/ResultCodeEnum.class | Bin 2360 -> 2366 bytes 26 files changed, 201 insertions(+), 61 deletions(-) create mode 100644 spzx-common/common-service/src/main/java/com/atguigu/config/ResourceConfiguration.java create mode 100644 spzx-common/common-service/src/main/java/com/atguigu/interceptor/LoginAuthInterceptor.java create mode 100644 spzx-common/common-service/target/classes/com/atguigu/config/RedisConfiguration.class create mode 100644 spzx-common/common-service/target/classes/com/atguigu/config/ResourceConfiguration.class create mode 100644 spzx-model/target/classes/com/atguigu/spzx/model/entity/system/SysUser$SysUserBuilder.class diff --git a/spzx-common/common-service/pom.xml b/spzx-common/common-service/pom.xml index 2611261..9d8c274 100644 --- a/spzx-common/common-service/pom.xml +++ b/spzx-common/common-service/pom.xml @@ -11,7 +11,7 @@ jar common-service - http://maven.apache.org + https://maven.apache.org UTF-8 @@ -34,5 +34,11 @@ org.springframework.boot spring-boot-starter-data-redis + + com.atguigu + common-util + 1.0-SNAPSHOT + compile + diff --git a/spzx-common/common-service/src/main/java/com/atguigu/config/ResourceConfiguration.java b/spzx-common/common-service/src/main/java/com/atguigu/config/ResourceConfiguration.java new file mode 100644 index 0000000..d2999b0 --- /dev/null +++ b/spzx-common/common-service/src/main/java/com/atguigu/config/ResourceConfiguration.java @@ -0,0 +1,15 @@ +package com.atguigu.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; + +@Configuration +@Slf4j +public class ResourceConfiguration extends WebMvcConfiguration { + protected void addResourceHandlers(ResourceHandlerRegistry registry) { + log.info("ResourceConfiguration===>设置静态资源映射......"); + registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); + } +} diff --git a/spzx-common/common-service/src/main/java/com/atguigu/config/WebMvcConfiguration.java b/spzx-common/common-service/src/main/java/com/atguigu/config/WebMvcConfiguration.java index 1381589..27d0e12 100644 --- a/spzx-common/common-service/src/main/java/com/atguigu/config/WebMvcConfiguration.java +++ b/spzx-common/common-service/src/main/java/com/atguigu/config/WebMvcConfiguration.java @@ -1,22 +1,71 @@ package com.atguigu.config; +import com.atguigu.constant.LocalDateTimeConstant; +import com.atguigu.interceptor.LoginAuthInterceptor; +import com.atguigu.json.JacksonObjectMapper; +import com.atguigu.properties.InterceptorsProperties; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.stereotype.Component; import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; + +import java.text.SimpleDateFormat; +import java.util.List; @Component -public class WebMvcConfiguration implements WebMvcConfigurer { +@Slf4j +public class WebMvcConfiguration extends WebMvcConfigurationSupport { + @Autowired + private LoginAuthInterceptor loginAuthInterceptor; + @Autowired + private InterceptorsProperties interceptorsProperties; + /** * * 解决跨域 * * @param registry 跨域注册表 */ - @Override - public void addCorsMappings(CorsRegistry registry) { + protected void addCorsMappings(CorsRegistry registry) { + log.info("开始跨域注册表..."); registry.addMapping("/**")// 添加路径规则 .allowCredentials(true)// 是否允许在跨域的情况下传递Cookie .allowedOriginPatterns("*")// 允许请求来源的域规则 - .allowedMethods("*") - .allowedHeaders("*");// 允许所有的请求头 + .allowedMethods("*").allowedHeaders("*");// 允许所有的请求头 + } + + /** + * 注册自定义拦截器 + * + * @param registry InterceptorRegistry + */ + protected void addInterceptors(InterceptorRegistry registry) { + log.info("开始注册自定义拦截器..."); + // 需要拦截的 + String[] addPathPatters = {"/admin/**"}; + registry.addInterceptor(loginAuthInterceptor).addPathPatterns(addPathPatters) + .excludePathPatterns(interceptorsProperties.getNoAuthUrls()); + System.out.println(interceptorsProperties.getNoAuthUrls()); + } + + /** + * 扩展Spring MVC框架的消息转化器 + * + * @param converters 转换器 + */ + public void extendMessageConverters(List> converters) { + log.info("扩展消息转换器..."); + // 创建一个消息转换器对象 + MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + // 需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据 + converter.setObjectMapper(new JacksonObjectMapper()); + // 添加条件判断,只应用于特定的请求路径 + converter.getObjectMapper().setDateFormat(new SimpleDateFormat(LocalDateTimeConstant.DEFAULT_DATE_TIME_SECOND_FORMAT)); + + // 将自己的消息转化器加入容器中 + converters.add(converter); } } \ No newline at end of file diff --git a/spzx-common/common-service/src/main/java/com/atguigu/interceptor/LoginAuthInterceptor.java b/spzx-common/common-service/src/main/java/com/atguigu/interceptor/LoginAuthInterceptor.java new file mode 100644 index 0000000..1cb2fe2 --- /dev/null +++ b/spzx-common/common-service/src/main/java/com/atguigu/interceptor/LoginAuthInterceptor.java @@ -0,0 +1,83 @@ +package com.atguigu.interceptor; + +import com.alibaba.fastjson.JSON; +import com.atguigu.context.BaseContext; +import com.atguigu.spzx.model.entity.system.SysUser; +import com.atguigu.spzx.model.vo.result.Result; +import com.atguigu.spzx.model.vo.result.ResultCodeEnum; +import com.atguigu.utils.InterceptorUtil; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.concurrent.TimeUnit; + +@Configuration +@Slf4j +public class LoginAuthInterceptor implements HandlerInterceptor { + @Autowired + RedisTemplate redisTemplate; + + @Override + public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception { + String method = request.getMethod(); + String token = request.getHeader("token"); + + // 判断当前拦截到的是Controller方法还是其它资源 + if ("OPTIONS".equals(method) || !(handler instanceof HandlerMethod)) return true; + + // 当前token为空 + if (StringUtils.isEmpty(token)) { + InterceptorUtil.unLoginInterceptor(response); + return false; + } + + // 获取用户信息不存在 + String userinfoString = (String) redisTemplate.opsForValue().get(token); + if (StringUtils.isEmpty(userinfoString)) { + InterceptorUtil.unLoginInterceptor(response); + return false; + } + + // 将用户信息放到ThreadLocal中 + SysUser sysUser = JSON.parseObject(userinfoString, SysUser.class); + BaseContext.setSysUser(sysUser); + + // 更新Redis过期时间 + redisTemplate.expire(token, 7, TimeUnit.DAYS); + + // 放行 + return true; + } + + /** + * 请求完成后删除ThreadLocal + */ + @Override + public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, @Nullable Exception ex) throws Exception { + log.info("删除ThreadLocal..."); + BaseContext.removeSysUser(); + } + + // 响应208状态码给前端 + private void responseNoLoginInfo(HttpServletResponse response) { + Result result = Result.error(ResultCodeEnum.LOGIN_AUTH); + response.setCharacterEncoding("UTF-8"); + response.setContentType("text/html; charset=utf-8"); + try (PrintWriter writer = response.getWriter()) { + writer.print(JSON.toJSONString(result)); + } catch (IOException e) { + log.error("出错了===>{}", e.getMessage()); + } + } +} diff --git a/spzx-common/common-service/target/classes/com/atguigu/config/RedisConfiguration.class b/spzx-common/common-service/target/classes/com/atguigu/config/RedisConfiguration.class new file mode 100644 index 0000000000000000000000000000000000000000..0fd0c6edd33f4b72630fd47a2850427606f9aaa3 GIT binary patch literal 7362 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 CrGa<= literal 0 HcmV?d00001 diff --git a/spzx-common/common-service/target/classes/com/atguigu/config/ResourceConfiguration.class b/spzx-common/common-service/target/classes/com/atguigu/config/ResourceConfiguration.class new file mode 100644 index 0000000000000000000000000000000000000000..76c9f3f501894c8b9fc1990f31b674307f5b8fdf GIT binary patch literal 1589 zcmb_d+fEZv6kVq+&a@Q4a#8S#B9b4^ovSse!%hW30lIyySGy|MY@>&DNQFSedM z-G0Bm_2t>t^H<+rulI+)dNkpXhEx*GXklooMQ4av&Z5iEn$9hYRl#lHn0!`wmSbjn z<}|d?qgsQGBMfn#ca8ofRj?E2z)=myk~oeN47WlbD*?iyCkpbR>pkEP`FxF$A)mg#N312{_Q7o!60v@Y;e=re-(L}G zX_!ylxO=_t*7PLz%HPlD37p0m4P8l`4HBQ)uf)s3YN<*-=NjRuuj3p;eZc3k@O+-h z=;#T=`p-Zsw-e~ac@2F@^n)`Tu2sXNFq9kc9yg^b$&cY|wK66GKiQtYRZ2pdaPyL( zF=sh)x>#6{-d(X^(+O$X5cZt#tYBY0jHxBdXUOFKw?eWE%~gbyr9u$X>3#e3Yb1FF z-P_UM?R|u%LYk6l$<5ypL0Ks2QSkbRVVB!SVm53GlUBf4M@99!xspzx-model 1.0-SNAPSHOT + + + + + org.springframework.boot @@ -40,10 +45,5 @@ minio 8.5.9 - - com.atguigu - common-service - 1.0-SNAPSHOT - diff --git a/spzx-manager/pom.xml b/spzx-manager/pom.xml index d00067c..3035841 100644 --- a/spzx-manager/pom.xml +++ b/spzx-manager/pom.xml @@ -24,6 +24,12 @@ common-service 1.0-SNAPSHOT + + com.atguigu + common-util + 1.0-SNAPSHOT + compile + org.springframework.boot @@ -54,11 +60,5 @@ com.github.pagehelper pagehelper-spring-boot-starter - - com.atguigu - common-util - 1.0-SNAPSHOT - compile - diff --git a/spzx-manager/src/main/java/com/atguigu/spzx/manger/controller/IndexController.java b/spzx-manager/src/main/java/com/atguigu/spzx/manger/controller/IndexController.java index 8d68933..6183201 100644 --- a/spzx-manager/src/main/java/com/atguigu/spzx/manger/controller/IndexController.java +++ b/spzx-manager/src/main/java/com/atguigu/spzx/manger/controller/IndexController.java @@ -1,5 +1,6 @@ package com.atguigu.spzx.manger.controller; +import com.atguigu.context.BaseContext; import com.atguigu.spzx.manger.service.SysUserService; import com.atguigu.spzx.manger.service.ValidateCodeService; import com.atguigu.spzx.model.dto.system.LoginDto; @@ -37,8 +38,8 @@ public class IndexController { @Operation(summary = "获取登录用户信息", description = "获取当前登录用户信息") @GetMapping("getUserInfo") - public Result getUserInfo(@RequestHeader(name = "token") String token) { - SysUser sysUser = sysUserService.getUserInfo(token); + public Result getUserInfo() { + SysUser sysUser = BaseContext.getSysUser(); return Result.success(sysUser); } diff --git a/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/SysUserService.java b/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/SysUserService.java index 7cc553a..1df55dc 100644 --- a/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/SysUserService.java +++ b/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/SysUserService.java @@ -1,7 +1,6 @@ package com.atguigu.spzx.manger.service; import com.atguigu.spzx.model.dto.system.LoginDto; -import com.atguigu.spzx.model.entity.system.SysUser; import com.atguigu.spzx.model.vo.system.LoginVo; public interface SysUserService { @@ -13,14 +12,6 @@ public interface SysUserService { */ LoginVo login(LoginDto loginDto); - /** - * * 获取当前登录用户信息 - * - * @param token token值 - * @return 用户信息 - */ - SysUser getUserInfo(String token); - /** * * 用户退出接口 * diff --git a/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/impl/SysUserServiceImpl.java b/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/impl/SysUserServiceImpl.java index ea9ac96..bcecf18 100644 --- a/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/impl/SysUserServiceImpl.java +++ b/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/impl/SysUserServiceImpl.java @@ -1,13 +1,14 @@ package com.atguigu.spzx.manger.service.impl; +import com.alibaba.fastjson.JSON; +import com.atguigu.constant.ExceptionConstant; import com.atguigu.exception.BunnyException; -import com.atguigu.exception.EnumException; +import com.atguigu.lib.MD5; import com.atguigu.spzx.manger.mapper.SysUserMapper; import com.atguigu.spzx.manger.service.SysUserService; import com.atguigu.spzx.model.dto.system.LoginDto; import com.atguigu.spzx.model.entity.system.SysUser; import com.atguigu.spzx.model.vo.system.LoginVo; -import com.atguigu.utils.MD5; import com.atguigu.utils.StringEmptyUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; @@ -40,50 +41,36 @@ public class SysUserServiceImpl implements SysUserService { String key = loginDto.getCodeKey(); // 得到Redis中验证码 String code = (String) redisTemplate.opsForValue().get(key); - stringEmptyUtil.isEmpty(userName, EnumException.USERNAME_IS_EMPTY); - stringEmptyUtil.isEmpty(password, EnumException.PASSWORD_IS_EMPTY); - stringEmptyUtil.isEmpty(captcha, EnumException.CAPTCHA_IS_EMPTY); - stringEmptyUtil.isEmpty(key, EnumException.KEY_IS_EMPTY); - stringEmptyUtil.isEmpty(code, EnumException.VERIFICATION_CODE_IS_EMPTY); + stringEmptyUtil.isEmpty(userName, ExceptionConstant.USERNAME_IS_EMPTY); + stringEmptyUtil.isEmpty(password, ExceptionConstant.PASSWORD_IS_EMPTY); + stringEmptyUtil.isEmpty(captcha, ExceptionConstant.CAPTCHA_IS_EMPTY); + stringEmptyUtil.isEmpty(key, ExceptionConstant.KEY_IS_EMPTY); + stringEmptyUtil.isEmpty(code, ExceptionConstant.VERIFICATION_CODE_IS_EMPTY); // 验证码不匹配 assert code != null; if ((!Objects.equals(code.toLowerCase(), captcha.toLowerCase()))) { - throw new BunnyException(EnumException.VERIFICATION_CODE_DOES_NOT_MATCH); + throw new BunnyException(ExceptionConstant.VERIFICATION_CODE_DOES_NOT_MATCH); } // 比较完成后删除验证码 redisTemplate.delete(key); // 根据username查询用户信息 SysUser sysUser = sysUserMapper.selectByUsername(userName); if (sysUser == null) { - throw new BunnyException(EnumException.USER_NOT_FOUND); + throw new BunnyException(ExceptionConstant.USER_NOT_FOUND); } String encryptedPassword = MD5.encrypt(password); // 比较密码 if (!encryptedPassword.equals(sysUser.getPassword())) { - throw new BunnyException(EnumException.PASSWORD_ERROR); + throw new BunnyException(ExceptionConstant.PASSWORD_ERROR); } // 登录成功 String token = UUID.randomUUID().toString().replaceAll("-", ""); - redisTemplate.opsForValue().set(token, userName, 7, TimeUnit.DAYS); + redisTemplate.opsForValue().set(token, JSON.toJSONString(sysUser), 7, TimeUnit.DAYS); // 返回loginVo对象 return LoginVo.builder().token(token).build(); } - /** - * * 获取当前登录用户信息 - * - * @param token token值 - * @return 用户信息 - */ - @Override - public SysUser getUserInfo(String token) { - String username = (String) redisTemplate.opsForValue().get(token); - SysUser sysUser = sysUserMapper.selectByUsername(username); - sysUser.setPassword("******"); - return sysUser; - } - /** * * 用户退出接口 * diff --git a/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/impl/ValidateCodeServiceImpl.java b/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/impl/ValidateCodeServiceImpl.java index d91db0d..627740f 100644 --- a/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/impl/ValidateCodeServiceImpl.java +++ b/spzx-manager/src/main/java/com/atguigu/spzx/manger/service/impl/ValidateCodeServiceImpl.java @@ -30,7 +30,7 @@ public class ValidateCodeServiceImpl implements ValidateCodeService { // 2. 验证码存储到Redis中,Redis的key为UUID,值为验证码的值 String key = UUID.randomUUID().toString(); // 3. 返回ValidateCodeVo - redisTemplate.opsForValue().set(key, code, 1, TimeUnit.MINUTES); + redisTemplate.opsForValue().set(key, code, 10, TimeUnit.MINUTES); return ValidateCodeVo.builder().codeKey(key).codeValue(base64Image).build(); } } diff --git a/spzx-manager/src/main/resources/application-dev.yml b/spzx-manager/src/main/resources/application-dev.yml index e72a30c..599866c 100644 --- a/spzx-manager/src/main/resources/application-dev.yml +++ b/spzx-manager/src/main/resources/application-dev.yml @@ -11,6 +11,11 @@ bunny: port: 6379 database: 2 + + spzx: + noAuthUrls: + - /admin/system/index/login + - /admin/system/index/generateValidateCode # jackson: # date-format: yyyy-MM-dd HH:mm:ss # time-zone: GMT+8 \ No newline at end of file diff --git a/spzx-manager/target/classes/application-dev.yml b/spzx-manager/target/classes/application-dev.yml index e72a30c..599866c 100644 --- a/spzx-manager/target/classes/application-dev.yml +++ b/spzx-manager/target/classes/application-dev.yml @@ -11,6 +11,11 @@ bunny: port: 6379 database: 2 + + spzx: + noAuthUrls: + - /admin/system/index/login + - /admin/system/index/generateValidateCode # jackson: # date-format: yyyy-MM-dd HH:mm:ss # time-zone: GMT+8 \ No newline at end of file diff --git a/spzx-manager/target/classes/com/atguigu/spzx/manger/MangerApplication.class b/spzx-manager/target/classes/com/atguigu/spzx/manger/MangerApplication.class index 073831e62c2b2a8891b773db5d7f088f600eb348..9ecda2a89eb666d35b9bd91f3d13b1df08a4f5a8 100644 GIT binary patch delta 109 zcmeBYKgG^<>ff$?3=9mm3`!fhteF^1CSDX%Oia#5)lbaJ%P&bR$;{8wcg;&o%1Lzw z3TNh}TQf4)OuQ&MIhtt=BkyDmW_wnC26hI4$v(_F(ozg83^G8|WPw-?h~*g=85E)! I7>gMc0UO8~WB>pF delta 68 zcmX@b-p|f;>ff$?3=9mm42m1MteF^XCSDYsJc(%yBll!`W_wm%26hI%$<53<;$jTU W3^G84vOp}yz{nsU&A?d9pa1}DG!3x; diff --git a/spzx-manager/target/classes/com/atguigu/spzx/manger/controller/IndexController.class b/spzx-manager/target/classes/com/atguigu/spzx/manger/controller/IndexController.class index 4452344e4078b041b608747ab1f3742ad338dd8e..f4806d79656abfc2a3f39a0f9479cd5cca42b277 100644 GIT binary patch delta 832 zcmZ8fO-~b16g_X+(#~{JFeDl(#x{V~8D-k~fe2MT6sb}b0l%ukh+}m@n=mEORoAZH z#$VvlKqRrc(47nZjeo#!-gE*@7c=kPdFR}7?!EIj{WWbI{QvbEKnZX5j6d3pfl-Xb zan8hfCCylH{Xc`jGEV6`Q)$p-nKwKCwIk=9Eha* zEE6^^%6w$Z7&mbWj)1Lht?!>BcGOIgra0yLyN2vfl(cG2ZX~{llB^`A<-d4FPU_=g zLJA`vU-aC!-u9IA^yOHz?rwQj%VM zK)KAfDgX@P3g4;#0l125JOxgW6hToQ7@2j2H7ElN^E?yaPX>8^h&RZbz;*H_iPCT* zFf+_(iqEvq3E%W_3o}H_Rv~=W7sz6cyrL{8v#n!|5w_ZlB?GlP zth~VcnBZrG!gqUx7nN`s_l|_KxKDIk4P=RdKt*-hf|}DTQ`M&4#>kT0#^5d!4aeRr zM7dZsuTKAZ=q*Y|5AcxmPXCX3Z7eGrkGuM>5Nl(F^_1{Ji!w?%W$k0g{)r13+PKs! zU*PzQUGk};(WJ17HI@tqvdU8Gcj(%{6XoD(mxE`)AWSug=O}P5K5J-rL7IkYKtIg| SyyX2WAFr{_iw!27{keziDrr;z delta 869 zcmZ{hO-~b17=_QB&M@uFSicekN{kh%^aB|DLInkjd|E(JL_};z9F2?CgmL4lKf%TQ z4<;HHHkt@7bYon&@}IbLXFT_I($*#{X5M?}zVA8DocpHlN1yZa@0YItuAy9az8NVO zCo$+DgEIo|v*6`=80;=qpS}<%%6IXC{9|`Js%OYU7CBjrWx5I;PGI2DKZ9lmX>^uo}Cj`vuP9>0L!k5*=s{EdK zUmGD+7X(IG4Y=^QZvSR+Z|M%79i!X{Rx9@zqOM2A_*MeIF`VOD39td@ae-CfD25S( z8lLCQU_G4s1bZKc1WI}N+ews_grkpAto>T1yU`lSI262yOB5JquYt>&v7f6ee6EI= zz+}jDud`!n3nHYgKpNAW^W}z{uC+W)^DhUq$0>pVMOmMlR{%{fP1byLZR^Q?hA8PA&4xOUq|uaGLl~WMYDZTxwoPW=W-f zab!l2GVn0)GB7f*0}W+mWZ(u; Mj0}80l8J#I04~EEp#T5? diff --git a/spzx-manager/target/classes/com/atguigu/spzx/manger/service/impl/SysUserServiceImpl.class b/spzx-manager/target/classes/com/atguigu/spzx/manger/service/impl/SysUserServiceImpl.class index bc70e3d8ba1dbc62b4433826f8bb3f35d2540840..dcccba822752b9c049e1c5672fbfe4a4813c1a93 100644 GIT binary patch delta 903 zcmZWnTSyd982)DVGP~2bnbmp;dyrDg%LZ#0m1UVE28s#_h0-c18?{@xLT}bfH!HJ~ znReNv`9!ag6Q?sdR+CM#=zP}zt2@%QCcEF3;18YZ&M7#r;Q}s-4|cctvV?3=W=Rm$6KtWyYMU%R zYI{~)f|+B44mA+mDs<1V8bHUHU?FpZvm!yg(SADe)sD4^ZU9E(w9K)j4`y01oS z0#1a9HTuDbYZ&A%VF<&lI6y)Nvs9WSk>q&SoTv<9+Z62X$KD|vurm5kqCJdbVVu-u znxGf1K|I$~mP=!5I$|-4G#Oko;bu#D$VL%dsK6Y?y0H;C*owJm!928MKDx1h16#;O z7ExS2?qLbWuncd|T!=4NZYZvgsER74K3vBQqst$-i4m$-@fEj-Ocd}Lw~5S@@dBdPNxs*F)Aa2 z;-F=|fI52s&Wtdssv-xbPee65Wh_^2h<8RJ|A?nwCzB8@-NO_coh)z6*{WtbOy?g)w delta 1050 zcmZXSTTB#Z6vuzx>}6($DdCQ-7?lFjg_T5%q$NbGw`yWrsq#QAgu+TTfkoZj=-ak0 zOT zx7-|mJa!dm;;$hyqgA}z)!$dw8ShC%dJ=Wv9bMrq@koEPZe=vlxALi%y05+EDJY&9 znTSVvW2rU%R<+N_$^C>+b#_{O#xBJidzmrEUSfp&do1=cU`LFWT$}wm2P_V9NKtL8 zK(#$-tj!(dh|W=qV;omB2;5+Q5NInL15T0$tk70WN@cXDdHNBeWwOU#y=A@_cGW_;c(UT3-B zKFRU9RZ`;BiKiSiIEu=qjfm@zKrxr81S=asno$82-;)sz$<|B>GzI(5UYh%NGE~Gz z!+e}!w_jrRy%-rQD*K32EvcE0`p?O60=ktfDEkqKz?r5Y;{&@grA6 zxyeJWiscaj54a|lS7iLdb+LRR<}NqH@(bN2ZVHJmwN~?!V1`i5m(93BfS-k{2Jio( zQr9Wfv8(dtC4Ujrr-afO)UR}B2gMFKooB2Fj!=@OtR_RbCWO`N1bDYLLx;wjp@P$C z&W5s&>&&ab%~?-AEtJVr%Guzy7|hn1Zn46Zq$IAYkl#d|CgFyw-NTfkW3Hm#X>}CY zZF#ek4udJ4^DY58+{z`cZ%$V>rz+1VVlY0vJ&WDVfc%2eH0O_?d(Y$bq-cJ2lZxDN e`OvIpC3F8nNat$Yo?g%i0q(eZ6oc6ON#F_Dx6s7^ diff --git a/spzx-manager/target/classes/com/atguigu/spzx/manger/service/impl/ValidateCodeServiceImpl.class b/spzx-manager/target/classes/com/atguigu/spzx/manger/service/impl/ValidateCodeServiceImpl.class index 9f9270620958c9fd45d155e5254339ed8b110dfd..06ef4fa83f09af9c516d793092472a2328a8e551 100644 GIT binary patch delta 486 zcmX|-$xd4_6ox3L=B@BvCL#0R{ArONC4UjTJ3G+M;rDblJp{-bS)4o7gSYm4uJn;tW7 zpG6Y%dGynxa98$L*QS=X57q)C81xuo*i<-eYV>@^c~C*w{={d^y2mRv%%Z+iTc+6G zq4vy%zs&xkh?rkGVlMo7KSxkllu#->CfCjo9v8NRowS+|6&0m~ow7^RY5I6lFqI71 zObL2V2~0C1N-@i@V9NYQ@>0Ljoy$>9m3FSs1LaAw1_ex)8!ikHJ)`=Xcm`KAhwUUC zl}UP&44jC~V$%F@Uw@BNlx|e>RP4D?CQZ!oURvc4XPys|UqB@vCGv@*m<5S!nTzRK gOE0fn7QG_NFWyyIn{1296Muphc5vBcpRa`f1FDru-T(jq delta 480 zcmX|+OHWf#6otQYdv8zg?d2H;R1!3Tfk5O{DuS&*p&;0T%KN1tl(!ZK3>-OChn~d5 z0f}>CBAOI*z`!taf~TfZ#Dh0}d~$xP(p8T&vYK_DYBtQ4K2=+$B{X2a zP~0+~L$zLgI+xqo-_zvGK`8oW424Aljlz%Q3qj$>!j`a8R8K^;ic-Q((-G>h_&gz4 zFhd!Wg8qepDW*j!X2=K@!e7Ma2&XFeSl*_cV|2PXPf13=jJuKR-gjDm5({$7y@;Ks z|8}0?Jfq(vWHDjhxizn2+$^r?ycl)4CQJ{r%*mp1V$8E3{%bU|C|y7jbu39|%XwOy g_3Y}8%c57LLXv$hwaK=qO35dQvxCbnFWDn<4uvXA2><{9 diff --git a/spzx-model/pom.xml b/spzx-model/pom.xml index 9fc4036..fef7b0b 100644 --- a/spzx-model/pom.xml +++ b/spzx-model/pom.xml @@ -1,4 +1,4 @@ - 4.0.0 diff --git a/spzx-model/src/main/java/com/atguigu/spzx/model/entity/base/BaseEntity.java b/spzx-model/src/main/java/com/atguigu/spzx/model/entity/base/BaseEntity.java index 130dee0..74d2286 100644 --- a/spzx-model/src/main/java/com/atguigu/spzx/model/entity/base/BaseEntity.java +++ b/spzx-model/src/main/java/com/atguigu/spzx/model/entity/base/BaseEntity.java @@ -1,6 +1,5 @@ package com.atguigu.spzx.model.entity.base; -import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -13,15 +12,14 @@ public class BaseEntity implements Serializable { @Schema(description = "唯一标识") private Long id; - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + // @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @Schema(description = "创建时间") private Date createTime; - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + // @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @Schema(description = "修改时间") private Date updateTime; @Schema(description = "是否删除") private Integer isDeleted; - } \ No newline at end of file diff --git a/spzx-model/src/main/java/com/atguigu/spzx/model/vo/result/ResultCodeEnum.java b/spzx-model/src/main/java/com/atguigu/spzx/model/vo/result/ResultCodeEnum.java index 33f9a56..3defdb3 100644 --- a/spzx-model/src/main/java/com/atguigu/spzx/model/vo/result/ResultCodeEnum.java +++ b/spzx-model/src/main/java/com/atguigu/spzx/model/vo/result/ResultCodeEnum.java @@ -12,7 +12,7 @@ public enum ResultCodeEnum { USE_NOT_EXIST(500, "失败"), SERVICE_ERROR(2012, "服务异常"), DATA_ERROR(204, "数据异常"), - LOGIN_AUTH(208, "未登陆"), + LOGIN_AUTH(208, "需要先登陆"), LOGIN_MOBLE_ERROR(208, "登录验证失败"), ACCOUNT_DEACTIVATION(208, "账户停用"), PERMISSION(209, "没有权限"); diff --git a/spzx-model/target/classes/com/atguigu/spzx/model/entity/base/BaseEntity.class b/spzx-model/target/classes/com/atguigu/spzx/model/entity/base/BaseEntity.class index aa4998f6fb3de0e4dae50bb577a2a7c6ddf92fde..23bdb8cc47650006befd56a96d0a715981a72fd9 100644 GIT binary patch delta 1139 zcma)*$!-%t5Qe`Qd&WCpk&J;LBbE?hgjmD@vYJ3b0&&<^vxkHwKumZ5iyIOW5}E@i z4!l7eKu8>N0K|a@Ktkdb5Ih0mpBc*-dk`GDySl6Xzy7N3ez$h1EBWc?+a+Lt`C9V3 z`EoomXD*vgGQ*7+H`DCqmiy8AV9dIY?UHfN{bCoQ6@$F{)y})!vA${wgS{HP59r5a zB`dVqBgQ7jfE*6FcE=zY9a`9$hlJU#)zE4c-eA;Zm=ra8Zb-0Cb23ThX1N=x#Q9sojOR(^Hh#pvYCBu?HAY zF+=XRc&`6G+yA(B;=zPQGuev!Y(WVxv)u zOi)s9I(g2dUX#fto^V8G5nb#fj>?LvbF&x%0PDo*tHFbqQQqEtl(rPHQq{~xSCz$k0+`&%&-3+H6mWwK= z`E!g(5>)C05$%Pq zAuo`S_yZQCfRI>3Vpy?9d;lN7k{#ka+e$((B2xU$eeVwE+;?B4=i|1}mtXHI0ETd< z9Qq+oN2k(xBetZQrN!bsBO6=M)2n7a7t?dOd`T}Y6Hd||&le57l#mc8=q0-5B(&e> zFPch4Gnt*qWZW>~ruq7(ye7Ba4q+K90jxIT5VF=?<+GHt5^73XvmU7tzbT>DdaU+Z zU)98V2V@+Dgdr2haD*Uk;yCx(v6;qUGWGHpriX?u*CWi;4LyMt8VXc?M;ILADsfdJ z?;w>4WSrzz90MVYu5)R2JTQiFS|o=Z{QepJ27y;RtdDNRs7LUAL_C698iU*1;7*%d zwRF^pwzdSd{u)osv(jGd6P2v#ptfG~?e_GYK$6^rq&QcZs~Q=2i-1Q*c&0fXE-TTk zu-&9nJX0hZ;%X*w8a_9r^*z{@s&QanJ+o}G1Kljb5Z5a%uQ~t{rku3aU{hC}s()p4 zro_!C43CT{OnYhX_^K+L34{}wuW8k5jm}IO`rZ^S)e3fquRX<%wU!xJMjW@ z95ESt@C5VR^YOMH;tY`=6IjJrA_XZd;vA8REWOVY1yIB=E)WIr6n(fz)P!f`a0#=1 zj`3w{dpNP=GMphpKejpy$wa&iapTIs2LxXd)DLleW0fjpg+v8qH{+bG`2YsFHDXo5 z4;C8lI!TT|!A;bAH)qJg*v*R6RDK)yty2> oiL_m7zNLSxv6k~(wQ8-5EoqVY!Tw0N#lL|(tq@Uxy(^*nH|Fe)6aWAK diff --git a/spzx-model/target/classes/com/atguigu/spzx/model/entity/system/SysUser$SysUserBuilder.class b/spzx-model/target/classes/com/atguigu/spzx/model/entity/system/SysUser$SysUserBuilder.class new file mode 100644 index 0000000000000000000000000000000000000000..545c713c52f1c2e4f665c34033c0356f5ed7cc64 GIT binary patch literal 2529 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