Replies: 3 comments
-
저는 아래와 같은 포멧을 주로 사용합니다!
이렇게 사용하게 된다면 성공하게 된다면 클라이언트에서 response만 바라보면 되고, 실패하게 된다면 error만 바라보면 되기 때문에 간편했어요 :) 저의 ApiUtil은 아래와 같아요! public class APIUtils {
public static <T> ResponseEntity<ApiResult<T>> result(boolean success, T response, HttpStatus status) {
return new ResponseEntity<>(new ApiResult<>(success, response, null), status);
}
public static ResponseEntity<ApiResult<ApiError>> error(CustomException exception) {
return new ResponseEntity<>(
new ApiResult<>(false, null, new ApiError(exception))
, exception.getErrorCode().getStatus());
}
@Getter
@Setter
public static class ApiResult<T> {
private boolean success;
private T response;
private ApiError error;
public ApiResult(boolean success, T response, ApiError error) {
this.success = success;
this.response = response;
this.error = error;
}
public ApiResult() {
}
}
@Getter
@Setter
public static class ApiError {
private String code;
private String message;
public ApiError(String code, String message) {
this.code = code;
this.message = message;
}
public ApiError() {
}
public ApiError(ErrorCode code) {
this(code.getCode(), code.getMessage());
}
public ApiError(CustomException exception) {
this(exception.getErrorCode());
}
}
} |
Beta Was this translation helpful? Give feedback.
0 replies
-
Controller@GetMapping("/recruitments/{recruitmentId}")
public RecruitmentDetailsResponse readRecruitmentDetails(@PathVariable("recruitmentId") final Long recruitmentId) {
return recruitmentDetailsFindService.findRecruitmentDetails(recruitmentId);
}
@GetMapping("/recruitments/popular")
public PopularRecruitmentsResponse readPopularRecruitments(@ModelAttribute PopularRecruitmentCond request) {
return popularRecruitmentsFindService.findPopularRecruitments(request);
}
@PostMapping("/studies/{studyId}/recruitments")
public RecruitmentDetailsResponse write(@PathVariable("studyId") final Long studyId, @RequestBody final WriteRecruitmentRequest request, @Parameter(hidden = true) @AuthUser final User user) {
return recruitmentService.write(user, request, studyId);
} ResponseBodyAdvice
@Component
@RestControllerAdvice
public final class CommonResponseAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(final MethodParameter returnType, final Class<? extends HttpMessageConverter<?>> converterType) {
return converterType.isAssignableFrom(MappingJackson2HttpMessageConverter.class);
}
@SneakyThrows
@Override
public Object beforeBodyWrite(Object body, final MethodParameter returnType, final MediaType selectedContentType, final Class<? extends HttpMessageConverter<?>> selectedConverterType, final ServerHttpRequest request, final ServerHttpResponse response)
{
final DataFieldName annotation = returnType.getMethodAnnotation(DataFieldName.class);
body = (annotation != null) ? CommonResponse.success(annotation.value(), body) : CommonResponse.success(body);
return body;
} ExceptionHandler
@Component
@RestControllerAdvice
public final class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public ResponseEntity<CommonResponse> handleException(Exception e) {
return toResponseEntity(e, e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
} |
Beta Was this translation helpful? Give feedback.
0 replies
-
24-08-12 회의 내용입니다. API 응답 모델1. 컨트롤러 반환 타입
2. POST
3. CSR vs SSR 기준이 모호함
4. ProblemDetail (RFC 9457)
결론1. 컨트롤러에서는 ResponseEntity를 반환한다.2. 예외가 발생하면 ProblemDetail을 활용한다.3. 성공: 2xx + ApiResponse / 실패: 4xx + ProblemDetail(+errorCode)로 세부 명시ex) 예시
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
API를 구현하면서 공통된 응답을 위해 모델을 만들 필요가 생겼습니다. 따라서 하단의 클래스를 만들었습니다.
이 구조는 컨트롤러에서 body에
ApiResponse
를 담아서 응답하는 구조입니다. 예외 발생시 ApiResponse.error(ErrorCode)를 호출하게 됩니다.모든 API에 공통되는 모델이므로 팀 내에서 합의가 필요할 것 같습니다. 의견있으시면 자유롭게 공유해주세요.
Beta Was this translation helpful? Give feedback.
All reactions