[Study-4주차] MapStruct, Exception 적용 + CRUD 수정 + Controller 수정 + ResponseFormat - ②

2023. 4. 15. 17:11· Study/Pet-Clinic-Project
목차
  1. ResponseFormat
  2. Exception
  3. Controller
728x90

 

[Study-4주차] MapStruct, Exception 적용 + CRUD 수정 + Controller 수정 + ResponseFormat - ①

 

[Study-4주차] MapStruct, Exception 적용 + CRUD 수정 - ①

[Study-3주차] PetClinicProject CRUD - ② [Study-3주차] PetClinicProject CRUD - ② [Study-3주차] PetClinicProject CRUD - ① [Study-3주차] PetClinicProject CRUD - ① [Study-2주차] PetClinicProject 초기 설정 + 클래스 생성 + 코드 설

soohykeee.tistory.com

 


 

이번에는 Exception 적용과 Controller 수정, Controller에서 사용할 ResponseEntity를 커스텀한 ResponseFormat, ReponseStatus를 사용해볼 것이다.

 

ResponseFormat

해당 코드를 보기 전, ResponseEntity에 대해 먼저 알아보는 것이 좋다.

[Study] ResponseEntity 란 무엇인가?

 

[Study] ResponseEntity 란 무엇인가?

[개념] REST, REST API, RESTful 이란 무엇인가? [개념] REST, REST API, RESTful 이란 무엇인가? REST란 ? REST란 Representational State Tranfer의 약자로, 자원을 이름으로 구분하여 해당 자원의 상태(정보)를 주고받는

soohykeee.tistory.com

 


 

package kr.co.jshpetclinicstudy.infra.model;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ResponseFormat<T> {

    private boolean isSuccessful;

    private Optional<T> data;

    private String message;

    private HttpStatus statusCode;

    // Success - If the ResponseStatus is declared + return Only Message
    public static <T> ResponseFormat<T> success(ResponseStatus responseStatus) {
        return ResponseFormat.<T>builder()
                .isSuccessful(true)
                .data(Optional.empty())
                .message(responseStatus.getMessage())
                .statusCode(responseStatus.getStatusCode())
                .build();
    }

    // Success - If the ResponseStatus is Not declared + return Only Message
    public static <T> ResponseFormat<T> success(String message,
                                                HttpStatus httpStatus) {
        return ResponseFormat.<T>builder()
                .isSuccessful(true)
                .data(Optional.empty())
                .message(message)
                .statusCode(httpStatus)
                .build();
    }

    // Success - If the ResponseStatus is declared + return Message And Data
    public static <T> ResponseFormat<T> successWithData(ResponseStatus responseStatus,
                                                        T data) {
        return ResponseFormat.<T>builder()
                .isSuccessful(true)
                .data(Optional.ofNullable(data))
                .message(responseStatus.getMessage())
                .statusCode(responseStatus.getStatusCode())
                .build();
    }

    // Success - If the ResponseStatus is Not declared + return Message And Data
    public static <T> ResponseFormat<T> successWithData(String message,
                                                        HttpStatus httpStatus,
                                                        T data) {
        return ResponseFormat.<T>builder()
                .isSuccessful(true)
                .data(Optional.ofNullable(data))
                .message(message)
                .statusCode(httpStatus)
                .build();
    }

    // Failed - If the ResponseStatus is declared
    public static <T> ResponseFormat<T> error(ResponseStatus responseStatus) {
        return ResponseFormat.<T>builder()
                .isSuccessful(false)
                .data(Optional.empty())
                .message(responseStatus.getMessage())
                .statusCode(responseStatus.getStatusCode())
                .build();
    }

    // Failed - If the ResponseStatus is Not declared
    public static <T> ResponseFormat<T> error(String message,
                                                HttpStatus httpStatus) {
        return ResponseFormat.<T>builder()
                .isSuccessful(false)
                .data(Optional.empty())
                .message(message)
                .statusCode(httpStatus)
                .build();
    }

}

 

