[API 응답 표준화] CustomApiResponse를 ApiResponseDto로 변경하여 API 응답 구조를 통일하고, 관련 코드 및 문서 업데이트
This commit is contained in:
21
README.md
21
README.md
@@ -32,14 +32,14 @@ src/main/java/com/bio/bio_backend/
|
|||||||
└── BioBackendApplication.java
|
└── BioBackendApplication.java
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. API 응답 표준화 (CustomApiResponse)
|
### 2. API 응답 표준화 (ApiResponseDto)
|
||||||
|
|
||||||
#### 응답 구조
|
#### 응답 구조
|
||||||
|
|
||||||
모든 API 응답은 `CustomApiResponse<T>` 형태로 표준화되어 있습니다.
|
모든 API 응답은 `ApiResponseDto<T>` 형태로 표준화되어 있습니다.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class CustomApiResponse<T> {
|
public class ApiResponseDto<T> {
|
||||||
private int code; // HTTP 상태 코드
|
private int code; // HTTP 상태 코드
|
||||||
private String message; // 응답 메시지 (ApiResponseCode enum 값)
|
private String message; // 응답 메시지 (ApiResponseCode enum 값)
|
||||||
private String description; // 응답 설명
|
private String description; // 응답 설명
|
||||||
@@ -81,12 +81,12 @@ public class CustomApiResponse<T> {
|
|||||||
|
|
||||||
```java
|
```java
|
||||||
@PostMapping("/members")
|
@PostMapping("/members")
|
||||||
public ResponseEntity<CustomApiResponse<CreateMemberResponseDto>> createMember(@RequestBody CreateMemberRequestDto requestDto) {
|
public ResponseEntity<ApiResponseDto<CreateMemberResponseDto>> createMember(@RequestBody CreateMemberRequestDto requestDto) {
|
||||||
// ... 비즈니스 로직 ...
|
// ... 비즈니스 로직 ...
|
||||||
|
|
||||||
// 성공 응답
|
// 성공 응답
|
||||||
CustomApiResponse<CreateMemberResponseDto> apiResponse =
|
ApiResponseDto<CreateMemberResponseDto> apiResponse =
|
||||||
CustomApiResponse.success(ApiResponseCode.COMMON_SUCCESS_CREATED, responseDto);
|
ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_CREATED, responseDto);
|
||||||
|
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse);
|
return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse);
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,7 @@ public enum ApiResponseCode {
|
|||||||
|
|
||||||
#### 핵심 규칙
|
#### 핵심 규칙
|
||||||
|
|
||||||
- **모든 API 응답**: `CustomApiResponse<T>`로 감싸서 반환
|
- **모든 API 응답**: `ApiResponseDto<T>`로 감싸서 반환
|
||||||
- **공용 응답 코드**: `COMMON_` 접두사로 시작하는 범용 코드 사용
|
- **공용 응답 코드**: `COMMON_` 접두사로 시작하는 범용 코드 사용
|
||||||
- **일관된 구조**: `code`, `message`, `description`, `data` 필드로 표준화
|
- **일관된 구조**: `code`, `message`, `description`, `data` 필드로 표준화
|
||||||
- **제네릭 활용**: `<T>`를 통해 다양한 데이터 타입 지원
|
- **제네릭 활용**: `<T>`를 통해 다양한 데이터 타입 지원
|
||||||
@@ -132,12 +132,11 @@ public enum ApiResponseCode {
|
|||||||
@Tag(name = "Member", description = "회원 관리 API")
|
@Tag(name = "Member", description = "회원 관리 API")
|
||||||
@Operation(summary = "회원 가입", description = "새로운 회원을 등록합니다.")
|
@Operation(summary = "회원 가입", description = "새로운 회원을 등록합니다.")
|
||||||
@ApiResponses(value = {
|
@ApiResponses(value = {
|
||||||
@ApiResponse(responseCode = "201", description = "회원 가입 성공",
|
@ApiResponse(responseCode = "201", description = "회원 가입 성공"),
|
||||||
content = @Content(schema = @Schema(implementation = CustomApiResponse.class))),
|
|
||||||
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터",
|
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터",
|
||||||
content = @Content(schema = @Schema(implementation = CustomApiResponse.class))),
|
content = @Content(schema = @Schema(implementation = ApiResponseDto.class))),
|
||||||
@ApiResponse(responseCode = "409", description = "중복된 사용자 정보",
|
@ApiResponse(responseCode = "409", description = "중복된 사용자 정보",
|
||||||
content = @Content(schema = @Schema(implementation = CustomApiResponse.class)))
|
content = @Content(schema = @Schema(implementation = ApiResponseDto.class)))
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@@ -1,14 +1,11 @@
|
|||||||
package com.bio.bio_backend.domain.user.member.controller;
|
package com.bio.bio_backend.domain.user.member.controller;
|
||||||
|
|
||||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
|
import com.bio.bio_backend.global.dto.ApiResponseDto;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
|
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
|
||||||
@@ -27,6 +24,7 @@ import com.bio.bio_backend.global.utils.ApiResponseCode;
|
|||||||
|
|
||||||
@Tag(name = "Member", description = "회원 관련 API")
|
@Tag(name = "Member", description = "회원 관련 API")
|
||||||
@RestController
|
@RestController
|
||||||
|
@RequestMapping("/members")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class MemberController {
|
public class MemberController {
|
||||||
@@ -38,16 +36,15 @@ public class MemberController {
|
|||||||
@Operation(summary = "회원 가입", description = "새로운 회원을 등록합니다.")
|
@Operation(summary = "회원 가입", description = "새로운 회원을 등록합니다.")
|
||||||
@ApiResponses({
|
@ApiResponses({
|
||||||
@ApiResponse(responseCode = "201", description = "회원 가입 성공"),
|
@ApiResponse(responseCode = "201", description = "회원 가입 성공"),
|
||||||
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
|
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content(schema = @Schema(implementation = ApiResponseDto.class))),
|
||||||
@ApiResponse(responseCode = "409", description = "중복된 사용자 정보")
|
@ApiResponse(responseCode = "409", description = "중복된 사용자 정보", content = @Content(schema = @Schema(implementation = ApiResponseDto.class)))
|
||||||
})
|
})
|
||||||
@PostMapping("/members")
|
@PostMapping
|
||||||
public ResponseEntity<CustomApiResponse<CreateMemberResponseDto>> createMember(@RequestBody @Valid CreateMemberRequestDto requestDto) {
|
public ResponseEntity<ApiResponseDto<CreateMemberResponseDto>> createMember(@RequestBody @Valid CreateMemberRequestDto requestDto) {
|
||||||
MemberDto member = memberMapper.toMemberDto(requestDto);
|
MemberDto member = memberMapper.toMemberDto(requestDto);
|
||||||
MemberDto createdMember = memberService.createMember(member);
|
MemberDto createdMember = memberService.createMember(member);
|
||||||
CreateMemberResponseDto responseDto = memberMapper.toCreateMemberResponseDto(createdMember);
|
CreateMemberResponseDto responseDto = memberMapper.toCreateMemberResponseDto(createdMember);
|
||||||
|
ApiResponseDto<CreateMemberResponseDto> apiResponse = ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_CREATED, responseDto);
|
||||||
CustomApiResponse<CreateMemberResponseDto> apiResponse = CustomApiResponse.success(ApiResponseCode.COMMON_SUCCESS_CREATED, responseDto);
|
|
||||||
|
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse);
|
return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse);
|
||||||
}
|
}
|
||||||
@@ -81,7 +78,7 @@ public class MemberController {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// @PutMapping("/member")
|
// @PutMapping("/member")
|
||||||
// public CustomApiResponse<Void> updateMember(@RequestBody @Valid CreateMemberRequestDTO requestMember, @AuthenticationPrincipal MemberDTO registrant) {
|
// public ApiResponseDto<Void> updateMember(@RequestBody @Valid CreateMemberRequestDTO requestMember, @AuthenticationPrincipal MemberDTO registrant) {
|
||||||
// // 현재 JWT는 사용자 id 값을 통하여 생성, 회원정보 변경 시 JWT 재발급 여부 검토
|
// // 현재 JWT는 사용자 id 값을 통하여 생성, 회원정보 변경 시 JWT 재발급 여부 검토
|
||||||
|
|
||||||
// MemberDTO member = mapper.map(requestMember, MemberDTO.class);
|
// MemberDTO member = mapper.map(requestMember, MemberDTO.class);
|
||||||
@@ -93,31 +90,31 @@ public class MemberController {
|
|||||||
// member.setRegSeq(registrant.getSeq());
|
// member.setRegSeq(registrant.getSeq());
|
||||||
// memberService.updateMember(member);
|
// memberService.updateMember(member);
|
||||||
|
|
||||||
// return CustomApiResponse.success(ApiResponseCode.USER_INFO_CHANGE, null);
|
// return ApiResponseDto.success(ApiResponseCode.USER_INFO_CHANGE, null);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// @DeleteMapping("/member")
|
// @DeleteMapping("/member")
|
||||||
// public CustomApiResponse<Void> deleteMember(@RequestBody @Valid CreateMemberRequestDTO requestMember){
|
// public ApiResponseDto<Void> deleteMember(@RequestBody @Valid CreateMemberRequestDTO requestMember){
|
||||||
|
|
||||||
// MemberDTO member = mapper.map(requestMember, MemberDTO.class);
|
// MemberDTO member = mapper.map(requestMember, MemberDTO.class);
|
||||||
|
|
||||||
// memberService.deleteMember(member);
|
// memberService.deleteMember(member);
|
||||||
|
|
||||||
// return CustomApiResponse.success(ApiResponseCode.USER_DELETE_SUCCESSFUL, null);
|
// return ApiResponseDto.success(ApiResponseCode.USER_DELETE_SUCCESSFUL, null);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// @PostMapping("/logout")
|
// @PostMapping("/logout")
|
||||||
// public CustomApiResponse<Void> logout(@AuthenticationPrincipal MemberDTO member) {
|
// public ApiResponseDto<Void> logout(@AuthenticationPrincipal MemberDTO member) {
|
||||||
|
|
||||||
// String id = member.getId();
|
// String id = member.getId();
|
||||||
|
|
||||||
// try {
|
// try {
|
||||||
// memberService.deleteRefreshToken(id);
|
// memberService.deleteRefreshToken(id);
|
||||||
// } catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
// return CustomApiResponse.fail(ApiResponseCode.INTERNAL_SERVER_ERROR, null);
|
// return ApiResponseDto.fail(ApiResponseCode.INTERNAL_SERVER_ERROR, null);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// return CustomApiResponse.success(ApiResponseCode.LOGOUT_SUCCESSFUL, null);
|
// return ApiResponseDto.success(ApiResponseCode.LOGOUT_SUCCESSFUL, null);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ package com.bio.bio_backend.global.config;
|
|||||||
|
|
||||||
import io.swagger.v3.oas.models.OpenAPI;
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
import io.swagger.v3.oas.models.info.Info;
|
import io.swagger.v3.oas.models.info.Info;
|
||||||
import io.swagger.v3.oas.models.info.Contact;
|
|
||||||
import io.swagger.v3.oas.models.info.License;
|
import io.swagger.v3.oas.models.info.License;
|
||||||
import io.swagger.v3.oas.models.servers.Server;
|
import io.swagger.v3.oas.models.servers.Server;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -22,10 +21,6 @@ public class SwaggerConfig {
|
|||||||
.version("v1.0.0")
|
.version("v1.0.0")
|
||||||
.license(new License()
|
.license(new License()
|
||||||
.name("STAM License")
|
.name("STAM License")
|
||||||
.url("https://stam.kr/")))
|
.url("https://stam.kr/")));
|
||||||
.servers(List.of(
|
|
||||||
new Server().url("http://localhost:8080/service").description("Local Development Server"),
|
|
||||||
new Server().url("https://api.bio.com/service").description("Production Server")
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,11 +7,10 @@ import com.bio.bio_backend.global.utils.ApiResponseCode;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
//공통 response Class
|
|
||||||
@Data
|
@Data
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
public class CustomApiResponse<T> {
|
public class ApiResponseDto<T> {
|
||||||
|
|
||||||
private int code;
|
private int code;
|
||||||
private String message;
|
private String message;
|
||||||
@@ -20,19 +19,19 @@ public class CustomApiResponse<T> {
|
|||||||
|
|
||||||
private static final int SUCCESS = 200;
|
private static final int SUCCESS = 200;
|
||||||
|
|
||||||
private CustomApiResponse(int code, String message, String description, T data){
|
private ApiResponseDto(int code, String message, String description, T data){
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> CustomApiResponse<T> success(ApiResponseCode responseCode, T data) {
|
public static <T> ApiResponseDto<T> success(ApiResponseCode responseCode, T data) {
|
||||||
return new CustomApiResponse<T>(SUCCESS, responseCode.name(), responseCode.getDescription(), data);
|
return new ApiResponseDto<T>(SUCCESS, responseCode.name(), responseCode.getDescription(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> CustomApiResponse<T> fail(ApiResponseCode responseCode, T data) {
|
public static <T> ApiResponseDto<T> fail(ApiResponseCode responseCode, T data) {
|
||||||
return new CustomApiResponse<T>(responseCode.getStatusCode(), responseCode.name(), responseCode.getDescription(), data);
|
return new ApiResponseDto<T>(responseCode.getStatusCode(), responseCode.name(), responseCode.getDescription(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -14,7 +14,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
|
import com.bio.bio_backend.global.dto.ApiResponseDto;
|
||||||
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -36,14 +36,14 @@ public class CustomAuthenticationFailureHandler implements AuthenticationFailure
|
|||||||
response.setCharacterEncoding("UTF-8");
|
response.setCharacterEncoding("UTF-8");
|
||||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||||
|
|
||||||
CustomApiResponse<String> apiResponse;
|
ApiResponseDto<String> apiResponse;
|
||||||
if (exception instanceof UsernameNotFoundException) {
|
if (exception instanceof UsernameNotFoundException) {
|
||||||
apiResponse = CustomApiResponse.fail(ApiResponseCode.USER_NOT_FOUND, null);
|
apiResponse = ApiResponseDto.fail(ApiResponseCode.USER_NOT_FOUND, null);
|
||||||
} else if (exception instanceof BadCredentialsException) {
|
} else if (exception instanceof BadCredentialsException) {
|
||||||
apiResponse = CustomApiResponse.fail(ApiResponseCode.COMMON_UNAUTHORIZED, null);
|
apiResponse = ApiResponseDto.fail(ApiResponseCode.COMMON_UNAUTHORIZED, null);
|
||||||
} else {
|
} else {
|
||||||
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||||
apiResponse = CustomApiResponse.fail(ApiResponseCode.COMMON_INTERNAL_SERVER_ERROR, null);
|
apiResponse = ApiResponseDto.fail(ApiResponseCode.COMMON_INTERNAL_SERVER_ERROR, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
String jsonResponse = objectMapper.writeValueAsString(apiResponse);
|
String jsonResponse = objectMapper.writeValueAsString(apiResponse);
|
||||||
|
@@ -1,92 +1,32 @@
|
|||||||
package com.bio.bio_backend.global.exception;
|
package com.bio.bio_backend.global.exception;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
|
||||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.bio.bio_backend.global.dto.ApiResponseDto;
|
||||||
|
|
||||||
import io.jsonwebtoken.ExpiredJwtException;
|
|
||||||
import io.jsonwebtoken.JwtException;
|
|
||||||
import io.jsonwebtoken.MalformedJwtException;
|
|
||||||
import io.jsonwebtoken.security.SignatureException;
|
|
||||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
|
|
||||||
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
@RestControllerAdvice
|
@RestControllerAdvice
|
||||||
public class GlobalExceptionHandler {
|
public class GlobalExceptionHandler {
|
||||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
|
||||||
public CustomApiResponse<Void> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
|
|
||||||
if (Objects.requireNonNull(e.getMessage()).contains("JSON parse error")) {
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_FORMAT_WRONG, null);
|
|
||||||
}
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_BAD_REQUEST, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
|
||||||
public CustomApiResponse<Void> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_METHOD_NOT_ALLOWED, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(NoResourceFoundException.class)
|
|
||||||
public CustomApiResponse<Void> handleNoResourceFoundException(NoResourceFoundException e){
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_NOT_FOUND, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(IllegalArgumentException.class)
|
|
||||||
public CustomApiResponse<Void> handleIllegalArgumentException(IllegalArgumentException e){
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_ARGUMENT_NOT_VALID, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(IndexOutOfBoundsException.class)
|
|
||||||
public CustomApiResponse<Void> handleIndexOutOfBoundsException(IndexOutOfBoundsException e){
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_INDEX_OUT_OF_BOUND, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(SignatureException.class)
|
|
||||||
public CustomApiResponse<Void> handleSignatureException(SignatureException e) {
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.JWT_SIGNATURE_MISMATCH, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(MalformedJwtException.class)
|
|
||||||
public CustomApiResponse<Void> handleMalformedJwtException(MalformedJwtException e) {
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.JWT_SIGNATURE_MISMATCH, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(JwtException.class)
|
|
||||||
public CustomApiResponse<Void> handleJwtExceptionException(JwtException e) {
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.JWT_TOKEN_NULL, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(ExpiredJwtException.class)
|
|
||||||
public CustomApiResponse<Void> handleExpiredJwtException(ExpiredJwtException e) {
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.JWT_TOKEN_EXPIRED, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(JsonProcessingException.class)
|
|
||||||
public CustomApiResponse<Void> handleExpiredJwtException(JsonProcessingException e) {
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_JSON_PROCESSING_EXCEPTION, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(ApiException.class)
|
@ExceptionHandler(ApiException.class)
|
||||||
public CustomApiResponse<Void> handleApiException(ApiException e) {
|
public ResponseEntity<ApiResponseDto<Void>> handleApiException(ApiException e) {
|
||||||
return CustomApiResponse.fail(e.getResponseCode(), null);
|
ApiResponseDto<Void> response = ApiResponseDto.fail(e.getResponseCode(), null);
|
||||||
|
return ResponseEntity.status(e.getResponseCode().getStatusCode()).body(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
public CustomApiResponse<Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
|
public ResponseEntity<ApiResponseDto<Object>> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
|
||||||
// 검증 실패한 필드들의 상세 오류 정보 추출
|
// 검증 실패한 필드들의 상세 오류 정보 추출
|
||||||
var errors = e.getBindingResult().getFieldErrors().stream()
|
var errors = e.getBindingResult().getFieldErrors().stream()
|
||||||
.map(error -> new ValidationError(error.getField(), error.getDefaultMessage()))
|
.map(error -> new ValidationError(error.getField(), error.getDefaultMessage()))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return CustomApiResponse.fail(ApiResponseCode.COMMON_ARGUMENT_NOT_VALID, errors);
|
ApiResponseDto<Object> response = ApiResponseDto.fail(ApiResponseCode.COMMON_ARGUMENT_NOT_VALID, errors);
|
||||||
|
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 검증 오류 상세 정보를 위한 내부 클래스
|
// 검증 오류 상세 정보를 위한 내부 클래스
|
||||||
|
@@ -14,7 +14,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
|
import com.bio.bio_backend.global.dto.ApiResponseDto;
|
||||||
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -35,8 +35,7 @@ public class JwtAccessDeniedHandler implements AccessDeniedHandler {
|
|||||||
} else {
|
} else {
|
||||||
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
new ObjectMapper().writeValue(response.getWriter(),
|
new ObjectMapper().writeValue(response.getWriter(), ApiResponseDto.fail(ApiResponseCode.COMMON_FORBIDDEN, null));
|
||||||
CustomApiResponse.fail(ApiResponseCode.COMMON_FORBIDDEN, null));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@ import jakarta.servlet.ServletException;
|
|||||||
import jakarta.servlet.http.Cookie;
|
import jakarta.servlet.http.Cookie;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
|
import com.bio.bio_backend.global.dto.ApiResponseDto;
|
||||||
import com.bio.bio_backend.domain.user.member.dto.LoginRequestDto;
|
import com.bio.bio_backend.domain.user.member.dto.LoginRequestDto;
|
||||||
import com.bio.bio_backend.domain.user.member.dto.LoginResponseDto;
|
import com.bio.bio_backend.domain.user.member.dto.LoginResponseDto;
|
||||||
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
|
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
|
||||||
@@ -116,6 +116,6 @@ public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilte
|
|||||||
response.setStatus(HttpStatus.OK.value());
|
response.setStatus(HttpStatus.OK.value());
|
||||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
new ObjectMapper().writeValue(response.getWriter(),
|
new ObjectMapper().writeValue(response.getWriter(),
|
||||||
CustomApiResponse.success(ApiResponseCode.LOGIN_SUCCESSFUL, memberData));
|
ApiResponseDto.success(ApiResponseCode.LOGIN_SUCCESSFUL, memberData));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,7 @@ import jakarta.servlet.FilterChain;
|
|||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import com.bio.bio_backend.global.dto.CustomApiResponse;
|
import com.bio.bio_backend.global.dto.ApiResponseDto;
|
||||||
import com.bio.bio_backend.domain.user.member.service.MemberService;
|
import com.bio.bio_backend.domain.user.member.service.MemberService;
|
||||||
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
import com.bio.bio_backend.global.utils.ApiResponseCode;
|
||||||
import com.bio.bio_backend.global.utils.JwtUtils;
|
import com.bio.bio_backend.global.utils.JwtUtils;
|
||||||
@@ -50,7 +50,7 @@ public class JwtTokenFilter extends OncePerRequestFilter {
|
|||||||
String refreshToken = jwtUtils.extractRefreshJwtFromCookie(request);
|
String refreshToken = jwtUtils.extractRefreshJwtFromCookie(request);
|
||||||
|
|
||||||
if(accessToken == null){
|
if(accessToken == null){
|
||||||
sendJsonResponse(response, CustomApiResponse.fail(ApiResponseCode.JWT_TOKEN_NULL, null));
|
sendJsonResponse(response, ApiResponseDto.fail(ApiResponseCode.JWT_TOKEN_NULL, null));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ public class JwtTokenFilter extends OncePerRequestFilter {
|
|||||||
response.setHeader("Authorization", "Bearer " + newAccessToken);
|
response.setHeader("Authorization", "Bearer " + newAccessToken);
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
} else {
|
} else {
|
||||||
sendJsonResponse(response, CustomApiResponse.fail(ApiResponseCode.ALL_TOKEN_INVALID, null));
|
sendJsonResponse(response, ApiResponseDto.fail(ApiResponseCode.ALL_TOKEN_INVALID, null));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
request.setAttribute("exception", e);
|
request.setAttribute("exception", e);
|
||||||
@@ -92,7 +92,7 @@ public class JwtTokenFilter extends OncePerRequestFilter {
|
|||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendJsonResponse(HttpServletResponse response, CustomApiResponse<?> apiResponse) throws IOException {
|
private void sendJsonResponse(HttpServletResponse response, ApiResponseDto<?> apiResponse) throws IOException {
|
||||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
response.setCharacterEncoding("UTF-8");
|
response.setCharacterEncoding("UTF-8");
|
||||||
response.setStatus(apiResponse.getCode());
|
response.setStatus(apiResponse.getCode());
|
||||||
|
Reference in New Issue
Block a user