feat: 添加代码格式化

This commit is contained in:
lirui
2025-11-25 13:53:29 +08:00
parent 4304ec6e29
commit d89960f51c
72 changed files with 1403 additions and 1311 deletions

BIN
.idea/.cache/.easy-yapi/.api.cache.v1.1.db generated Normal file

Binary file not shown.

View File

View File

6
.idea/CoolRequestSetting.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CoolRequestSetting">
<option name="projectCachePath" value="project-e82c3cb9-7dfc-4fa6-b498-45789b6b3803" />
</component>
</project>

2
.idea/misc.xml generated
View File

@@ -15,7 +15,7 @@
</set> </set>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="zulu-17" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>

View File

@@ -7,7 +7,9 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients(basePackages = "cn.meowrain.aioj.backend.auth.clients") @EnableFeignClients(basePackages = "cn.meowrain.aioj.backend.auth.clients")
@SpringBootApplication @SpringBootApplication
public class AIOJAuthApplication { public class AIOJAuthApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(AIOJAuthApplication.class, args); SpringApplication.run(AIOJAuthApplication.class, args);
} }
} }

View File

@@ -8,9 +8,11 @@ import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "user-service", path = "/api/v1/user") @FeignClient(name = "user-service", path = "/api/v1/user")
public interface UserClient { public interface UserClient {
@GetMapping("/inner/get-by-username") @GetMapping("/inner/get-by-username")
Result<UserAuthRespDTO> getUserByUserName(@RequestParam("userAccount") String userAccount); Result<UserAuthRespDTO> getUserByUserName(@RequestParam("userAccount") String userAccount);
@GetMapping("/inner/get-by-userid") @GetMapping("/inner/get-by-userid")
public Result<UserAuthRespDTO> getUserById(@RequestParam("userId") String userid); public Result<UserAuthRespDTO> getUserById(@RequestParam("userId") String userid);
} }

View File

@@ -1,5 +1,7 @@
package cn.meowrain.aioj.backend.auth.common.constants; package cn.meowrain.aioj.backend.auth.common.constants;
public class RedisKeyConstants { public class RedisKeyConstants {
public static String REFRESH_TOKEN_KEY_PREFIX = "refresh_token:%s"; public static String REFRESH_TOKEN_KEY_PREFIX = "refresh_token:%s";
} }

View File

@@ -5,6 +5,7 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor
public enum ChainMarkEnums { public enum ChainMarkEnums {
/** /**
* 用户登录请求验证 * 用户登录请求验证
*/ */
@@ -17,4 +18,5 @@ public enum ChainMarkEnums {
public String toString() { public String toString() {
return markName; return markName;
} }
} }

View File

@@ -17,21 +17,14 @@ public class SecurityConfiguration {
@Bean @Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http http.csrf(csrf -> csrf.disable())
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth .authorizeHttpRequests(auth -> auth
.requestMatchers( .requestMatchers("/v1/auth/**", "/doc.html", "/swagger-ui/**", "/swagger-resources/**", "/webjars/**",
"/v1/auth/**", "/v3/api-docs/**", "/favicon.ico")
"/doc.html",
"/swagger-ui/**",
"/swagger-resources/**",
"/webjars/**",
"/v3/api-docs/**",
"/favicon.ico"
)
.permitAll() .permitAll()
.anyRequest().authenticated()); .anyRequest()
.authenticated());
return http.build(); return http.build();
} }
@@ -44,4 +37,5 @@ public class SecurityConfiguration {
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception { public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager(); return configuration.getAuthenticationManager();
} }
} }

View File

@@ -16,23 +16,25 @@ import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
@EnableKnife4j @EnableKnife4j
public class SwaggerConfiguration implements ApplicationRunner { public class SwaggerConfiguration implements ApplicationRunner {
@Value("${server.port:8080}") @Value("${server.port:8080}")
private String serverPort; private String serverPort;
@Value("${server.servlet.context-path:}") @Value("${server.servlet.context-path:}")
private String contextPath; private String contextPath;
@Bean @Bean
public OpenAPI customerOpenAPI() { public OpenAPI customerOpenAPI() {
return new OpenAPI() return new OpenAPI().info(new Info().title("AIOJ-renz微服务✨")
.info(new Info()
.title("AIOJ-renz微服务✨")
.description("用户认证功能") .description("用户认证功能")
.version("v1.0.0") .version("v1.0.0")
.contact(new Contact().name("meowrain").email("meowrain@126.com")) .contact(new Contact().name("meowrain").email("meowrain@126.com"))
.license(new License().name("MeowRain").url("https://meowrain.cn"))); .license(new License().name("MeowRain").url("https://meowrain.cn")));
} }
@Override @Override
public void run(ApplicationArguments args) throws Exception { public void run(ApplicationArguments args) throws Exception {
log.info("✨API Document: http://127.0.0.1:{}{}/doc.html", serverPort, contextPath); log.info("✨API Document: http://127.0.0.1:{}{}/doc.html", serverPort, contextPath);
} }
} }

View File

@@ -8,7 +8,9 @@ import org.springframework.stereotype.Component;
@Data @Data
@ConfigurationProperties(value = JwtPropertiesConfiguration.PREFIX) @ConfigurationProperties(value = JwtPropertiesConfiguration.PREFIX)
public class JwtPropertiesConfiguration { public class JwtPropertiesConfiguration {
public static final String PREFIX = "jwt"; public static final String PREFIX = "jwt";
/** /**
* JWT 密钥(必须 32 字节以上) * JWT 密钥(必须 32 字节以上)
*/ */
@@ -18,8 +20,10 @@ public class JwtPropertiesConfiguration {
* 过期时间(单位:毫秒) * 过期时间(单位:毫秒)
*/ */
private long accessExpire; // access token TTL private long accessExpire; // access token TTL
/** /**
* 刷新令牌时间 * 刷新令牌时间
*/ */
private long refreshExpire; // refresh token TTL private long refreshExpire; // refresh token TTL
} }

View File

@@ -33,5 +33,4 @@ public class AuthController {
return Results.success(userLoginResponseDTO.getAccessToken()); return Results.success(userLoginResponseDTO.getAccessToken());
} }
} }

View File