package kr.co.jshpetclinicstudy.infra.model;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum ResponseStatus {

    // Success Status
    SUCCESS_OK("요청이 성공적으로 처리되었습니다.", HttpStatus.OK),
    SUCCESS_CREATE("요청이 성공적으로 처리되어 새로운 리소스가 생성되었습니다.", HttpStatus.CREATED),
    SUCCESS_ACCEPTED("요청이 성공적으로 처리되었지만, 결과가 아직 완료되지 않았습니다.", HttpStatus.ACCEPTED),
    SUCCESS_NO_CONTENT("요청이 성공적으로 처리되었지만, 응답 데이터가 없습니다.", HttpStatus.NO_CONTENT),

    // Failed Status
    FAIL_BAD_REQUEST("클라이언트의 요청이 잘못되었습니다.", HttpStatus.BAD_REQUEST),
    FAIL_UNAUTHORIZED("클라이언트가 인증되지 않았습니다.", HttpStatus.UNAUTHORIZED),
    FAIL_FORBIDDEN("클라이언트가 요청한 리소스에 접근할 권한이 없습니다.", HttpStatus.FORBIDDEN),
    FAIL_NOT_FOUND("클라이언트가 요청한 리소스를 찾을 수 없습니다.", HttpStatus.NOT_FOUND),
    FAIL_METHOD_NOT_ALLOWED("클라이언트가 요청한 HTTP 메소드가 허용되지 않았습니다.", HttpStatus.METHOD_NOT_ALLOWED),

    // Owner Failed Status
    FAIL_TELEPHONE_DUPLICATED("클라이언트의 전화번호가 중복되었습니다.", HttpStatus.BAD_REQUEST);

    private String message;

    private HttpStatus statusCode;
}

 


 

Exception

package kr.co.jshpetclinicstudy.infra.exception;

public class BusinessLogicException extends RuntimeException {

    private ResponseStatus responseStatus;

    public BusinessLogicException(ResponseStatus responseStatus) {
        super(responseStatus.getMessage());
        this.responseStatus = responseStatus;
    }

    public BusinessLogicException(String message) {
        super(message);
    }
}
package kr.co.jshpetclinicstudy.infra.exception;


/**
 * 이미 존재하는 리소스를 생성하려 할 때 사용하는 예외
 */
public class DuplicatedException extends BusinessLogicException {

    public DuplicatedException(ResponseStatus responseStatus) {
        super(responseStatus);
    }

    public DuplicatedException(String message) {
        super(message);
    }
}
package kr.co.jshpetclinicstudy.infra.exception;

/**
 * 인증된 사용자가 권한이 없는 리소스에 접근하려 할 때 사용하는 예외
 */
public class ForbiddenException extends BusinessLogicException {

    public ForbiddenException(ResponseStatus responseStatus) {
        super(responseStatus);
    }

    public ForbiddenException(String message) {
        super(message);
    }
}
package kr.co.jshpetclinicstudy.infra.exception;

/**
 * 클라이언트의 요청이 잘못되었을 때 사용하는 예외
 */
public class InvalidRequestException extends BusinessLogicException {

    public InvalidRequestException(ResponseStatus responseStatus) {
        super(responseStatus);
    }

    public InvalidRequestException(String message) {
        super(message);
    }
}
package kr.co.jshpetclinicstudy.infra.exception;

/**
 * 요청한 리소스가 존재하지 않을 때 사용하는 예외
 */
public class NotFoundException extends BusinessLogicException{

    public NotFoundException(ResponseStatus responseStatus) {
        super(responseStatus);
    }

    public NotFoundException(String message) {
        super(message);
    }
}
package kr.co.jshpetclinicstudy.infra.exception;

/**
 * 인증되지 않은 사용자가 보호된 리소스에 접근하려 할 때 사용하는 예외
 */
public class UnauthorizedException extends BusinessLogicException {

    public UnauthorizedException(ResponseStatus responseStatus) {
        super(responseStatus);
    }

    public UnauthorizedException(String message) {
        super(message);
    }
}

 


 

Controller

OwnerController

package kr.co.jshpetclinicstudy.controller;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/owners")
public class OwnerController {

    private final OwnerService ownerService;

