domain 패키지 생성
request 와 response 시 json 으로 데이터를 주고 받게 되는데 java에는 json 이라는 데이터 타입이 없다. 그래서 json과 매핑할 수 있는 객체를 생성하는데 그것을 VO 혹은 DTO 라고 한다. VO는 Virtual Object 그리고, DTO는 Data Transfer Object라고 모두 데이터를 담기 위한 객체이다. json과 java 객체 간의 매핑은 jackson 매퍼라는 3rd party 라이브러리가 수행해준다.
앞에서 생성한 board 테이블의 데이터를 저장할 VO 객체를 생성한다.
domain 패키지를 추가하고 BoardVO 객체를 생성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.eastflag.fullstack.domain; import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Data; @JsonInclude(JsonInclude.Include.NON_NULL) @Data public class BoardVO { private Integer id; private String title; private String content; private String created; private String updated; } |
@JsonInclude(JsonInclude.Include.NON_NULL) 의 의미는 not_null 인 경우만 포함한다는 의미이므로 json을 만들때 property가 null이면 만들지 말라는 의미이다.
@Data 는 lombok에서 제공해주는 어노테이션으로 setter 와 getter를 자동으로 생성해준다.
insert나 update 시에는 쿼리 결과만을 리턴해야 할 필요가 있으므로 처리 결과를 리턴할 ResultVO 객체를 추가한다.
1 2 3 4 5 6 7 8 9 10 11 |
package com.eastflag.fullstack.domain; import lombok.AllArgsConstructor; import lombok.Data; @AllArgsConstructor @Data public class ResultVO { private Integer code; private String message; } |
@AllArgsConstructor 어노테이션은 모든 프라퍼티를 포함한 생성자를 생성해준다. 그래서 인스턴스를 생성시 new ResultVO(0, “success”); 이렇게 사용할 수가 있게 된다.
persistence 레이어 생성
Control 레이어에서 request를 받은 다음에 바로 응답을 주는것이 아니라 DB를 조회해야 하므로 DB 처리를 담당할 persistence 레이어를 생성한다.
persistence 패키지를 생성하고 BoardMapper 인터페이스를 생성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.eastflag.fullstack.persistence; import com.eastflag.fullstack.domain.BoardVO; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; @Mapper public interface BoardMapper { @Insert({"<script>", "INSERT INTO board(title, content)", "VALUES(#{title}, #{content})", "</script>"}) int insertBoard(BoardVO boardVO); } |
insertBoard 메서드는 입력을 객체로 받고 출력은 int로 리턴한다. 입력이 성공하면 1이 리턴되고 실패하면 0이 리턴되기 때문이다.
xml 구문없이 자바에서 MyBatis 구문을 사용하기 위해서는 <script> 태그를 사용하면 된다. @Mapper 어노테이션을 사용하게 되면 스프링이 구동시 해당 인터페이스가 인스턴스로 스프링에 등록되게 된다. 문법적으로 인터페이스가 인스턴스를 생성하는게 맞지 않지만 내부적으로 익명클래스 인스턴스로 생성이 된다고 이해하면되겠다.
Controller 생성
이제 입력을 처리할 컨트롤러를 생성한다. 좀전에 생성한 Mapper 인스턴스를 @Autowired를 이용하여 주입(Dependancy Injection)하게 되면 IDEA에서 노란줄 경고가 보일것이다. @Autowired로 주입 받게될 경우 상호 의존성 에러가 발생할 수 있으므로 생성자 주입을 받아야 한다. 그래서 boardMapper를 final로 만들고 생성자 주입은 @RequiredArgsConstructor로 생성자 주입을 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.eastflag.fullstack.controller; import com.eastflag.fullstack.domain.BoardVO; import com.eastflag.fullstack.domain.ResultVO; import com.eastflag.fullstack.persistence.BoardMapper; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequiredArgsConstructor @RestController @RequestMapping("/api") public class BoardController { private final BoardMapper boardMapper; @PostMapping("/board") public ResultVO addBoard(@RequestBody BoardVO boardVO) { int result = boardMapper.insertBoard(boardVO); if (result > 0) { return new ResultVO(0, "success"); } else { return new ResultVO(100, "fail"); } } } |
board 테이블을 생성할것이므로 post 매핑을 사용하였고, RestController 바로 아래에 /api가 매핑되어있으므로 전체 매핑 유알엘은 /api/board 이다. 요청은 Json으로 받고 결과는 ResultVO 타입의 json을 리턴한다. 다시 요약하자면, REST API 규격은 유알엘이 /api/board 이고 메서드는 post 이며 json으로 데이터를 받아서 json을 리턴한다.
프로젝트 구조는 아래와 같다.
Test
서버를 재시작하고 postman으로 테스트한 결과는 다음과 같다.