Skip to content

Commit

Permalink
[Feat] BeanValid Exception 기능 추가 & Swagger API 명세 작성
Browse files Browse the repository at this point in the history
  • Loading branch information
jiyunio committed May 13, 2024
1 parent dc2705f commit 4cdadcf
Show file tree
Hide file tree
Showing 16 changed files with 97 additions and 85 deletions.
8 changes: 3 additions & 5 deletions src/main/java/com/jiyunio/todolist/ResponseDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
@Getter
@Setter
public class ResponseDTO {
Long id;
String userId;
String result;
String msg;

@Builder
ResponseDTO(Long id, String userId, String msg) {
this.id = id;
this.userId = userId;
ResponseDTO(String result, String msg) {
this.result = result;
this.msg = msg;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.jiyunio.todolist.category;

import com.jiyunio.todolist.ResponseDTO;
import jakarta.validation.Valid;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
Expand All @@ -13,11 +15,14 @@

@RestController
@RequiredArgsConstructor
@Validated
@Tag(name = "Category", description = "카테고리 API")
public class CategoryController {
private final CategoryService categoryService;

@PostMapping("/category{memberId}")
public ResponseEntity<ResponseDTO> createCategory(@PathVariable Long memberId, @Validated @RequestParam @NotBlank String categoryName) {
@Operation(summary = "카테고리 생성")
public ResponseEntity<ResponseDTO> createCategory(@Parameter(description = "member의 id") @PathVariable Long memberId, @RequestParam @NotBlank String categoryName) {
categoryService.createCategory(memberId, categoryName);
ResponseDTO responseDTO = ResponseDTO.builder()
.msg("카테고리 생성 성공")
Expand All @@ -26,12 +31,14 @@ public ResponseEntity<ResponseDTO> createCategory(@PathVariable Long memberId, @
}

@GetMapping("/category/{memberId}")
public List<GetCategoryDTO> getCategory(@PathVariable Long memberId) {
@Operation(summary = "카테고리 조회")
public List<GetCategoryDTO> getCategory(@Parameter(description = "member의 id") @PathVariable Long memberId) {
return categoryService.getCategory(memberId);
}

@PutMapping("/category/{categoryId}")
public ResponseEntity<ResponseDTO> updateCategory(@PathVariable Long categoryId, @RequestParam @NotBlank String categoryName) {
@Operation(summary = "카테고리 수정")
public ResponseEntity<ResponseDTO> updateCategory(@Parameter(description = "카테고리의 id") @PathVariable Long categoryId, @RequestParam @NotBlank String categoryName) {
categoryService.updateCategory(categoryId, categoryName);
ResponseDTO responseDTO = ResponseDTO.builder()
.msg("카테고리 수정 성공")
Expand All @@ -40,7 +47,8 @@ public ResponseEntity<ResponseDTO> updateCategory(@PathVariable Long categoryId,
}

@DeleteMapping("/category/{categoryId}")
public ResponseEntity<ResponseDTO> deleteCategory(@PathVariable Long categoryId) {
@Operation(summary = "카테고리 삭제")
public ResponseEntity<ResponseDTO> deleteCategory(@Parameter(description = "카테고리의 id") @PathVariable Long categoryId) {
categoryService.deleteCategory(categoryId);
ResponseDTO responseDTO = ResponseDTO.builder()
.msg("카테고리 삭제 성공")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.jiyunio.todolist.category;

import com.jiyunio.todolist.member.Member;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Schema(description = "카테고리 조회")
public class GetCategoryDTO {
private String category;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.jiyunio.todolist.customError;

import lombok.*;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
public class CustomException extends RuntimeException {
private final HttpStatus httpStatus;
private final ErrorCode errorCode;

public CustomException(HttpStatus httpStatus, ErrorCode errorCode){
public CustomException(HttpStatus httpStatus, ErrorCode errorCode) {
this.httpStatus = httpStatus;
this.errorCode = errorCode;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
package com.jiyunio.todolist.customError;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.ArrayList;
import java.util.List;

@ControllerAdvice
public class CustomExceptionHandler {
@ExceptionHandler(CustomException.class)
protected ResponseEntity<ErrorDTO> handleCustomException(CustomException e){
protected ResponseEntity<ErrorDTO> handleCustomException(CustomException e) {
return ErrorDTO.toResponseEntity(e);
}

@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<List<ErrorDTO>> beanValidationException(MethodArgumentNotValidException e) {
List<FieldError> list = e.getBindingResult().getFieldErrors();
List<ErrorDTO> responseDTOList = new ArrayList<>();

for (FieldError error : list) {
ErrorDTO errorDTO = ErrorDTO.builder()
.code("400_Bad_Request")
.msg(error.getDefaultMessage())
.build();

responseDTOList.add(errorDTO);
}
return new ResponseEntity<>(responseDTOList, HttpStatus.BAD_REQUEST);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package com.jiyunio.todolist.customError;

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
Expand Down
52 changes: 14 additions & 38 deletions src/main/java/com/jiyunio/todolist/member/MemberController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,44 @@
import com.jiyunio.todolist.member.dto.ChangeUserPwDTO;
import com.jiyunio.todolist.member.dto.SignInDTO;
import com.jiyunio.todolist.member.dto.SignUpDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequiredArgsConstructor
@Tag(name = "Member", description = "회원 API")
public class MemberController {
private final MemberService memberService;

@PostMapping("/signUp")
public ResponseEntity<?> signUp(@Valid @RequestBody SignUpDTO signUpDto, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
List<ResponseDTO> responseDTOList = returnBindingResult(bindingResult);
return new ResponseEntity<>(responseDTOList, HttpStatus.BAD_REQUEST);
}

@Operation(summary = "회원가입", description = "아이디, 비밀번호, 이메일 이용\n\n 아이디 : 5 ~ 10자 \n\n 비밀번호: 8~16자의 영문 대/소문자, 숫자, 특수문자")
public ResponseEntity<?> signUp(@Valid @RequestBody SignUpDTO signUpDto) {
ResponseDTO responseDTO = ResponseDTO.builder()
.userId(memberService.signUp(signUpDto)) // 화면에 "ㅇㅇ님 환영합니다" 글씨 원함
.result(memberService.signUp(signUpDto)) // 화면에 "ㅇㅇ님 환영합니다" 글씨 원함
.msg("회원가입 성공")
.build();
return new ResponseEntity<>(responseDTO, HttpStatus.CREATED);
}

@PostMapping("/signIn")
public ResponseEntity<?> signIn(@Valid @RequestBody SignInDTO signInDto, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
List<ResponseDTO> responseDTOList = returnBindingResult(bindingResult);
return new ResponseEntity<>(responseDTOList, HttpStatus.BAD_REQUEST);
}

@Operation(summary = "로그인", description = "아이디와 비밀번호 이용")
public ResponseEntity<?> signIn(@Valid @RequestBody SignInDTO signInDto) {
ResponseDTO responseDTO = ResponseDTO.builder()
.userId(memberService.signIn(signInDto)) // 로그인하면 회원 페이지에 ㅇㅇ님 원함
.result(memberService.signIn(signInDto)) // 로그인하면 회원 페이지에 ㅇㅇ님 원함
.msg("로그인 성공")
.build();
return ResponseEntity.ok(responseDTO);
}

@PutMapping("/{id}/update")
public ResponseEntity<?> updateUserPw(@PathVariable Long id, @Valid @RequestBody ChangeUserPwDTO changeUserPwDto, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
List<ResponseDTO> responseDTOList = returnBindingResult(bindingResult);
return new ResponseEntity<>(responseDTOList, HttpStatus.BAD_REQUEST);
}

@Operation(summary = "회원 비밀번호 수정", description = "비밀번호, 수정 비밀번호 이용")
public ResponseEntity<?> updateUserPw(@Parameter(description = "member의 id") @PathVariable Long id, @Valid @RequestBody ChangeUserPwDTO changeUserPwDto) {
memberService.updateUserPw(id, changeUserPwDto);
ResponseDTO responseDTO = ResponseDTO.builder()
.msg("비밀번호 변경 성공")
Expand All @@ -63,23 +50,12 @@ public ResponseEntity<?> updateUserPw(@PathVariable Long id, @Valid @RequestBody
}

@DeleteMapping("/{id}/delete")
public ResponseEntity<ResponseDTO> deleteMember(@PathVariable Long id, @RequestParam String userPw) {
@Operation(summary = "회원 탈퇴", description = "비밀번호 이용")
public ResponseEntity<ResponseDTO> deleteMember(@Parameter(description = "member의 id") @PathVariable Long id, @RequestParam String userPw) {
memberService.deleteMember(id, userPw);
ResponseDTO responseDTO = ResponseDTO.builder()
.msg("회원 탈퇴 성공")
.build();
return new ResponseEntity<>(responseDTO, HttpStatus.NO_CONTENT);
}

public List<ResponseDTO> returnBindingResult(BindingResult bindingResult) {
List<FieldError> list = bindingResult.getFieldErrors();
List<ResponseDTO> responseDTOList = new ArrayList<>();
for (FieldError error : list) {
ResponseDTO responseDTO = ResponseDTO.builder()
.msg(error.getDefaultMessage())
.build();
responseDTOList.add(responseDTO);
}
return responseDTOList;
}
}
7 changes: 4 additions & 3 deletions src/main/java/com/jiyunio/todolist/member/MemberService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.jiyunio.todolist.member.dto.ChangeUserPwDTO;
import com.jiyunio.todolist.member.dto.SignInDTO;
import com.jiyunio.todolist.member.dto.SignUpDTO;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
Expand All @@ -14,7 +15,7 @@
public class MemberService {
private final MemberRepository memberRepository;

public String signUp(SignUpDTO signUpDto) {
public String signUp(@Valid SignUpDTO signUpDto) {
if (memberRepository.existsByUserEmail(signUpDto.getUserEmail())) {
// 이미 존재하는 이메일
throw new CustomException(HttpStatus.BAD_REQUEST, ErrorCode.EXIST_EMAIL);
Expand All @@ -39,7 +40,7 @@ public String signUp(SignUpDTO signUpDto) {
throw new CustomException(HttpStatus.BAD_REQUEST, ErrorCode.NOT_SAME_CONFIRM_PASSWORD);
}

public String signIn(SignInDTO signInDto) {
public String signIn(@Valid SignInDTO signInDto) {
if (memberRepository.existsByUserId(signInDto.getUserId())) {
Member member = memberRepository.findByUserId(signInDto.getUserId()).get();
if (member.getUserPw().equals(signInDto.getUserPw())) {
Expand All @@ -53,7 +54,7 @@ public String signIn(SignInDTO signInDto) {
throw new CustomException(HttpStatus.NOT_FOUND, ErrorCode.WRONG_USERID_PASSWORD);
}

public void updateUserPw(Long id, ChangeUserPwDTO changeUserPwDto) {
public void updateUserPw(Long id, @Valid ChangeUserPwDTO changeUserPwDto) {
Member member = memberRepository.findById(id).get();
if (member.getUserPw().equals(changeUserPwDto.getUserPw())) { // 회원 비밀번호 확인
if (changeUserPwDto.getChangePw().equals(changeUserPwDto.getConfirmChangePw())) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
package com.jiyunio.todolist.member.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Schema(description = "회원 비밀번호 수정")
public class ChangeUserPwDTO {
@NotBlank(message = "비밀번호를 입력하세요.")
@Schema(description = "회원 비밀번호")
private String userPw;

@NotBlank(message = "변경 비밀번호를 입력하세요.")
@Pattern(regexp = "(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,16}")
@Schema(description = "회원 수정 비밀번호", example = "qwer1234!")
private String changePw;

@NotBlank(message = "확인 비밀번호를 입력하세요.")
@Schema(description = "회원 수정 확인 비밀번호")
private String confirmChangePw;
}
3 changes: 3 additions & 0 deletions src/main/java/com/jiyunio/todolist/member/dto/SignInDTO.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.jiyunio.todolist.member.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
Expand All @@ -8,8 +9,10 @@
@Setter
public class SignInDTO {
@NotBlank(message = "아이디를 입력하세요.")
@Schema(example = "qwe123")
private String userId;

@NotBlank(message = "비밀번호를 입력하세요.")
@Schema(example = "qwer1234!")
private String userPw;
}
7 changes: 6 additions & 1 deletion src/main/java/com/jiyunio/todolist/member/dto/SignUpDTO.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.jiyunio.todolist.member.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
Expand All @@ -8,17 +9,21 @@

@Getter
@Setter
@Schema(description = "회원가입")
public class SignUpDTO {

@NotBlank(message = "아이디를 입력하세요.")
@Pattern(regexp = "(?=.*[a-zA-Z])(?=\\S+$).{5,10}", message = "아이디 : 5~10자")
@Schema(description = "회원의 userId : 영문 대/소문자 5~10자", example = "qwe123")
private String userId;

@NotBlank(message = "비밀번호를 입력하세요.")
@Pattern(regexp = "(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,16}", message = "비밀번호: 8~16자의 영문 대/소문자, 숫자, 특수문자를 사용하십쇼.")
@Schema(description = "회원의 비밀번호 : 8~16자의 영문 대/소문자, 숫자, 특수문자", example = "qwer123!")
private String userPw;

@NotBlank(message = "이메일를 입력하세요.")
@Email(message = "이메일 형식이 맞지 않습니다.")
@Schema(description = "회원의 이메일", example = "qwer@google.com")
private String userEmail;

@NotBlank(message = "확인 비밀번호를 입력하세요.")
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/jiyunio/todolist/todo/Todo.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class Todo {
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "memberId")
@JoinColumn(name = "member Id")
private Member member;

@Lob // 길이 제한 X
Expand Down
Loading

0 comments on commit 4cdadcf

Please sign in to comment.