요절복통 블로그 API 만들기 기본
데이터 검증-1
팁: 3번이상 반복작업 = 잘못하고 있나?
if(result.hasErrors()){
List<FieldError> fieldErrors = result.getFieldErrors();
FieldError firstFieldError = fieldErrors.get(0);
String fieldName = firstFieldError.getField(); // title
String errorMessage = firstFieldError.getDefaultMessage(); //..에러메시지
Map<String, String> error = new HashMap<>();
error.put(fieldName, errorMessage);
return error;
}
.andExpect(jsonPath("$.title").value("타이틀을 입력해주세요."))
https://ykh6242.tistory.com/entry/MockMvc%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-REST-API%EC%9D%98-Json-Response-%EA%B2%80%EC%A6%9D
데이터 검증-2
@ControllerAdvice
https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
Binding Result 삭제
일단 400 => 이후에는 뭐 다른걸로
오류 정하는법
/**
* {
* "code" : "400",
* "message": "잘못된 요청입니다.",
* "validation":{
* "title": "값을 입력해주세요"
* }
* }
*/
public class ErrorResponse {
private final String code;
private final String message;
}
요런 느낌으로 개선해 보자
private Map<String, String> validation = new HashMap<>();
public void addValidation(String fieldName, String errorMessage) {
ValidationTuple tuple = new ValidationTuple(fieldName, errorMessage);
this.validation.put(fieldName, errorMessage);
}
@RequiredArgsConstructor
private class ValidationTuple{
private final String fieldName;
private final String errorMessage;
}
문제가 있다.
변경의 여지가 너무 많다.
작성글 저장 1 - 게시글 저장 구현
작성글 저장 2 - 클래스 분리
ObjectMapper objectMapper = new ObjectMapper();
String s = objectMapper.writeValueAsString(request);
순서 바꾸면 망한다.
@Builder
public PostCreate(String title, String content) {
this.title = title;
this.content = content;
}
public PostCreate changeTitle(String title){
return PostCreate.builder()
.title(title)
.content(this.content)
.build();
}
게시글 조회 2 - 응답 클래스 분리
게시글 조회 3 - 게시글 여러개 조회
게시글 조회 4 - 페이징 처리
게시글 조회 5 - 페이징 처리 (QueryDSL)
implementation "com.querydsl:querydsl-core"
implementation "com.querydsl:querydsl-jpa"
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa" // querydsl JPAAnnotationProcessor 사용 지정
annotationProcessor "jakarta.persistence:jakarta.persistence-api" // java.lang.NoClassDefFoundError(javax.annotation.Entity) 발생 대응
annotationProcessor "jakarta.annotation:jakarta.annotation-api" // java.lang.NoClassDefFoundError (javax.annotation.Generated) 발생 대응
변경사항 :
화면과 내 테스트 케이스 변수가 다름.
반포자이 -> foo, bar
게시글 수정
파라미터가 많아 질수 잇다.
문제점이 있다.
if(postEdit.getTitle() != null){
editorBuilder.title(postEdit.getTitle());
}
if(postEdit.getContent() != null){
editorBuilder.content(postEdit.getContent());
}
PostEditor postEditor = editorBuilder.build();
@Builder
public PostEditor(String title, String content) {
this.title = title != null ? title : this.title;
this.content = content != null ? content : this.content;
}
오류&해결 : jakson 생성자 오류남. 그래서 객체 수정
@Setter
@Getter
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class PostEdit {
@NotBlank(message = "타이틀을 입력하세요.")
private String title;
@NotBlank(message="콘텐츠를 입력해주세요.")
private String content;
@Builder
public PostEdit(String title, String content) {
this.title = title;
this.content = content;
}
}
org.springframework.http.converter.HttpMessageConversionException
nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of 'PostEdit'
(no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
예외처리1
상수로 만들어서 양쪽에 적용되게 했었다.
예외처리2
@JsonInclude(value=JsonInclude.Include.NON_EMPTY)
선호하지 않는 이유 :
비어있음으로 유추 가능하다.
수십 가지로 늘어남
향후를 대비하면 int로 해두는게 좋다.
스프링에서 제공해주는 것은 저렇게 따로 만든다.
비즈니스용은 하나의 메소드에서 따로
이렇게 꺼내오고 검증하는거 하지마
if 문이 많아 질수 있다.
오류발생:
@DisplayName("/posts 요청시 title값은 필수다.")
해결 :
ErrorResponse response = ErrorResponse.builder()
.code("400")
.message("잘못된 요청입니다.")
.validation(new HashMap<>())
.build();
문서화