@@ -12,6 +12,7 @@ import org.springframework.stereotype.Component;
@Component @Component
@Slf4j @Slf4j
public class UserLoginRequestParamVerifyChain implements AbstractChianHandler<UserLoginRequestDTO> { public class UserLoginRequestParamVerifyChain implements AbstractChianHandler<UserLoginRequestDTO> {
@Override @Override
public void handle(UserLoginRequestDTO requestParam) { public void handle(UserLoginRequestDTO requestParam) {
if (StringUtils.isAnyBlank(requestParam.getUserAccount(), requestParam.getUserPassword())) { if (StringUtils.isAnyBlank(requestParam.getUserAccount(), requestParam.getUserPassword())) {
@@ -34,4 +35,5 @@ public class UserLoginRequestParamVerifyChain implements AbstractChianHandler<Us
public int getOrder() { public int getOrder() {
return 10; return 10;
} }
} }

View File

@@ -6,4 +6,5 @@ import org.springframework.stereotype.Component;
@Component @Component
public class UserLoginRequestParamVerifyContext extends CommonChainContext<UserLoginRequestDTO> { public class UserLoginRequestParamVerifyContext extends CommonChainContext<UserLoginRequestDTO> {
} }

View File

@@ -4,6 +4,9 @@ import lombok.Data;
@Data @Data
public class UserLoginRequestDTO { public class UserLoginRequestDTO {
private String userAccount; private String userAccount;
private String userPassword; private String userPassword;
} }

View File

@@ -19,6 +19,7 @@ public class UserAuthRespDTO {
* 用户账号 * 用户账号
*/ */
private String userAccount; private String userAccount;
/** /**
* 用户密码 * 用户密码
*/ */
@@ -64,5 +65,4 @@ public class UserAuthRespDTO {
*/ */
private Date updateTime; private Date updateTime;
} }

View File

@@ -7,6 +7,7 @@ import java.util.Date;
@Data @Data
public class UserLoginResponseDTO implements Serializable { public class UserLoginResponseDTO implements Serializable {
/** /**
* id * id
*/ */
@@ -23,8 +24,11 @@ public class UserLoginResponseDTO implements Serializable {
private String unionId; private String unionId;
private String accessToken; private String accessToken;
private String refreshToken; private String refreshToken;
private Long expire; private Long expire;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@@ -7,4 +7,5 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
public class JwtAuthenticationFilter { public class JwtAuthenticationFilter {
} }

View File

@@ -4,6 +4,7 @@ import cn.meowrain.aioj.backend.auth.dto.req.UserLoginRequestDTO;
import cn.meowrain.aioj.backend.auth.dto.resp.UserLoginResponseDTO; import cn.meowrain.aioj.backend.auth.dto.resp.UserLoginResponseDTO;
public interface AuthService { public interface AuthService {
/** /**
* 用户登录 * 用户登录
* @param request {@link UserLoginRequestDTO} * @param request {@link UserLoginRequestDTO}
@@ -17,4 +18,5 @@ public interface AuthService {
* @return * @return
*/ */
UserLoginResponseDTO refreshToken(String refreshToken); UserLoginResponseDTO refreshToken(String refreshToken);
} }

View File

@@ -26,10 +26,15 @@ import java.util.concurrent.TimeUnit;
@RequiredArgsConstructor @RequiredArgsConstructor
@Slf4j @Slf4j
public class AuthServiceImpl implements AuthService { public class AuthServiceImpl implements AuthService {
private final JwtUtil jwtUtil; private final JwtUtil jwtUtil;
private final UserLoginRequestParamVerifyContext userLoginRequestParamVerifyContext; private final UserLoginRequestParamVerifyContext userLoginRequestParamVerifyContext;
private final UserClient userClient; private final UserClient userClient;
private final StringRedisTemplate stringRedisTemplate; private final StringRedisTemplate stringRedisTemplate;
private final JwtPropertiesConfiguration jwtPropertiesConfiguration; private final JwtPropertiesConfiguration jwtPropertiesConfiguration;
@Override @Override
@@ -45,8 +50,7 @@ public class AuthServiceImpl implements AuthService {
} }
UserAuthRespDTO user = userResp.getData(); UserAuthRespDTO user = userResp.getData();
if (ObjectUtil.isNull(user) if (ObjectUtil.isNull(user) || !BCrypt.checkpw(requestParam.getUserPassword(), user.getUserPassword())) {
|| !BCrypt.checkpw(requestParam.getUserPassword(), user.getUserPassword())) {
throw new ServiceException("用户不存在或者密码错误", ErrorCode.NOT_LOGIN_ERROR); throw new ServiceException("用户不存在或者密码错误", ErrorCode.NOT_LOGIN_ERROR);
} }
// 生成 JWT // 生成 JWT
@@ -59,11 +63,9 @@ public class AuthServiceImpl implements AuthService {
resp.setRefreshToken(refreshToken); resp.setRefreshToken(refreshToken);
// refresh token存入到REDIS里面 // refresh token存入到REDIS里面
stringRedisTemplate.opsForValue().set( stringRedisTemplate.opsForValue()
String.format(RedisKeyConstants.REFRESH_TOKEN_KEY_PREFIX, user.getId()), .set(String.format(RedisKeyConstants.REFRESH_TOKEN_KEY_PREFIX, user.getId()), refreshToken,
refreshToken, jwtPropertiesConfiguration.getRefreshExpire(), TimeUnit.MILLISECONDS);
jwtPropertiesConfiguration.getRefreshExpire(),
TimeUnit.MILLISECONDS);
return resp; return resp;
} }
@@ -98,9 +100,10 @@ public class AuthServiceImpl implements AuthService {
UserAuthRespDTO user = userResult.getData(); UserAuthRespDTO user = userResult.getData();
String newAccessToken = jwtUtil.generateAccessToken(user); String newAccessToken = jwtUtil.generateAccessToken(user);
//设置refresh token和access token // 设置refresh token和access token
userLoginResponseDTO.setRefreshToken(refreshToken); userLoginResponseDTO.setRefreshToken(refreshToken);
userLoginResponseDTO.setAccessToken(newAccessToken); userLoginResponseDTO.setAccessToken(newAccessToken);
return userLoginResponseDTO; return userLoginResponseDTO;
} }
} }

View File

@@ -55,11 +55,7 @@ public class JwtUtil {
/** 解析 Token */ /** 解析 Token */
public Claims parseClaims(String token) { public Claims parseClaims(String token) {
return Jwts.parser() return Jwts.parser().verifyWith(getSigningKey()).build().parseSignedClaims(token).getPayload();
.verifyWith(getSigningKey())
.build()
.parseSignedClaims(token)
.getPayload();
} }
/** 校验 Token 是否过期 */ /** 校验 Token 是否过期 */
@@ -67,8 +63,10 @@ public class JwtUtil {
try { try {
Claims claims = parseClaims(token); Claims claims = parseClaims(token);
return claims.getExpiration().after(new Date()); return claims.getExpiration().after(new Date());
} catch (Exception ignored) { }
catch (Exception ignored) {
return false; return false;
} }
} }
} }

View File

@@ -47,24 +47,15 @@ public class EnvironmentBanner implements ApplicationListener<ApplicationReadyEv
printBanner(appName, profiles, port, jvm, pid, time, gitCommit); printBanner(appName, profiles, port, jvm, pid, time, gitCommit);
} }
private void printBanner(String appName, private void printBanner(String appName, String profiles, String port, String jvm, String pid, String time,
String profiles,
String port,
String jvm,
String pid,
String time,
String gitCommit) { String gitCommit) {
String banner = "\n" + String banner = "\n" + "------------------------------------------------------------\n"
"------------------------------------------------------------\n" + + " ✨AI Online Judge✨ - " + appName + "\n" + " Environment : " + profiles + "\n" + " Port : "
" ✨AI Online Judge✨ - " + appName + "\n" + + port + "\n" + " Git Commit : " + gitCommit + "\n" + " JVM : " + jvm + "\n"
" Environment : " + profiles + "\n" + + " PID : " + pid + "\n" + " Started At : " + time + "\n"
" Port : " + port + "\n" + + "------------------------------------------------------------\n";
" Git Commit : " + gitCommit + "\n" +
" JVM : " + jvm + "\n" +
" PID : " + pid + "\n" +
" Started At : " + time + "\n" +
"------------------------------------------------------------\n";
System.out.println(banner); System.out.println(banner);
} }
} }

