diff --git a/src/main/java/co/jp/app/common/ApiResponse.java b/src/main/java/co/jp/app/common/ApiResponse.java index 33bbe4f..3bea82a 100644 --- a/src/main/java/co/jp/app/common/ApiResponse.java +++ b/src/main/java/co/jp/app/common/ApiResponse.java @@ -1,59 +1,64 @@ package co.jp.app.common; -import java.util.Objects; +import co.jp.app.common.ResultCode; public class ApiResponse { private boolean success; + private int code; private String message; private T data; - public static ApiResponse success(T data) { - - return new ApiResponse<>(true, null, data); - } - - public static ApiResponse fail(String message) { - - return new ApiResponse<>(false, message, null); - } - - public ApiResponse() { - } - - public ApiResponse(boolean success, String message, T data) { - this.success = success; - this.message = message; + private ApiResponse(ResultCode resultCode, T data) { + this.code = resultCode.getCode(); + this.message = resultCode.getMessage(); + this.success = (resultCode.getCode() == ResultCode.SUCCESS.getCode()); this.data = data; } + public static ApiResponse success(T data) { + return new ApiResponse<>(ResultCode.SUCCESS, data); + } + + public static ApiResponse success() { + return success(null); + } + + public static ApiResponse fail(ResultCode resultCode) { + if (resultCode == ResultCode.SUCCESS) { + + throw new IllegalArgumentException("Cannot use SUCCESS ResultCode for fail method. Use a specific error code."); + } + return new ApiResponse<>(resultCode, null); + } + + public static ApiResponse fail(ResultCode resultCode, T data) { + if (resultCode == ResultCode.SUCCESS) { + throw new IllegalArgumentException("Cannot use SUCCESS ResultCode for fail method. Use a specific error code."); + } + return new ApiResponse<>(resultCode, data); + } + public boolean isSuccess() { return success; } - public void setSuccess(boolean success) { - this.success = success; + public int getCode() { + return code; } public String getMessage() { return message; } - public void setMessage(String message) { - this.message = message; - } - public T getData() { return data; } - public void setData(T data) { - this.data = data; - } - @Override public String toString() { return "ApiResponse{" + "success=" + success + + ", code=" + code + ", message='" + message + '\'' + ", data=" + data + '}'; diff --git a/src/main/java/co/jp/app/common/ResultCode.java b/src/main/java/co/jp/app/common/ResultCode.java new file mode 100644 index 0000000..871174a --- /dev/null +++ b/src/main/java/co/jp/app/common/ResultCode.java @@ -0,0 +1,84 @@ +package co.jp.app.common; + +public enum ResultCode { + + SUCCESS(200, "Success"), // 通常与 HTTP 200 OK 对应 + + // 客户端错误段 (1000 - 1999) + BAD_REQUEST(1000, "HTTP 400 Bad Request"), + UNAUTHORIZED(1001, "HTTP 401 Unauthorized"), + FORBIDDEN(1002, "HTTP 403 Forbidden"), + NOT_FOUND(1003, "HTTP 404 Not Found"), + METHOD_NOT_ALLOWED(1004, "HTTP 405 Method Not Allowed"), + REQUEST_TIMEOUT(1005, "HTTP 408 Request Timeout"), + CONFLICT(1006, "HTTP 409 Conflict"), + UNSUPPORTED_MEDIA_TYPE(1007, "HTTP 415 Unsupported Media Type"), // 对应 + TOO_MANY_REQUESTS(1008, "HTTP 429 Too Many Requests"), // 对应 + VALIDATION_ERROR(1009, "Parameter validation failure"), // 通常由 @Valid 触发,可包含更详细的字段错误信息 + + // 服务端错误段 (2000 - 2999) - 通常建议与 HTTP 5xx 状态码含义相似 + INTERNAL_SERVER_ERROR(2000, "HTTP 500 Internal Server Error"), + SERVICE_UNAVAILABLE(2001, "HTTP 503 Service Unavailable"), + GATEWAY_TIMEOUT(2002, "HTTP 504 Gateway Timeout"), + DATABASE_ERROR(2003, "Database error"), + NETWORK_ERROR(2004, "Network error"), + THIRD_PARTY_SERVICE_ERROR(2005, "Third-party service error"), + + // ================================== 用户模块状态码 (3000 - 3999) ================================== + // 注册相关 + // USER_REGISTRATION_SUCCESS(3000, "用户注册成功"), // 成功状态也可以用通用的 SUCCESS + USER_EMAIL_ALREADY_EXISTS(3001, "Email already exists"), + // USER_USERNAME_ALREADY_EXISTS(3002, "Username"), + USER_PASSWORD_TOO_SHORT(3003, "password too short"), + USER_PASSWORD_TOO_WEAK(3004, "password too weak"), + USER_REGISTRATION_FAILED(3005, "User registration failed"), + + // 登录相关 + // USER_LOGIN_SUCCESS(3100, "登录成功"), + USER_ACCOUNT_NOT_FOUND(3101, "User account not found"), + USER_INVALID_CREDENTIALS(3102, "User invalid credentials"), + USER_ACCOUNT_LOCKED(3103, "User account locked"), + USER_ACCOUNT_DISABLED(3104, "User account disabled"), + USER_ACCOUNT_EXPIRED(3105, "User account expired"), + USER_LOGIN_FAILED(3106, "User login failed"), + USER_SESSION_EXPIRED(3107, "User session expired"), + USER_TOKEN_INVALID(3108, "User token invalid"), + USER_TOKEN_EXPIRED(3109, "User token expired(Token"), + USER_REFRESH_TOKEN_INVALID(3110, "User refresh token invalid"), + // USER_REFRESH_TOKEN_EXPIRED(3111, "User refresh token expired(Refresh Token"), + USER_LOGOUT_SUCCESS(3112, "loignout success"), + + // 用户信息相关 + USER_PROFILE_NOT_FOUND(3200, "User profile not found"), + USER_UPDATE_PROFILE_SUCCESS(3201, "User profile updated"), + USER_UPDATE_PROFILE_FAILED(3202, "User profile update failed"), + USER_CHANGE_PASSWORD_SUCCESS(3203, "Change password success"), + USER_CHANGE_PASSWORD_FAILED(3204, "Change password failed"), + USER_OLD_PASSWORD_MISMATCH(3205, "Old password mismatch"), + + // 权限相关 (如果你的用户模块包含复杂权限) + // USER_PERMISSION_DENIED(3300, "用户权限不足(细粒度)"), // 可用于补充 FORBIDDEN + + ; + + private final int code; + private final String message; + + ResultCode(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public String getMessage() { + return message; + } + + // (可选) 允许覆盖默认消息的方法,用于更具体的场景 + public String getMessage(String customDetail) { + return this.message + (customDetail == null || customDetail.isEmpty() ? "" : " (" + customDetail + ")"); + } +} \ No newline at end of file diff --git a/src/main/java/co/jp/app/controller/UserController.java b/src/main/java/co/jp/app/controller/UserController.java index 803c305..6324317 100644 --- a/src/main/java/co/jp/app/controller/UserController.java +++ b/src/main/java/co/jp/app/controller/UserController.java @@ -1,6 +1,7 @@ package co.jp.app.controller; import co.jp.app.common.ApiResponse; +import co.jp.app.common.ResultCode; import co.jp.app.dto.LoginDto; import co.jp.app.dto.RegistrationDto; import co.jp.app.service.JwtService; @@ -15,9 +16,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.*; -import co.jp.app.entity.ErrorEntity; import co.jp.app.entity.UserEntity; -import co.jp.app.service.ErraService; import co.jp.app.service.UserService; import java.util.HashMap; @@ -46,7 +45,7 @@ public class UserController { return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse.success(registeredUser.getEmail())); } catch (Exception e) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ApiResponse.fail("ユーザー登録失敗しました。")); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ApiResponse.fail(ResultCode.BAD_REQUEST,null)); } } @@ -59,7 +58,7 @@ public class UserController { SecurityContextHolder.getContext().setAuthentication(authentication); UserDetails userDetails = (UserDetails) authentication.getPrincipal(); - String jwtToken = jwtService.generateToken(userDetails); // 生成单一的Token + String jwtToken = jwtService.generateToken(userDetails); Map tokenResponse = new HashMap<>(); tokenResponse.put("token", jwtToken); @@ -68,10 +67,10 @@ public class UserController { } catch (BadCredentialsException e) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponse.fail("メールアドレスまたはパスワードが間違っています。")); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponse.fail(ResultCode.UNAUTHORIZED,null)); } catch (Exception e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ApiResponse.fail("サーバーエラー。")); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ApiResponse.fail(ResultCode.SERVICE_UNAVAILABLE,null)); } } } diff --git a/target/classes/co/jp/app/repository/ErrRepository.class b/target/classes/co/jp/app/repository/ErrRepository.class deleted file mode 100644 index c8802c9..0000000 Binary files a/target/classes/co/jp/app/repository/ErrRepository.class and /dev/null differ diff --git a/target/classes/co/jp/app/service/erraService.class b/target/classes/co/jp/app/service/erraService.class deleted file mode 100644 index 6e7e760..0000000 Binary files a/target/classes/co/jp/app/service/erraService.class and /dev/null differ