[등록 API 만들기]

API를 만들기 위한 클래스
- Request 데이터를 받을 Dto
- API 요청을 받을 Controller
- 트랜잭션, 도메인 기능간의 순서를 보장하는 Service(비지니스 로직 처리 x)

Spring 웹 계층
1. Web Layer
- 컨트롤러와 JSP등의 뷰 템플릿 영역
- 필터, 인터셉터등 외부 요청과 응답에 대한 전반적인 영역

2. Service Layer
- @Service에 사용되는 서비스 영역
- Controller와 Dao의 중간 영역에서 사용
- @Transactonal이 사용되어야 하는 영역

3. Repository Layer
- Database와 같이 데이터 저장소에 접근하는 영역
- Dao영역

4. Dtos
- 계층간에 데이터 교환을 위한 객체
- 뷰에서 사용될 객체나 Repository Layer에서 결과로 넘겨준 객체 

5. Domain Model
- 비지니스 처리를 담당하는 곳
- 도메인이라 불리는 개발 대상을 모든사람이 동일한 관점에서 이해할 수 있고 공유할 수 있도록 단순화 시킨 것
- @Entity가 사용된 영역 역시 도메인 모델
src/main/java/com/intellij/project/springboot/web/PostsApiController

@RequiredArgsConstructor
@RestController
public class PostsApiController {

    private final PostsService postsService;

    @PostMapping("/api/v1/posts")
    public Long save(@RequestBody PostsSaveRequestDto requestDto){
        return postsService.save(requestDto);
    }
}
src/main/java/com/intellij/project/springboot/service/PostsService

@RequiredArgsConstructor
@Service
public class PostsService {
    private final PostsRepository postsRepository;

    @Transactional
    public Long save(PostsSaveRequestDto requestDto) {
        return postsRepository.save(requestDto.toEntity()).getId();
    }
}
- @Autowired로 Bean을 주입받지 않고 생성자로 주입받는다.
- @RequiredArgsConstructor
	- final이 선언된 모든 필드를 인자값으로 하는 생성자를 생성해줌
	- 해당 클래스의 의존성 관계가 변경될 때마다 생성자 코드를 수정 안해줘도 됨
src/main/java/com/intellij/project/springboot/dto/PostsSaveRequestDto

@Getter
@NoArgsConstructor
public class PostsSaveRequestDto {
    private String title;
    private String content;
    private String author;

    @Builder
    public PostsSaveRequestDto(String title, String content, String author) {
        this.title = title;
        this.content = content;
        this.author = author;
    }

    public Posts toEntity(){

        return Posts.builder().title(title).content(content).author(author).build();
    }
}
- Entity와 매우 유사한 클래스지만 따로 생성
- Entity 클래스는 DB와 맞닿아 있는 핵심 클래스 이기 때문에 Request/Response 클래서 사용하면 안됨
src/test/java/com/intellij/project/springboot/web/PostsApiControllerTest

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PostsApiControllerTest {

    @LocalServerPort
    private int port;

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private PostsRepository postsRepository;

    @After
    public void tearDown() throws Exception {
        postsRepository.deleteAll();
    }

    @Test
    public void Posts_등록된다() throws Exception {

        //given
        String title = "title";
        String content = "content";
        PostsSaveRequestDto requestDto = PostsSaveRequestDto.builder().title(title).content(content).author("author").build();

        String url = "http://localhost:"+port+"/api/v1/posts";

        //when
        ResponseEntity<Long> responseEntity = restTemplate.postForEntity(url,requestDto, Long.class);

        //then
        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(responseEntity.getBody()).isGreaterThan(0L);

        List<Posts> all = postsRepository.findAll();
        assertThat(all.get(0).getTitle()).isEqualTo(title);
        assertThat(all.get(0).getContent()).isEqualTo(content);

    }
}
- insert 테스트 클래스
profile
개발이좋아요

0개의 댓글

Powered by GraphCDN, the GraphQL CDN