스프링수업 7일차
한 일
RESTful 웹 프로젝트
- start spring을 통해 프로젝트 생성하기
- GET 유저 조회하기
- POST 새 유저 생성하기
- PUT 유저정보 업데이트하기
- DELETE 유저 삭제하기
pma 프로젝트에 rest api적용하기 -1-
- GET으로 직원 검색하기
- POST로 새 직원 입력하기
RESTful 웹 프로젝트
start spring을 통해 프로젝트 생성하기
https://start.spring.io/
위 링크를 통해 프로젝트 생성.
이후 생성하기 진행 > 생성된 압축파일을 워크스페이스로 옮겨 압축풀기
프로젝트 파일 불러오기로 열기
실행 시 출력되는 페이지.
spring-boot-devtools 추가. 빠른 사용에 도움을 줌.
GET 유저 조회하기
새 클래스 생성
- UserController -
@RestController
@RequestMapping("/users") // http://localhost:8080/users
public class UserController {
@GetMapping
public String getUser() {
return "유저 리스트 리턴";
}
@PostMapping
public String getCreaterUser() {
return "새 유저를 생성";
}
@PutMapping
public String getUpdateUser() {
return "유저 업데이트";
}
@DeleteMapping
public String geDeletetUser() {
return "유저 삭제";
}
}
postman에 http://localhost:8080/users 로 접속해 결과확인
GET
POST
PUT
DELETE
@PathVariable으로 path변수 사용하기
- UserController -
getUser, getUserList 로수정 (문자열 기준)
@GetMapping
public String getUserList() {
return "유저 리스트 리턴";
}
@GetMapping(path = "/{userId}")
public String getUser(@PathVariable("userId") String userId) {
return "유저 리스트 중 하나 " + userId;
}
id를 숫자로 받을 경우 아래처럼 수정
@GetMapping(path = "/{userId}")
public String getUser(@PathVariable("userId") int userId) {
return "유저 리스트 중 하나 " + userId;
}
http://localhost:8080/users/0829kuj 의 결과.
쿼리 스트링으로 입력하기
유저의 수가 많을때 일일히 request방식으로 받아오면 비효율적임.
최소page와 최대limit을 쿼리스트링으로 주소에 추가하여 요청.
- UserController -
@GetMapping
public String getUserList(@RequestParam("page") int page, @RequestParam("limit") int limit) {
return "유저 리스트 리턴 페이지: "+ page + ", limit : " + limit;
}
http://localhost:8080/users?page=1&limit=10
정상응답.
parameter없이 http://localhost:8080/users 로 요청 시 에러발생.
defaultValue(기본값)를 설정하여 에러를 방지.
- UserController -
// 효율적으로 DB를 사용하기 위해 페이지 수와 한 페이지 당 가져올 데이터수를 지정
@GetMapping
public String getUserList(@RequestParam(value= "page", defaultValue = "1") int page,
@RequestParam(value = "limit", defaultValue = "50") int limit,
@RequestParam(value = "sort", defaultValue = "desc", required = false) String sort) {
return "유저 리스트 리턴 페이지: "+ page + ", limit : " + limit + ", 정렬 : " + sort;
}
sort의 required = false 는 이 속성이 없어도 에러가 발생하지 않도록하는 설정.
defaultValue값을 설정해주지 않았다면 if (sort == null) sort = "DESC"; 를 넣어 기본값을 따로 작성해줘야하지만 여기서는 넣어줬으니 필요없음.
http://localhost:8080/users
수정 전 요청시 에러발생
defaultValue 추가 후 접근 시 에러발생x
java 객체로 리턴받기
새 클래스 생성
- UserRest클래스 -
public class UserRest {
private String name;
private String email;
private String userId;
// get/set 자동생성
}
- UserController -
@GetMapping(path = "/{userId}")
public UserRest getUser(@PathVariable("userId") String id) {
// java 객체 유저를 리턴
UserRest returnUser = new UserRest();
returnUser.setName("홍");
returnUser.setUserId(id);
returnUser.setEmail("[email protected]");
// 객체로 리턴 시 RestController에서 json으로 리턴
return returnUser;
}
http://localhost:8080/users/ 뒤에 id를 입력 후 요청하면 입력된 홍길동의 정보가 json으로 리턴됨.
=> 자바객체로 리턴 시 자동으로 json타입으로 response됨.
xml로 리턴받기
링크 에서 2.13.2버전 사용
- pom.xml -
spring이 자동관리하도록 version삭제 > pom.xml에 추가 > 메이븐 업데이트
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
- UserController -
@GetMapping(path = "/{userId}", produces = {MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE})
public UserRest getUser(@PathVariable("userId") String id) {
// java 객체 유저를 리턴
UserRest returnUser = new UserRest();
returnUser.setName("홍");
returnUser.setUserId(id);
returnUser.setEmail("[email protected]");
// 객체로 리턴 시 RestController에서 json으로 리턴
return returnUser;
}
여기서 mediaType은 org.springframework.http.MediaType이니 import시 주의.
produces속성을 추가하여 미디어타입을 지정.
xml과 json을 모두 리턴할 수 있도록 해줌.
재시작 후 확인.
Header의 Accept 설정을 application/xml 로 바꾼 후 재확인.
xml로 리턴됨을 확인가능.
HTTP 상태코드
http상태코드를 함께 리턴하기.
http상태코드: 200번대 - 정상응답, 400번대 - 요청오류, 500번대 - 서버오류
- UserController -
@GetMapping(path = "/{userId}", produces = {MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<UserRest> getUser(@PathVariable("userId") String id) {
// java 객체 유저를 리턴
UserRest returnUser = new UserRest();
returnUser.setName("홍");
returnUser.setUserId(id);
returnUser.setEmail("[email protected]");
// 객체로 리턴 시 RestController에서 json으로 리턴
return new ResponseEntity<UserRest>(returnUser, HttpStatus.BAD_REQUEST);
}
@GetMapping("/bad")
public ResponseEntity<String> badRequest() {
return new ResponseEntity<String>("잘못된 요청", HttpStatus.BAD_REQUEST);
}
BAD_REQUEST를 OK로 바꿨을때도 확인해보기
POST 새 유저 생성하기
새 클래스 생성
- UserRequest -
public class UserRequest {
private String name;
private String email;
private String password;
//getset 자동생성
}
- UserController -
@PostMapping
public String getCreaterUser(@RequestBody UserRequest user) {
return "새 유저를 생성";
}
@RequestBody: 실제 요청시의 데이터
post로 데이터가 전달되는지 확인
- UserController -
@PostMapping
public ResponseEntity<UserRest> getCreaterUser(@RequestBody UserRequest user) {
UserRest returnUser = new UserRest();
returnUser.setName(user.getName());
returnUser.setEmail(user.getEmail());
return new ResponseEntity<UserRest>(returnUser, HttpStatus.CREATED);
}
요청성공 시 화면.
데이터 검증 Validating Request Body
POST로 입력받은 값 검증하기
라이브러리 다운 pom.xml에 추가.
이전과 마찬가지로 spring이 자동관리하도록 version태그는 삭제.
- UserController -
@PostMapping
public ResponseEntity<UserRest> getCreaterUser(@Valid @RequestBody UserRequest user) {
UserRest returnUser = new UserRest();
returnUser.setName(user.getName());
returnUser.setEmail(user.getEmail());
return new ResponseEntity<UserRest>(returnUser, HttpStatus.CREATED);
}
@Valid로 userRequest로 들어오는 user의 유효성을 검사
- UserRequest클래스 -
@NotBlank(message="이름을 입력해주세요")
private String name;
@NotBlank(message="이메일을 입력해주세요")
@Email
private String email;
@NotNull(message = "패스워드를 입력해주세요")
@Size(min = 4, max = 10, message = "패스워드의 길이는 4 ~ 10 사이입니다")
private String password;
어노테이션으로 유효성 설정
재시작 후 확인. (maven을 수동으로 추가했을땐 재시작 후 확인해야 변경사항이 적용됨)
유효성에 어긋나는 요청 시 에러와 함께 설정한 메시지가 출력됨.
정상요청의 경우 상단의 유효성 적용 전 결과와 동일하므로 생략.
userId 자동생성해서 저장하기
우선 DB를 사용하지 않고 리스트로 생성하여 저장.
- UserController -
@PostMapping
public ResponseEntity<UserRest> getCreaterUser(@Valid @RequestBody UserRequest user) {
UserRest returnUser = new UserRest();
returnUser.setName(user.getName());
returnUser.setEmail(user.getEmail());
String userId = UUID.randomUUID().toString(); // 랜덤한 고유id를 만듦
returnUser.setUserId(userId);
if (users == null) users = new HashMap<>(); // 싱클톤 패턴. 선언된 map <문자열, UserRest>가 없으면 새로생성
users.put(userId, returnUser); // map이므로 (유저id, 유저객체) 를 한쌍으로 입력
return new ResponseEntity<UserRest>(returnUser, HttpStatus.CREATED);
}
post를 통해 새 유저를 생성 시 랜덤하게 생성된 userId가 함께 저장됨.
- UserController -
userId로 유저를 찾아 리턴, 없을 시 없음을 알리도록 수정.
@GetMapping(path = "/{userId}", produces = {MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<UserRest> getUser(@PathVariable("userId") String id) {
// java 객체 유저를 리턴
if (users.containsKey(id)) {
return new ResponseEntity<UserRest>(users.get(id), HttpStatus.OK);
} else { // userId가 없음을 알림
return new ResponseEntity<UserRest>(HttpStatus.NO_CONTENT);
}
앞서 만든 유저의 id를 get으로 요청하면 정상적으로 해당 유저의 정보가 출력됨.
없는 id로 요청 시 NO_CONTENT로 지정해뒀으므로 아무 정보도 나타나지 않음.
리스트로 저장했기때문에 서버를 내리면 생성한 유저가 초기화되므로 테스트 시 주의.
PUT 유저정보 업데이트하기
새 클래스 생성
- UpdateUserRequest -
public class UpdateUserRequest {
// 유저 객체에서 email을 제외한 name만 업데이트
@Size(min = 2, message = "이름의 길이는 2자 이상")
private String name;
// getset 자동생성
}
- UserController -
// 업데이트 시 id를 입력 후 body에 업데이트 할 이름을 json으로 입력함
@PutMapping("/{userId}")
public UserRest getUpdateUser(@PathVariable("userId") String id,
@Valid @RequestBody UpdateUserRequest user) {
UserRest savedUser = users.get(id);
savedUser.setName(user.getName()); // 이름 수정됨
return savedUser;
}
입력한 userId로 유저를 찾은 후
@Valid로 유효성을 검증,
검증을 마친 name을 @RequestBody로 내용을 넣어 업데이트한다.
DELETE 유저 삭제하기
- UserController -
@DeleteMapping("/{userId}")
public ResponseEntity<Void> geDeletetUser(@PathVariable("userId") String id) {
users.remove(id);
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
}
새 유저 생성 후 생성된 id로 delete요청 > 삭제 후 GET으로 id를 검색해보면 no content로 뜨는것을 확인할 수 있음.
pma 프로젝트에 rest api적용하기 -1-
GET으로 직원 검색하기
새 클래스, 패키지 생성
- EmployeeApiController -
@RestController
@RequestMapping("/app-api/employees")
public class EmployeeApiController {
@Autowired
private EmployeeRepository empRepo;
@GetMapping
public Iterable<Employee> getEmployees(){
return empRepo.findAll();
}
}
- Employee -
무한반복 방지를 위해 @JsonIgnore추가
// N:N 관계에서는 테이블을 만들어 만든 테이블에 id를 넣고 다른 테이블의 id도 입력한다.
// CascadeType.PERSIST, CascadeType.REMOVE 제거
@ManyToMany(cascade = {CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH}, fetch = FetchType.LAZY)
@JoinTable(name = "project_employee", joinColumns = @JoinColumn(name="employee_id"),
inverseJoinColumns = @JoinColumn(name="project_id"))
@JsonIgnore // 이게 없으면 무한으로 서로 검색해서 호출함
private List<Project> projects;
http://localhost:8080/app-api/employees 로 실행시 모든 직원들의 명단이 json으로 출력됨.
- EmployeeApiController -
id로 직원을 찾는 메서드 추가
@GetMapping("/{id}")
public Employee getEmployeeById(@PathVariable("id") Long id){
return empRepo.findByEmployeeId(id);
}
http://localhost:8080/app-api/employees/1 검색 시 해당 id의 직원정보가 json으로 출력됨.
POST로 새 직원 입력하기
- EmployeeApiController -
// 요청하는 body에 json타입의 새 직원 데이터를 입력 시 새 직원 생성 후 그 직원을 리턴
@PostMapping(consumes = "application/json")
@ResponseStatus(HttpStatus.CREATED) // 상태 201 생성
public Employee create(@RequestBody Employee employee){
return empRepo.save(employee);
}
postman으로 입력 테스트 하기전, csrf설정을 끔
- SecurityConfiguration -
@Override
protected void configure(HttpSecurity http) throws Exception {
...
http.csrf().disable(); // REST API에서는 csrf설정을 끔
}
테스트 시 새 직원을 생성 후 그 직원의 데이터를 리턴함.
생성된 employeeId로 검색해보면 같은 결과가 나옴.
여기서는 없는 id로 저장을 요청했기 때문에 새 직원이 저장된 것.
(이전 수업에서 empRepo.save(employee)시 id를 검색해 있으면 update작업을, 없으면 save로 새 직원을 만드는 작업을 하도록 작성하였음.)
Author And Source
이 문제에 관하여(스프링수업 7일차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@0829kuj/스프링수업-7일차저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)