    /**
     * Create Owner API
     *
     * @param create
     * @return
     */
    @PostMapping
    public ResponseFormat<Void> createOwner(@RequestBody @Valid OwnerRequestDto.CREATE create){
        try {
            ownerService.createOwner(create);
            return ResponseFormat.success(ResponseStatus.SUCCESS_CREATE);
        } catch (DuplicatedException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_TELEPHONE_DUPLICATED);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

    /**
     * Read(Get) Owner API
     *
     * @param ownerId
     * @return
     */
    @GetMapping("/{owner_id}")
    public ResponseFormat<OwnerResponseDto.READ> getOwner(@PathVariable(name = "owner_id") Long ownerId) {
        try {
            return ResponseFormat.successWithData(ResponseStatus.SUCCESS_OK, ownerService.getOwner(ownerId));
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

    /**
     * Update Owner API
     *
     * @param update
     * @return
     */
    @PutMapping
    public ResponseFormat<Void> updateOwner(@RequestBody @Valid OwnerRequestDto.UPDATE update) {
        try {
            ownerService.updateOwner(update);
            return ResponseFormat.success(ResponseStatus.SUCCESS_NO_CONTENT);
        } catch (DuplicatedException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_TELEPHONE_DUPLICATED);
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }

    }

    /**
     * Delete Owner API
     *
     * @param ownerId
     * @return
     */
    @DeleteMapping("/{owner_id}")
    public ResponseFormat<Void> deleteOwner(@PathVariable(name = "owner_id") Long ownerId) {

        try {
            ownerService.deleteOwner(ownerId);
            return ResponseFormat.success(ResponseStatus.SUCCESS_NO_CONTENT);
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

}

 

 

PetController

package kr.co.jshpetclinicstudy.controller;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/pets")
public class PetController {

    private final PetService petService;

    /**
     * Create Pet API
     *
     * @param create
     * @return
     */
    @PostMapping
    public ResponseFormat<Void> createPet(@RequestBody @Valid PetRequestDto.CREATE create) {
        try {
            petService.createPet(create);
            return ResponseFormat.success(ResponseStatus.SUCCESS_CREATE);
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

    /**
     * Read(Get) Pet API
     *
     * @param petId
     * @return
     */
    @GetMapping("/{pet_id}")
    public ResponseFormat<PetResponseDto.READ> getPet(@PathVariable(name = "pet_id") Long petId) {
        try {
            return ResponseFormat.successWithData(ResponseStatus.SUCCESS_OK, petService.getPet(petId));
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

    /**
     * Read(Get) PetList Of Owner API
     *
     * @param ownerId
     * @return
     */
    @GetMapping("/owner/{owner_id}")
    public ResponseFormat<List<PetResponseDto.READ>> getPetListOfOwner(@PathVariable(name = "owner_id") Long ownerId) {
        try {
            return ResponseFormat.successWithData(ResponseStatus.SUCCESS_OK, petService.getPetListOfOwner(ownerId));
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

    /**
     * Update Pet API
     *
     * @param update
     * @return
     */
    @PutMapping
    public ResponseFormat<Void> updatePet(@RequestBody @Valid PetRequestDto.UPDATE update) {
        try {
            petService.updatePet(update);
            return ResponseFormat.success(ResponseStatus.SUCCESS_NO_CONTENT);
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

    /**
     * Delete Pet API
     *
     * @param petId
     * @return
     */
    @DeleteMapping("/{pet_id}")
    public ResponseFormat<Void> deletePet(@PathVariable(name = "pet_id") Long petId) {
        try {
            petService.deletePet(petId);
            return ResponseFormat.success(ResponseStatus.SUCCESS_NO_CONTENT);
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

}

 

VetController

package kr.co.jshpetclinicstudy.controller;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/vets")
public class VetController {

    private final VetService vetService;

    /**
     * Create Vet + Specialty API
     *
     * @param create
     * @return
     */
    @PostMapping
    public ResponseFormat<Void> createVet(@RequestBody @Valid VetRequestDto.CREATE create) {
        try {
            vetService.createVet(create);
            return ResponseFormat.success(ResponseStatus.SUCCESS_CREATE);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }

    }

    /**
     * Get Vet API
     *
     * @param vetId
     * @return
     */
    @GetMapping("/{vet_id}")
    public ResponseFormat<VetResponseDto.READ> getVet(@PathVariable(name = "vet_id") Long vetId) {
        try {
            return ResponseFormat.successWithData(ResponseStatus.SUCCESS_OK, vetService.getVet(vetId));
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

    /**
     * Update Vet API
     *
     * @param update
     * @return
     */
    @PutMapping
    public ResponseFormat<Void> updateVet(@RequestBody @Valid VetRequestDto.UPDATE update) {
        try {
            vetService.updateVet(update);
            return ResponseFormat.success(ResponseStatus.SUCCESS_NO_CONTENT);
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

    /**
     * Delete Vet API
     *
     * @param vetId
     * @return
     */
    @DeleteMapping("/{vet_id}")
    public ResponseFormat<Void> deleteVet(@PathVariable(name = "vet_id") Long vetId) {
        try {
            vetService.deleteVet(vetId);
            return ResponseFormat.success(ResponseStatus.SUCCESS_NO_CONTENT);
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

}

 

VisitController

package kr.co.jshpetclinicstudy.controller;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/visits")
public class VisitController {

    private final VisitService visitService;

    /**
     * Create Visit API
     *
     * @param create
     * @return
     */
    @PostMapping
    public ResponseFormat<Void> createVisit(@RequestBody @Valid VisitRequestDto.CREATE create) {
        try {
            visitService.createVisit(create);
            return ResponseFormat.success(ResponseStatus.SUCCESS_CREATE);
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }


    /**
     * Read(Get) Visit API
     *
     * @param visitId
     * @return
     */
    @GetMapping("/{visit_id}")
    public ResponseFormat<VisitResponseDto.READ> getVisit(@PathVariable(name = "visit_id") Long visitId) {
        try {
            return ResponseFormat.successWithData(ResponseStatus.SUCCESS_OK, visitService.getVisit(visitId));
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

    /**
     * Read(Get) VisitList Of Pet API
     *
     * @param petId
     * @return
     */
    @GetMapping("/pets/{pet_id}")
    public ResponseFormat<List<VisitResponseDto.READ>> getVisitListOfPet(@PathVariable(name = "pet_id") Long petId) {
        try {
            return ResponseFormat.successWithData(ResponseStatus.SUCCESS_OK, visitService.getVisitListOfPet(petId));
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

    /**
     * Update Visit API
     *
     * @param update
     * @return
     */
    @PutMapping
    public ResponseFormat<Void> updateVisit(@RequestBody @Valid VisitRequestDto.UPDATE update) {
        try {
            visitService.updateVisit(update);
            return ResponseFormat.success(ResponseStatus.SUCCESS_NO_CONTENT);
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }

    /**
     * Delete Visit API
     *
     * @param visitId
     * @return
     */
    @DeleteMapping("/{visit_id}")
    public ResponseFormat<Void> deleteVisit(@PathVariable(name = "visit_id") Long visitId) {
        try {
            visitService.deleteVisit(visitId);
            return ResponseFormat.success(ResponseStatus.SUCCESS_NO_CONTENT);
        } catch (NotFoundException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_NOT_FOUND);
        } catch (RuntimeException e) {
            return ResponseFormat.error(ResponseStatus.FAIL_BAD_REQUEST);
        }
    }
}

 

 


 

728x90
저작자표시 (새창열림)
  1. ResponseFormat
  2. Exception
  3. Controller
'Study/Pet-Clinic-Project' 카테고리의 다른 글
  • [Study-6, 7주차] AOP + QueryDSL + (N+1) 문제 및 RequestDTO 수정 + JPA Auditing 사용 (regDate, modDate) - ①
  • [Study-5주차] @Query + 조회 기능 (PostMan) + 연관 관계 추가(Visit-Vet) + 더미 테스트 코드
  • [Study-4주차] MapStruct, Exception 적용 + CRUD 수정 + Controller 수정 + ResponseFormat - ①
  • [Study-3주차] PetClinicProject CRUD - ②
soohykeee
soohykeee
Computer Science. 2017~2023 / Java, Spring, Backend
soohykeee
Coding_
soohykeee
전체
오늘
어제
  • 분류 전체보기
    • 회고
    • Info
      • 개념 정리
      • 정보
    • Study
      • Pet-Clinic-Project
      • Concept
    • Inflearn
      • 스프링 핵심 원리_기본편
      • Git
    • 코드로 배우는 스프링 부트 웹 프로젝트
      • Guestbook
      • MovieReview
      • Security & API

블로그 메뉴

  • 홈
  • 방명록
  • Github

인기 글

최근 댓글

최근 글

250x250
hELLO · Designed By 정상우.v4.2.1
soohykeee
[Study-4주차] MapStruct, Exception 적용 + CRUD 수정 + Controller 수정 + ResponseFormat - ②
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.