View File

@@ -1,6 +1,5 @@
package cn.meowrain.aioj.backend.framework.core.config; package cn.meowrain.aioj.backend.framework.core.config;
import cn.meowrain.aioj.backend.framework.core.exception.handler.GlobalExceptionHandler; import cn.meowrain.aioj.backend.framework.core.exception.handler.GlobalExceptionHandler;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@@ -8,8 +7,10 @@ import org.springframework.context.annotation.Bean;
* 注册为bean,全局异常拦截器 * 注册为bean,全局异常拦截器
*/ */
public class WebAutoConfiguration { public class WebAutoConfiguration {
@Bean @Bean
public GlobalExceptionHandler globalExceptionHandler() { public GlobalExceptionHandler globalExceptionHandler() {
return new GlobalExceptionHandler(); return new GlobalExceptionHandler();
} }
} }

View File

@@ -3,17 +3,17 @@ package cn.meowrain.aioj.backend.framework.core.designpattern.chains;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
public interface AbstractChianHandler<T> extends Ordered { public interface AbstractChianHandler<T> extends Ordered {
/** /**
* 执行责任链逻辑 * 执行责任链逻辑
*
* @param requestParam 责任链执行入参 * @param requestParam 责任链执行入参
*/ */
void handle(T requestParam); void handle(T requestParam);
/** /**
* 责任链组件标识 * 责任链组件标识
*
* @return String * @return String
*/ */
String mark(); String mark();
} }

View File

