Java Spring_API-GET/POST/PUT/DELETE
- API : 클라이언트가 정한대로 서버에게 요청(Request)을 보내면,
서버가 요구사항을 처리하여 응답(Response)을 반환합니다. - REST : 주소에 명사, 요청 방식에 동사를 사용함으로써 의도를 명확히 드러냄을 의미합니다.
동사는 CRUD를 지칭한다.
CRUD 란 : 정보관리의 기본 기능
: 생성 (Create)→ 조회 (Read)→ 변경 (Update)→ 삭제 (Delete)
REST : A에 대해 생성(POST)/조회(GET)/수정(PUT)/삭제(DELETE) 요청을 하는 것
예시)
GET /courses → 강의 전체 목록 조회 요청
GET /courses/1 → ID가 1번인 녀석 조회 요청
POST /courses → 강의 생성 요청
PUT /courses/3 → ID가 3번인 녀석 수정 요청
DELETE /courses/2 → ID 2번인 녀석 삭제 요청
API - GET (조회)
1) controller 패키지 -> CourseController.java클래스 생성하기
코드 입력
@RequiredArgsConstructor // final -> @RequiredArgsConstructor 입력
@RestController // json 으로 응답해야하니까
public class CourseController {
// CourseRepository를 멤버변수로 하자 꼭 필요하니까 final
private final CourseRepository courseRepository;
@GetMapping("/api/courses")
public List<Course> getCourses() {
return courseRepository.findAll();
}
}
2) 결과 확인
ARC 프로그램으로 확인해보자
Advanced REST Client (다운로드 링크)
API - POST (생성)
1. GET에서 생성한 CourseController.java 클래스에 아래 코드 삽입
- @PostMapping("/api/courses") : 괄호 안의 주소로 오면 아래 메소드가 실행된다.
- 아래 생성한 public Course createCourse()는 기본적으로 생성한 Course를 반환한다.
- createCourse(@RequestBody CourseRequestDto requestDto) 괄호 안의 내용
: 정보를 몰고다니는 CourseRequestDto 랑 같은 형태로 정보를 받는다. 반드시 @RequestBody 어노테이션을 작성해주어야 한다.
*Spring은 요청을 주고 받는 방식을 강제한다.
Post/Put이나 데이터를 주고 받을 때 API단에서 넘어오는 데이터를 잘 받으려면
RequestBody 형태로 받아줘야한다.
private final CourseService courseService;
// PostMapping을 통해서, 같은 주소라도 방식이 다름을 구분합니다.
@PostMapping("/api/courses")
public Course createCourse(@RequestBody CourseRequestDto requestDto) {
// requestDto 는, 생성 요청을 의미합니다.
// 강의 정보를 만들기 위해서는 강의 제목과 튜터 이름이 필요하잖아요?
// 그 정보를 가져오는 녀석입니다.
// 저장하는 것은 Dto가 아니라 Course이니, Dto의 정보를 course에 담아야 합니다.
// 잠시 뒤 새로운 생성자를 만듭니다.
Course course = new Course(requestDto);
// JPA를 이용하여 DB에 저장하고, 그 결과를 반환합니다.
return courseRepository.save(course);
}
2. Course course = new Course(requestDto); 이부분의 오류
: Course 클래스에 requestDto 파라미터로 받는 생성자가 아직 안만들어져 있기 때문이다.
controller 패키지의 CourseController.java 안에 아래 코드를 작성해주자.
# CourseController.java
public Course(CourseRequestDto requestDto){
this.title = requestDto.getTitle();
this.tutor = requestDto.getTutor();
}
3. 결과 확인하기
1) Application 실행 후 ARC 프로그램에서 GET요청
2) POST 요청하면 에러가 난다,,?! Bad Request
=> POST 는 요청하는 방식이 정해져있는데 안지켜서 그렇다.
*해결 방법
: Spring POST방식에서 데이터를 전달하는 방식은 엄격하게 정해져 있기에 룰을 암기해야한다
1. HEADERS 탭 -> ADD 누르고 -> Name : Content-Type / Value : application/json 으로 설정해준다.
2. BODY 탭 -> input 창에 다음과 같이 작성한다.
작성 형식
{
"key1값": "value1값",
"key2값": "value2값"
}
3. 다시 POST 요청을 한다. 결과 확인
API - PUT (수정)
1. 다음 코드를 controller 패키지의 CourseController.java 에 추가한다.
- @PutMapping("/api/courses/{id}") : api course에 ID 값 넣어서 수정요청이 오면
- 아래에 있는 public Long updateCourse() 라는 메소드를 실행해라
* { } 중괄호 안에는 변수명, 변형되는 값이 들어간다
* @PathVariable 어노테이션을 써야 변수명을 가져다 쓸 수 있다.
- 메서드 역할 : 아이디와 변경할 데이터를 가져오면 return 변경한 다음 id 값을 돌려주겠다
@PutMapping("/api/courses/{id}")
public Long updateCourse(@PathVariable Long id, @RequestBody CourseRequestDto requestDto) {
return courseService.update(id, requestDto);
}
작성했으면 Application 을 실행 시킨다.
2. ARC 로 PUT 요청 해보기
1) 먼저 ARC로 GET 요청을 한다.
2) PUT으로 변경하고 주소 courses 뒤에 /1 입력한다.
HEADERS : Name : Content-Type / Value : application/json 설정
3) BODY 탭에 수정할 내용 입력 -> SEND 클릭
* 결과
return 으로
return courseService.update(id, requestDto);
id 값을 돌려줬기 때문에 1이 출력됐다.
다시 결과를 확인하기 위해 GET요청을 한다.
* 이때 courses뒤에 /1 은 지워준다.
내용이 바뀐걸 확인했다.
API - Delete (삭제)
아래 코드를 controller 패키지의 CourseController.java 맨 아래 붙여 넣는다. - 끝
@DeleteMapping("/api/courses/{id}")
public Long deletCourse(@PathVariable Long id) {
// 쿼리를 날리는 부분 : repository
courseRepository.deleteById(id);
return id;
}
완성코드 접은 글
<application.properties>
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testdb
spring.jpa.show-sql=true
Week02Application
package com.sparta.week02;
import com.sparta.week02.Service.CourseService;
import com.sparta.week02.domain.Course;
import com.sparta.week02.domain.CourseRepository;
import com.sparta.week02.domain.CourseRequestDto;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import java.util.List;
@EnableJpaAuditing
@SpringBootApplication
public class Week02Application {
public static void main(String[] args) {
SpringApplication.run(Week02Application.class, args);
}
// Week02Application.java 의 main 함수 아래에 붙여주세요.
@Bean
public CommandLineRunner demo(CourseRepository courseRepository, CourseService courseService) {
return (args) -> {
courseRepository.save(new Course("프론트엔드의 꽃, 리액트", "고로케"));
System.out.println("데이터 인쇄");
List<Course> courseList = courseRepository.findAll();
for (int i = 0; i < courseList.size(); i++) {
Course course = courseList.get(i);
System.out.println(course.getId());
System.out.println(course.getTitle());
System.out.println(course.getTutor());
}
CourseRequestDto requestDto = new CourseRequestDto("웹개발의 봄, Spring", "무야호");
courseService.update(1L, requestDto);
courseList = courseRepository.findAll();
for (int i = 0; i < courseList.size(); i++) {
Course course = courseList.get(i);
System.out.println(course.getId());
System.out.println(course.getTitle());
System.out.println(course.getTutor());
}
};
}
}
Service 패키지
>CourseService.java
package com.sparta.week02.Service;
import com.sparta.week02.domain.Course;
import com.sparta.week02.domain.CourseRepository;
import com.sparta.week02.domain.CourseRequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
@RequiredArgsConstructor
@Service // 스프링에게 이 클래스는 서비스임을 명시
public class CourseService {
// final: 서비스에게 꼭 필요한 녀석임을 명시
private final CourseRepository courseRepository;
@Transactional // SQL 쿼리가 일어나야 함을 스프링에게 알려줌
public Long update(Long id, CourseRequestDto requestDto) {
Course course1 = courseRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException("해당 아이디가 존재하지 않습니다.")
);
course1.update(requestDto);
return course1.getId();
}
}
domain 패키지
>Course
package com.sparta.week02.domain;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Getter
@NoArgsConstructor // 기본생성자를 대신 생성해줍니다.
@Entity // 테이블임을 나타냅니다.
public class Course extends Timestamped {
@Id // ID 값, Primary Key로 사용하겠다는 뜻입니다.
@GeneratedValue(strategy = GenerationType.AUTO) // 자동 증가 명령입니다.
private Long id;
@Column(nullable = false) // 컬럼 값이고 반드시 값이 존재해야 함을 나타냅니다.
private String title;
@Column(nullable = false)
private String tutor;
public Course(CourseRequestDto requestDto) {
this.title = requestDto.getTitle();
this.tutor = requestDto.getTutor();
}
public Course(String title, String tutor) {
this.title = title;
this.tutor = tutor;
}
public void update(CourseRequestDto requestDto) {
this.title = requestDto.getTitle();
this.tutor = requestDto.getTutor();
}
}
domain 패키지
>CourseRepository 인터페이스
package com.sparta.week02.domain;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@RequiredArgsConstructor
public class CourseRequestDto {
private final String title;
private final String tutor;
}
domain 패키지
>CourseRequestDto.java 클래스
package com.sparta.week02.domain;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@RequiredArgsConstructor
public class CourseRequestDto {
private final String title;
private final String tutor;
}
domain 패키지
> Timestamped.java 클래스
package com.sparta.week02.domain;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@MappedSuperclass // 상속했을 때, 컬럼으로 인식하게 합니다.
@EntityListeners(AuditingEntityListener.class) // 생성/수정 시간을 자동으로 반영하도록 설정
public class Timestamped {
@CreatedDate // 생성일자임을 나타냅니다.
private LocalDateTime createdAt;
@LastModifiedDate // 마지막 수정일자임을 나타냅니다.
private LocalDateTime modifiedAt;
}
controller 패키지
>CourseeController.java 클래스
package com.sparta.week02.controller;
import com.sparta.week02.Service.CourseService;
import com.sparta.week02.domain.Course;
import com.sparta.week02.domain.CourseRepository;
import com.sparta.week02.domain.CourseRequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequiredArgsConstructor // final -> @RequiredArgsConstructor 입력
@RestController // json 으로 응답해야하니까
public class CourseController {
private final CourseService courseService;
// PostMapping을 통해서, 같은 주소라도 방식이 다름을 구분합니다.
@PostMapping("/api/courses")
public Course createCourse(@RequestBody CourseRequestDto requestDto) {
// requestDto 는, 생성 요청을 의미합니다.
// 강의 정보를 만들기 위해서는 강의 제목과 튜터 이름이 필요하잖아요?
// 그 정보를 가져오는 녀석입니다.
// 저장하는 것은 Dto가 아니라 Course이니, Dto의 정보를 course에 담아야 합니다.
// 잠시 뒤 새로운 생성자를 만듭니다.
Course course = new Course(requestDto);
// JPA를 이용하여 DB에 저장하고, 그 결과를 반환합니다.
return courseRepository.save(course);
}
// CourseRepository를 멤버변수로 하자 꼭 필요하니까 final
private final CourseRepository courseRepository;
@GetMapping("/api/courses")
public List<Course> getCourses() {
return courseRepository.findAll();
}
@PutMapping("/api/courses/{id}")
public Long updateCourse(@PathVariable Long id, @RequestBody CourseRequestDto requestDto) {
return courseService.update(id, requestDto);
}
@DeleteMapping("/api/courses/{id}")
public Long deletCourse(@PathVariable Long id) {
// 쿼리를 날리는 부분 : repository
courseRepository.deleteById(id);
return id;
}
}
'Java, IntelliJ > Spring' 카테고리의 다른 글
[Spring]Thymeleaf Js내부에서 사용하기, 로그인 여부에 따라 보이기 (0) | 2021.07.06 |
---|---|
Spring_CRUD할 수 있는 API 연습 (0) | 2021.06.27 |
Java/intelliJ Lombok, DTO 사용법 (2) | 2021.06.26 |
Java JPA /Timestamped/service/update/delete 사용법 (0) | 2021.06.26 |
Java Spring H2 Console 사용법 (0) | 2021.06.26 |
댓글