@@ -19,6 +19,7 @@ import java.util.stream.Collectors;
@Component @Component
@Slf4j @Slf4j
public class CommonChainContext<T> implements ApplicationContextAware, CommandLineRunner { public class CommonChainContext<T> implements ApplicationContextAware, CommandLineRunner {
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
@Override @Override
@@ -41,16 +42,12 @@ public class CommonChainContext<T> implements ApplicationContextAware, CommandLi
@Override @Override
public void run(String... args) throws Exception { public void run(String... args) throws Exception {
log.info("【责任链路初始化】开始加载并分组所有处理器..."); log.info("【责任链路初始化】开始加载并分组所有处理器...");
applicationContext.getBeansOfType(AbstractChianHandler.class) applicationContext.getBeansOfType(AbstractChianHandler.class).values().forEach(handler -> {
.values()
.forEach(handler -> {
// 打印当前处理器的类名和它所属的 ChainMark // 打印当前处理器的类名和它所属的 ChainMark
String handlerName = handler.getClass().getSimpleName(); String handlerName = handler.getClass().getSimpleName();
String mark = handler.mark(); String mark = handler.mark();
log.info(" -> 发现处理器:{},归属链路:{}", handlerName, mark); log.info(" -> 发现处理器:{},归属链路:{}", handlerName, mark);
abstractChainHandlerMap abstractChainHandlerMap.computeIfAbsent(handler.mark(), k -> new ArrayList<>()).add(handler);
.computeIfAbsent(handler.mark(), k -> new ArrayList<>())
.add(handler);
}); });
// 步骤 2: 对每个链路中的处理器进行排序 (Sort 阶段) // 步骤 2: 对每个链路中的处理器进行排序 (Sort 阶段)

View File

@@ -4,14 +4,17 @@ package cn.meowrain.aioj.backend.framework.core.enums;
* 删除枚举 * 删除枚举
*/ */
public enum DelStatusEnum { public enum DelStatusEnum {
STATUS_NORMAL("0"),
STATUS_DELETE("1"); STATUS_NORMAL("0"), STATUS_DELETE("1");
private final String code; private final String code;
DelStatusEnum(String code) { DelStatusEnum(String code) {
this.code = code; this.code = code;
} }
public String code() { public String code() {
return this.code; return this.code;
} }
} }

View File

@@ -1,15 +1,11 @@
package cn.meowrain.aioj.backend.framework.core.errorcode; package cn.meowrain.aioj.backend.framework.core.errorcode;
public enum ErrorCode implements IErrorCode { public enum ErrorCode implements IErrorCode {
SUCCESS("0", "ok"),
PARAMS_ERROR("40000", "请求参数错误"), SUCCESS("0", "ok"), PARAMS_ERROR("40000", "请求参数错误"), NOT_LOGIN_ERROR("40100", "未登录"), NO_AUTH_ERROR("40101", "无权限"),
NOT_LOGIN_ERROR("40100", "未登录"), NOT_FOUND_ERROR("40400", "请求数据不存在"), FORBIDDEN_ERROR("40300", "禁止访问"), SYSTEM_ERROR("50000", "系统内部异常"),
NO_AUTH_ERROR("40101", "无权限"), OPERATION_ERROR("50001", "操作失败"), API_REQUEST_ERROR("50010", "接口调用失败");
NOT_FOUND_ERROR("40400", "请求数据不存在"),
FORBIDDEN_ERROR("40300", "禁止访问"),
SYSTEM_ERROR("50000", "系统内部异常"),
OPERATION_ERROR("50001", "操作失败"),
API_REQUEST_ERROR("50010", "接口调用失败");
/** /**
* 状态码 * 状态码
*/ */
@@ -35,4 +31,5 @@ public enum ErrorCode implements IErrorCode {
public String message() { public String message() {
return message; return message;
} }
} }

View File

@@ -1,6 +1,9 @@
package cn.meowrain.aioj.backend.framework.core.errorcode; package cn.meowrain.aioj.backend.framework.core.errorcode;
public interface IErrorCode { public interface IErrorCode {
String code(); String code();
String message(); String message();
} }

View File

@@ -12,7 +12,9 @@ import java.util.Optional;
@Getter @Getter
public class AbstractException extends RuntimeException { public class AbstractException extends RuntimeException {
public final String errorCode; public final String errorCode;
public final String errorMessage; public final String errorMessage;
public AbstractException(String message, Throwable throwable, IErrorCode errorCode) { public AbstractException(String message, Throwable throwable, IErrorCode errorCode) {
@@ -21,4 +23,5 @@ public class AbstractException extends RuntimeException {
this.errorMessage = Optional.ofNullable(StringUtils.hasLength(message) ? message : null) this.errorMessage = Optional.ofNullable(StringUtils.hasLength(message) ? message : null)
.orElse(errorCode.message()); .orElse(errorCode.message());
} }
} }

View File

@@ -8,7 +8,8 @@ import lombok.ToString;
* 客户端异常 * 客户端异常
*/ */
@ToString @ToString
public class ClientException extends AbstractException{ public class ClientException extends AbstractException {
public ClientException(String message, Throwable throwable, IErrorCode errorCode) { public ClientException(String message, Throwable throwable, IErrorCode errorCode) {
super(message, throwable, errorCode); super(message, throwable, errorCode);
} }

View File

@@ -8,7 +8,8 @@ import lombok.ToString;
* 调用第三方服务异常 * 调用第三方服务异常
*/ */
@ToString @ToString
public class RemoteException extends AbstractException{ public class RemoteException extends AbstractException {
public RemoteException(IErrorCode errorCode) { public RemoteException(IErrorCode errorCode) {
this(null, null, errorCode); this(null, null, errorCode);
} }
@@ -20,6 +21,7 @@ public class RemoteException extends AbstractException{
public RemoteException(String message, Throwable throwable, IErrorCode errorCode) { public RemoteException(String message, Throwable throwable, IErrorCode errorCode) {
super(message, throwable, errorCode); super(message, throwable, errorCode);
} }
public RemoteException(String message) { public RemoteException(String message) {
this(message, null, ErrorCode.API_REQUEST_ERROR); this(message, null, ErrorCode.API_REQUEST_ERROR);
} }

View File

@@ -9,6 +9,7 @@ import lombok.ToString;
*/ */
@ToString @ToString
public class ServiceException extends AbstractException { public class ServiceException extends AbstractException {
public ServiceException(String message, IErrorCode errorCode) { public ServiceException(String message, IErrorCode errorCode) {
this(message, null, errorCode); this(message, null, errorCode);
} }

View File

@@ -20,6 +20,7 @@ import java.util.List;
@Slf4j @Slf4j
@RestControllerAdvice @RestControllerAdvice
public class GlobalExceptionHandler { public class GlobalExceptionHandler {
/** /**
* 捕获所有参数错误,然后统一捕获并且抛出 * 捕获所有参数错误,然后统一捕获并且抛出
* @param request {@link HttpServletRequest} * @param request {@link HttpServletRequest}
@@ -30,8 +31,10 @@ public class GlobalExceptionHandler {
public Result<Void> validExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException ex) { public Result<Void> validExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException ex) {
BindingResult bindingResult = ex.getBindingResult(); BindingResult bindingResult = ex.getBindingResult();
// 收集所有错误字段 // 收集所有错误字段
List<String> errorMessages = bindingResult.getFieldErrors().stream() List<String> errorMessages = bindingResult.getFieldErrors()
.map(FieldError::getDefaultMessage).toList(); .stream()
.map(FieldError::getDefaultMessage)
.toList();
String exceptionMessage = String.join(",", errorMessages); String exceptionMessage = String.join(",", errorMessages);
log.error("[{}] {} [ex] {}", request.getMethod(), getUrl(request), exceptionMessage); log.error("[{}] {} [ex] {}", request.getMethod(), getUrl(request), exceptionMessage);
return Results.paramsValidFailure(); return Results.paramsValidFailure();
@@ -43,8 +46,8 @@ public class GlobalExceptionHandler {
* @param ex {@link AbstractException} * @param ex {@link AbstractException}
* @return {@link Result<Void>} * @return {@link Result<Void>}
*/ */
@ExceptionHandler(value = {AbstractException.class}) @ExceptionHandler(value = { AbstractException.class })
public Result<Void> abstractExceptionHandler(HttpServletRequest request,AbstractException ex ) { public Result<Void> abstractExceptionHandler(HttpServletRequest request, AbstractException ex) {
if (ex.getCause() != null) { if (ex.getCause() != null) {
log.error("[{}] {} [ex] {}", request.getMethod(), request.getRequestURL().toString(), ex, ex.getCause()); log.error("[{}] {} [ex] {}", request.getMethod(), request.getRequestURL().toString(), ex, ex.getCause());
return Results.failure(ex); return Results.failure(ex);
@@ -80,4 +83,5 @@ public class GlobalExceptionHandler {
} }
return request.getRequestURL() + "?" + request.getQueryString(); return request.getRequestURL() + "?" + request.getQueryString();
} }
} }

View File

@@ -12,20 +12,25 @@ import java.io.Serializable;
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public class Result<T> implements Serializable { public class Result<T> implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 正确返回码 * 正确返回码
* */ */
public static final String SUCCESS_CODE = "0"; public static final String SUCCESS_CODE = "0";
/** /**
* 响应码 * 响应码
*/ */
private String code; private String code;
/** /**
* 响应数据 * 响应数据
*/ */
private T data; private T data;
/** /**
* 响应信息 * 响应信息
*/ */
@@ -33,7 +38,6 @@ public class Result<T> implements Serializable {
/** /**
* 返回是否是正确响应 * 返回是否是正确响应
*
* @return boolean * @return boolean
*/ */
public boolean isSuccess() { public boolean isSuccess() {
@@ -47,4 +51,5 @@ public class Result<T> implements Serializable {
public boolean isFail() { public boolean isFail() {
return !isSuccess(); return !isSuccess();
} }
} }

View File

@@ -1,6 +1,5 @@
package cn.meowrain.aioj.backend.framework.core.web; package cn.meowrain.aioj.backend.framework.core.web;
import cn.meowrain.aioj.backend.framework.core.errorcode.ErrorCode; import cn.meowrain.aioj.backend.framework.core.errorcode.ErrorCode;
import cn.meowrain.aioj.backend.framework.core.exception.AbstractException; import cn.meowrain.aioj.backend.framework.core.exception.AbstractException;
@@ -10,9 +9,9 @@ import java.util.Optional;
* 构建响应的工具类 * 构建响应的工具类
*/ */
public final class Results { public final class Results {
/** /**
* 成功响应,不返回任何信息 * 成功响应,不返回任何信息
*
* @return {@link Result<Void>} * @return {@link Result<Void>}
*/ */
public static Result<Void> success() { public static Result<Void> success() {
@@ -21,14 +20,12 @@ public final class Results {
/** /**
* 成功响应 返回数据 * 成功响应 返回数据
*
* @param data 返回的响应体信息 * @param data 返回的响应体信息
* @param <T> 泛型 * @param <T> 泛型
* @return {@link Result<T>} * @return {@link Result<T>}
*/ */
public static <T> Result<T> success(T data) { public static <T> Result<T> success(T data) {
return new Result<T>().setCode(Result.SUCCESS_CODE) return new Result<T>().setCode(Result.SUCCESS_CODE).setData(data);
.setData(data);
} }
/** /**
@@ -41,17 +38,14 @@ public final class Results {
/** /**
* 服务端错误默认响应 -- <b>内部错误</b> * 服务端错误默认响应 -- <b>内部错误</b>
*
* @return {@link Result<Void>} * @return {@link Result<Void>}
*/ */
public static Result<Void> failure() { public static Result<Void> failure() {
return new Result<Void>().setCode(ErrorCode.SYSTEM_ERROR.code()) return new Result<Void>().setCode(ErrorCode.SYSTEM_ERROR.code()).setMessage(ErrorCode.SYSTEM_ERROR.message());
.setMessage(ErrorCode.SYSTEM_ERROR.message());
} }
/** /**
* 服务端错误响应 - 接收一个AbstractException里面定义了错误码和错误信息 * 服务端错误响应 - 接收一个AbstractException里面定义了错误码和错误信息
*
* @param exception {@link AbstractException} * @param exception {@link AbstractException}
* @return {@link Result<Void>} * @return {@link Result<Void>}
*/ */
@@ -59,21 +53,17 @@ public final class Results {
String errorCode = Optional.ofNullable(exception.getErrorCode()).orElse(ErrorCode.SYSTEM_ERROR.code()); String errorCode = Optional.ofNullable(exception.getErrorCode()).orElse(ErrorCode.SYSTEM_ERROR.code());
String errorMessage = Optional.ofNullable(exception.getMessage()).orElse(ErrorCode.SYSTEM_ERROR.message()); String errorMessage = Optional.ofNullable(exception.getMessage()).orElse(ErrorCode.SYSTEM_ERROR.message());
return new Result<Void>() return new Result<Void>().setCode(errorCode).setMessage(errorMessage);
.setCode(errorCode)
.setMessage(errorMessage);
} }
/** /**
* 服务端错误响应,自定义错误码和错误信息 * 服务端错误响应,自定义错误码和错误信息
*
* @param errorCode {@link String} * @param errorCode {@link String}
* @param errorMessage {@link String} * @param errorMessage {@link String}
* @return {@link Result<Void>} * @return {@link Result<Void>}
*/ */
public static Result<Void> failure(String errorCode, String errorMessage) { public static Result<Void> failure(String errorCode, String errorMessage) {
return new Result<Void>() return new Result<Void>().setCode(errorCode).setMessage(errorMessage);
.setCode(errorCode)
.setMessage(errorMessage);
} }
} }

View File

@@ -14,13 +14,16 @@ import org.springframework.scheduling.annotation.EnableAsync;
@EnableConfigurationProperties(AIOJLogPropertiesConfiguration.class) @EnableConfigurationProperties(AIOJLogPropertiesConfiguration.class)
@ConditionalOnProperty(value = "aioj.log.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "aioj.log.enabled", matchIfMissing = true)
public class LogAutoConfiguration { public class LogAutoConfiguration {
/** /**
* 创建并返回SysLogListener的Bean实例 * 创建并返回SysLogListener的Bean实例
*/ */
@Bean @Bean
public SysLogListener sysLogListener(AIOJLogPropertiesConfiguration logProperties, RemoteLogService remoteLogService) { public SysLogListener sysLogListener(AIOJLogPropertiesConfiguration logProperties,
RemoteLogService remoteLogService) {
return new SysLogListener(remoteLogService, logProperties); return new SysLogListener(remoteLogService, logProperties);
} }
/** /**
* 返回切面类实例 * 返回切面类实例
* @return {@link SysLogAspect} * @return {@link SysLogAspect}
@@ -29,4 +32,5 @@ public class LogAutoConfiguration {
public SysLogAspect sysLogAspect() { public SysLogAspect sysLogAspect() {
return new SysLogAspect(); return new SysLogAspect();
} }
} }

View File

@@ -9,6 +9,7 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface SysLog { public @interface SysLog {
/** /**
* 描述 * 描述
* @return {@link String} * @return {@link String}
@@ -20,4 +21,5 @@ public @interface SysLog {
* @return 日志描述 * @return 日志描述
*/ */
String expression() default ""; String expression() default "";
} }

View File

@@ -16,16 +16,17 @@ import org.springframework.expression.EvaluationContext;
public class SysLogAspect { public class SysLogAspect {
@Around("@annotation(sysLog)") @Around("@annotation(sysLog)")
public Object around(ProceedingJoinPoint joinPoint,SysLog sysLog) throws Throwable { public Object around(ProceedingJoinPoint joinPoint, SysLog sysLog) throws Throwable {
String strClassName = joinPoint.getTarget().getClass().getName(); String strClassName = joinPoint.getTarget().getClass().getName();
String strMethodName = joinPoint.getSignature().getName(); String strMethodName = joinPoint.getSignature().getName();
log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName); log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName);
String value = sysLog.value(); String value = sysLog.value();
String expression = sysLog.expression(); String expression = sysLog.expression();
if(StrUtil.isNotBlank(expression)) { if (StrUtil.isNotBlank(expression)) {
// 解析SPEL // 解析SPEL
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); MethodSignature signature = (MethodSignature) joinPoint.getSignature();
EvaluationContext context = SysLogUtils.getContext(point.getArgs(), signature.getMethod()); EvaluationContext context = SysLogUtils.getContext(point.getArgs(), signature.getMethod());
} }
} }
} }

View File

@@ -8,7 +8,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@Setter @Setter
@ConfigurationProperties(AIOJLogPropertiesConfiguration.PREFIX) @ConfigurationProperties(AIOJLogPropertiesConfiguration.PREFIX)
public class AIOJLogPropertiesConfiguration { public class AIOJLogPropertiesConfiguration {
public static final String PREFIX = "aioj.log"; public static final String PREFIX = "aioj.log";
/** /**
* 开启日志记录 * 开启日志记录
*/ */
@@ -18,4 +20,5 @@ public class AIOJLogPropertiesConfiguration {
* 请求报文最大存储长度 * 请求报文最大存储长度
*/ */
private Integer maxLength = 20000; private Integer maxLength = 20000;
} }

View File

@@ -89,4 +89,5 @@ public class SysLog implements Serializable {
* 删除标记 * 删除标记
*/ */
private String delFlag; private String delFlag;
} }

View File

@@ -9,12 +9,15 @@ import java.io.Serial;
* 系统日志事件类 * 系统日志事件类
*/ */
public class SysLogEvent extends ApplicationEvent { public class SysLogEvent extends ApplicationEvent {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 构造方法根据源SysLog对象创建SysLogEvent * 构造方法根据源SysLog对象创建SysLogEvent
*/ */
public SysLogEvent(SysLog source) { public SysLogEvent(SysLog source) {
super(source); super(source);
} }
} }

View File

@@ -13,6 +13,7 @@ import org.springframework.scheduling.annotation.Async;
@RequiredArgsConstructor @RequiredArgsConstructor
public class SysLogListener implements InitializingBean { public class SysLogListener implements InitializingBean {
private final static ObjectMapper objectMapper = new ObjectMapper(); private final static ObjectMapper objectMapper = new ObjectMapper();
private final RemoteLogService remoteLogService; private final RemoteLogService remoteLogService;
@@ -23,14 +24,16 @@ public class SysLogListener implements InitializingBean {
@Async @Async
@Order @Order
@EventListener(SysLogEvent.class) @EventListener(SysLogEvent.class)
public void saveLog(SysLogEvent sysLogEvent){ public void saveLog(SysLogEvent sysLogEvent) {
SysLogEventSource source = (SysLogEventSource) sysLogEvent.getSource(); SysLogEventSource source = (SysLogEventSource) sysLogEvent.getSource();
SysLog sysLog = new SysLog(); SysLog sysLog = new SysLog();
BeanUtils.copyProperties(source, sysLog); BeanUtils.copyProperties(source, sysLog);
} }
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
} }
} }

View File

@@ -6,6 +6,7 @@ import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
public class ApplicationLoggerInitializer implements EnvironmentPostProcessor, Ordered { public class ApplicationLoggerInitializer implements EnvironmentPostProcessor, Ordered {
@Override @Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
@@ -15,4 +16,5 @@ public class ApplicationLoggerInitializer implements EnvironmentPostProcessor, O
public int getOrder() { public int getOrder() {
return Ordered.LOWEST_PRECEDENCE; return Ordered.LOWEST_PRECEDENCE;
} }
} }

View File

@@ -3,7 +3,9 @@ package cn.meowrain.aioj.backend.framework.log.utils;
import cn.meowrain.aioj.backend.framework.log.event.SysLogEventSource; import cn.meowrain.aioj.backend.framework.log.event.SysLogEventSource;
public final class SysLogUtils { public final class SysLogUtils {
public static SysLogEventSource getSysLog() { public static SysLogEventSource getSysLog() {
} }
} }

View File

@@ -16,8 +16,10 @@ import java.time.LocalDateTime;
@Getter @Getter
@Setter @Setter
public class BaseEntity implements Serializable { public class BaseEntity implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 创建者 * 创建者
*/ */
@@ -45,4 +47,5 @@ public class BaseEntity implements Serializable {
@Schema(description = "更新时间") @Schema(description = "更新时间")
@TableField(fill = FieldFill.INSERT_UPDATE) @TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime; private LocalDateTime updateTime;
} }

View File

@@ -17,6 +17,7 @@ import java.util.Optional;
*/ */
@Slf4j @Slf4j
public class MybatisPlusMetaObjectHandler implements MetaObjectHandler { public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
@Override @Override
public void insertFill(MetaObject metaObject) { public void insertFill(MetaObject metaObject) {
log.debug("mybatis plus start insert fill ...."); log.debug("mybatis plus start insert fill ....");
@@ -39,7 +40,7 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
} }
private void fillValIfNullByName(String fieldName, Object fieldVal, MetaObject metaObject, boolean isCover) { private void fillValIfNullByName(String fieldName, Object fieldVal, MetaObject metaObject, boolean isCover) {
//如果填充值为空 // 如果填充值为空
if (fieldVal == null) { if (fieldVal == null) {
return; return;
} }
@@ -67,4 +68,5 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
return null; return null;
} }
} }

View File

@@ -1,6 +1,5 @@
package cn.meowrain.backend.common.mybaits.plugins; package cn.meowrain.backend.common.mybaits.plugins;
import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ParameterUtils; import com.baomidou.mybatisplus.core.toolkit.ParameterUtils;
@@ -16,14 +15,15 @@ import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.RowBounds;
/** /**
* * 分页拦截器实现类,用于处理分页查询逻辑 * * 分页拦截器实现类,用于处理分页查询逻辑 *
* * <p> * <p>
* * 当分页大小小于0时自动设置为0防止全表查询 * * 当分页大小小于0时自动设置为0防止全表查询
*/ */
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class PaginationInterceptor extends PaginationInnerInterceptor { public class PaginationInterceptor extends PaginationInnerInterceptor {
/** /**
* 数据库类型 * 数据库类型
* <p> * <p>
@@ -38,7 +38,6 @@ public class PaginationInterceptor extends PaginationInnerInterceptor {
*/ */
private IDialect dialect; private IDialect dialect;
public PaginationInterceptor(DbType dbType) { public PaginationInterceptor(DbType dbType) {
this.dbType = dbType; this.dbType = dbType;
} }
@@ -51,7 +50,8 @@ public class PaginationInterceptor extends PaginationInnerInterceptor {
* 在执行查询前处理分页参数 * 在执行查询前处理分页参数
*/ */
@Override @Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
ResultHandler resultHandler, BoundSql boundSql) {
IPage<?> page = ParameterUtils.findPage(parameter).orElse(null); IPage<?> page = ParameterUtils.findPage(parameter).orElse(null);
// size 小于 0 直接设置为 0 , 即不查询任何数据 // size 小于 0 直接设置为 0 , 即不查询任何数据
if (null != page && page.getSize() < 0) { if (null != page && page.getSize() < 0) {
@@ -59,4 +59,5 @@ public class PaginationInterceptor extends PaginationInnerInterceptor {
} }
super.beforeQuery(executor, ms, page, rowBounds, resultHandler, boundSql); super.beforeQuery(executor, ms, page, rowBounds, resultHandler, boundSql);
} }
} }

View File

@@ -5,10 +5,12 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
@EnableConfigurationProperties(value = {GatewayPropertiesConfiguration.class}) @EnableConfigurationProperties(value = { GatewayPropertiesConfiguration.class })
@SpringBootApplication @SpringBootApplication
public class AIOJGatewayApplication { public class AIOJGatewayApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(AIOJGatewayApplication.class, args); SpringApplication.run(AIOJGatewayApplication.class, args);
} }
} }

View File

@@ -12,22 +12,16 @@ import java.util.List;
/** /**
* 全局 CORS 配置WebFlux 环境使用 CorsWebFilter * 全局 CORS 配置WebFlux 环境使用 CorsWebFilter
* *
* WebFlux 不使用 Spring MVC 的 CorsFilter * WebFlux 不使用 Spring MVC 的 CorsFilter 而是使用专门的 CorsWebFilter 处理跨域。
* 而是使用专门的 CorsWebFilter 处理跨域。
* *
* 此配置实现了: * 此配置实现了: - 允许任意域名访问AllowedOriginPatterns = "*" - 允许所有请求方法GET、POST、PUT... - 允许所有请求头 -
* - 允许任意域名访问AllowedOriginPatterns = "*" * 允许跨域携带 CookieAllowCredentials - 对所有路径生效(/**
* - 允许所有请求方法GET、POST、PUT...
* - 允许所有请求头
* - 允许跨域携带 CookieAllowCredentials
* - 对所有路径生效(/**
*/ */
@Configuration @Configuration
public class CorsConfig { public class CorsConfig {
/** /**
* 注册全局 CORS 过滤器 * 注册全局 CORS 过滤器
*
* @return CorsWebFilter 跨域过滤器 * @return CorsWebFilter 跨域过滤器
*/ */
@Bean @Bean
@@ -43,9 +37,8 @@ public class CorsConfig {
corsConfiguration.setAllowCredentials(true); corsConfiguration.setAllowCredentials(true);
/** /**
* 允许跨域的来源域名 * 允许跨域的来源域名 使用 setAllowedOriginPatterns("*") 是 WebFlux 推荐方式, 因为
* 使用 setAllowedOriginPatterns("*") 是 WebFlux 推荐方式, * setAllowedOrigins("*") 在 allowCredentials=true 时会被拦截。
* 因为 setAllowedOrigins("*") 在 allowCredentials=true 时会被拦截。
*/ */
corsConfiguration.setAllowedOriginPatterns(List.of("*")); corsConfiguration.setAllowedOriginPatterns(List.of("*"));
@@ -53,11 +46,9 @@ public class CorsConfig {
corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedHeader("*");
/** /**
* 基于 URL 的跨域配置源, * 基于 URL 的跨域配置源, PathPatternParser 用于解析路径模式(更高性能)
* PathPatternParser 用于解析路径模式(更高性能)
*/ */
UrlBasedCorsConfigurationSource source = UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
new UrlBasedCorsConfigurationSource(new PathPatternParser());
// 对所有路径应用跨域设置 // 对所有路径应用跨域设置
source.registerCorsConfiguration("/**", corsConfiguration); source.registerCorsConfiguration("/**", corsConfiguration);
@@ -65,4 +56,5 @@ public class CorsConfig {
// 创建并返回 WebFlux 专用的 CORS 过滤器 // 创建并返回 WebFlux 专用的 CORS 过滤器
return new CorsWebFilter(source); return new CorsWebFilter(source);
} }
} }

View File

@@ -6,9 +6,12 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = GatewayPropertiesConfiguration.PREFIX) @ConfigurationProperties(prefix = GatewayPropertiesConfiguration.PREFIX)
@Data @Data
public class GatewayPropertiesConfiguration { public class GatewayPropertiesConfiguration {
public static final String PREFIX = "aioj-backend-gateway"; public static final String PREFIX = "aioj-backend-gateway";
/* /*
* 白名单放行 * 白名单放行
* */ */
private String[] whiteList; private String[] whiteList;
} }

View File

@@ -24,4 +24,5 @@ public class AuthGlobalFilter implements GlobalFilter, Ordered {
public int getOrder() { public int getOrder() {
return 0; return 0;
} }
} }

View File

@@ -7,7 +7,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication @SpringBootApplication
@MapperScan("cn.meowrain.aioj.backend.userservice.dao.mapper") @MapperScan("cn.meowrain.aioj.backend.userservice.dao.mapper")
public class UserServiceApplication { public class UserServiceApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args); SpringApplication.run(UserServiceApplication.class, args);
} }
} }

View File

@@ -5,6 +5,7 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor
public enum ChainMarkEnums { public enum ChainMarkEnums {
/** /**
* 用户注册请求验证 * 用户注册请求验证
*/ */
@@ -21,4 +22,5 @@ public enum ChainMarkEnums {
public String toString() { public String toString() {
return markName; return markName;
} }
} }

View File

@@ -5,10 +5,7 @@ import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
@ComponentScans({ @ComponentScans({ @ComponentScan("cn.meowrain.aioj.backend.framework.core.banner") })
@ComponentScan("cn.meowrain.aioj.backend.framework.core.banner")
})
public class FrameworkConfiguration { public class FrameworkConfiguration {
} }

View File

@@ -16,23 +16,25 @@ import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
@EnableKnife4j @EnableKnife4j
public class SwaggerConfiguration implements ApplicationRunner { public class SwaggerConfiguration implements ApplicationRunner {
@Value("${server.port:8080}") @Value("${server.port:8080}")
private String serverPort; private String serverPort;
@Value("${server.servlet.context-path:}") @Value("${server.servlet.context-path:}")
private String contextPath; private String contextPath;
@Bean @Bean
public OpenAPI customerOpenAPI() { public OpenAPI customerOpenAPI() {
return new OpenAPI() return new OpenAPI().info(new Info().title("AIOJ-用户微服务✨")
.info(new Info()
.title("AIOJ-用户微服务✨")
.description("用户注册,用户登录等功能") .description("用户注册,用户登录等功能")
.version("v1.0.0") .version("v1.0.0")
.contact(new Contact().name("meowrain").email("meowrain@126.com")) .contact(new Contact().name("meowrain").email("meowrain@126.com"))
.license(new License().name("MeowRain").url("https://meowrain.cn"))); .license(new License().name("MeowRain").url("https://meowrain.cn")));
} }
@Override @Override
public void run(ApplicationArguments args) throws Exception { public void run(ApplicationArguments args) throws Exception {
log.info("✨API Document: http://127.0.0.1:{}{}/doc.html", serverPort, contextPath); log.info("✨API Document: http://127.0.0.1:{}{}/doc.html", serverPort, contextPath);
} }
} }

View File

@@ -15,7 +15,6 @@ public class UserController {
private final UserService userService; private final UserService userService;
@PostMapping("/register") @PostMapping("/register")
public Result<Long> register(@RequestBody UserRegisterRequestDTO userRegisterRequest) { public Result<Long> register(@RequestBody UserRegisterRequestDTO userRegisterRequest) {
Long l = userService.userRegister(userRegisterRequest); Long l = userService.userRegister(userRegisterRequest);

View File

@@ -77,4 +77,5 @@ public class User implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@@ -4,4 +4,5 @@ import cn.meowrain.aioj.backend.userservice.dao.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface UserMapper extends BaseMapper<User> { public interface UserMapper extends BaseMapper<User> {
} }

View File

@@ -12,6 +12,7 @@ import org.springframework.stereotype.Component;
@Component @Component
@Slf4j @Slf4j
public class UserRegisterRequestParamVerifyChain implements AbstractChianHandler<UserRegisterRequestDTO> { public class UserRegisterRequestParamVerifyChain implements AbstractChianHandler<UserRegisterRequestDTO> {
@Override @Override
public void handle(UserRegisterRequestDTO requestParam) { public void handle(UserRegisterRequestDTO requestParam) {
// 校验参数里面用户名和密码是不是空的 // 校验参数里面用户名和密码是不是空的
@@ -40,4 +41,5 @@ public class UserRegisterRequestParamVerifyChain implements AbstractChianHandler
public int getOrder() { public int getOrder() {
return 10; return 10;
} }
} }

View File

@@ -6,4 +6,5 @@ import org.springframework.stereotype.Component;
@Component @Component
public class UserRegisterRequestParamVerifyContext extends CommonChainContext<UserRegisterRequestDTO> { public class UserRegisterRequestParamVerifyContext extends CommonChainContext<UserRegisterRequestDTO> {
} }

View File

@@ -5,6 +5,9 @@ import lombok.Data;
@Data @Data
public class UserLoginRequestDTO { public class UserLoginRequestDTO {
private String userAccount; private String userAccount;
private String userPassword; private String userPassword;
} }

View File

@@ -5,7 +5,11 @@ import lombok.NoArgsConstructor;
@Data @Data
public class UserRegisterRequestDTO { public class UserRegisterRequestDTO {
private String userAccount; private String userAccount;
private String userPassword; private String userPassword;
private String checkPassword; private String checkPassword;
} }

View File

@@ -19,6 +19,7 @@ public class UserAuthRespDTO {
* 用户账号 * 用户账号
*/ */
private String userAccount; private String userAccount;
/** /**
* 用户密码 * 用户密码
*/ */
@@ -64,6 +65,4 @@ public class UserAuthRespDTO {
*/ */
private Date updateTime; private Date updateTime;
} }

View File

@@ -8,6 +8,7 @@ import java.util.Date;
@Data @Data
public class UserLoginResponseDTO implements Serializable { public class UserLoginResponseDTO implements Serializable {
/** /**
* id * id
*/ */
@@ -65,11 +66,11 @@ public class UserLoginResponseDTO implements Serializable {
private Integer isDelete; private Integer isDelete;
/** /**
* JWT令牌登录成功返回 * JWT令牌登录成功返回
*/ */
private String token; private String token;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@@ -9,5 +9,7 @@ import java.io.Serializable;
*/ */
@Data @Data
public class UserRegisterResponseDTO implements Serializable { public class UserRegisterResponseDTO implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@@ -7,15 +7,15 @@ import cn.meowrain.aioj.backend.userservice.dto.resp.UserAuthRespDTO;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
public interface UserService extends IService<User> { public interface UserService extends IService<User> {
/** /**
* 用户注册 * 用户注册
* @param request {@link cn.meowrain.aioj.backend.userservice.dto.req.UserRegisterRequestDTO} * @param request
* {@link cn.meowrain.aioj.backend.userservice.dto.req.UserRegisterRequestDTO}
* @return {@link Long} * @return {@link Long}
*/ */
Long userRegister(UserRegisterRequestDTO request); Long userRegister(UserRegisterRequestDTO request);
/** /**
* 根据用户账号查找用户认证信息 * 根据用户账号查找用户认证信息
* @param userAccount * @param userAccount
@@ -27,4 +27,5 @@ public interface UserService extends IService<User> {
* 根据用户id查找用户认证信息 * 根据用户id查找用户认证信息
*/ */
UserAuthRespDTO findAuthInfoByUserId(String userId); UserAuthRespDTO findAuthInfoByUserId(String userId);
} }

View File

@@ -25,6 +25,7 @@ import java.util.Date;
@RequiredArgsConstructor @RequiredArgsConstructor
@Slf4j @Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
private final UserRegisterRequestParamVerifyContext userRegisterRequestParamVerifyContext; private final UserRegisterRequestParamVerifyContext userRegisterRequestParamVerifyContext;
@Override @Override
@@ -41,12 +42,16 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
Date now = new Date(); Date now = new Date();
String salt = BCrypt.gensalt(); String salt = BCrypt.gensalt();
String encryptPassword = BCrypt.hashpw(request.getUserPassword(), salt); String encryptPassword = BCrypt.hashpw(request.getUserPassword(), salt);
User user = new User().setUserAccount(request.getUserAccount()).setUserPassword(encryptPassword) User user = new User().setUserAccount(request.getUserAccount())
.setUserRole("user").setCreateTime(now).setUpdateTime(now); .setUserPassword(encryptPassword)
.setUserRole("user")
.setCreateTime(now)
.setUpdateTime(now);
try { try {
// 需要修改表,使得用户名是唯一的 // 需要修改表,使得用户名是唯一的
this.save(user); this.save(user);
} catch (DuplicateKeyException e) { }
catch (DuplicateKeyException e) {
log.error("重复创建用户"); log.error("重复创建用户");
throw new ServiceException("用户名已存在", ErrorCode.SYSTEM_ERROR); throw new ServiceException("用户名已存在", ErrorCode.SYSTEM_ERROR);
} }
@@ -54,7 +59,6 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
return user.getId(); return user.getId();
} }
@Override @Override
public UserAuthRespDTO findAuthInfoByUserAccount(String userAccount) { public UserAuthRespDTO findAuthInfoByUserAccount(String userAccount) {
User one = this.lambdaQuery().eq(User::getUserAccount, userAccount).one(); User one = this.lambdaQuery().eq(User::getUserAccount, userAccount).one();
@@ -77,4 +81,5 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
return null; return null;
} }
} }

20
pom.xml
View File

@@ -31,6 +31,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>3.5.7</spring-boot.version> <spring-boot.version>3.5.7</spring-boot.version>
<spring-cloud-alibaba.version>2025.0.0.0</spring-cloud-alibaba.version> <spring-cloud-alibaba.version>2025.0.0.0</spring-cloud-alibaba.version>
<spring.checkstyle.plugin>0.0.47</spring.checkstyle.plugin>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
@@ -84,6 +85,10 @@
<resources> <resources>
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
<includes>
<include>application*.yml</include>
<include>application*.properties</include>
</includes>
<filtering>true</filtering> <filtering>true</filtering>
</resource> </resource>
</resources> </resources>
@@ -103,6 +108,21 @@
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version> <version>${spring-boot.version}</version>
</plugin> </plugin>
<!--
代码格式插件默认使用spring 规则,可运行命令进行项目格式化:./mvnw spring-javaformat:apply 或 mvn spring-javaformat:apply可在IDEA中安装插件以下插件进行自动格式化
https://repo1.maven.org/maven2/io/spring/javaformat/spring-javaformat-intellij-idea-plugin
-->
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>${spring.checkstyle.plugin}</version>
<executions>
<execution>
<phase>validate</phase>
<inherited>true</inherited>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>
<profiles> <profiles>