스프링수업 6일차
한 일
- 업데이트, 삭제, 유효성 검사 기능 추가
- REST란?
- 포스트맨 사용하기
업데이트, 삭제 기능 추가
기능을 추가할때 허가가 걸려있으면 불편하므로 관리자에게만 허가하는 부분 주석처리.
업데이트
이대로도 새로 저장은 되지만 그대로 두면 참여중인 프로젝트까지 모두 초기화되어 새로저장되는 문제가 생긴다.
예 - 직원 '강감찬'의 정보를 수정 > 강감찬이 참여하고있던 프로젝트가 0개가 되어버림
- EmployeeController -
@GetMapping("/new")
public String newEmployeeForm(Model model) {
Employee e = new Employee();
model.addAttribute("employee", e);
return "employees/new-employee";
}
@PostMapping("/save")
public String createEmployee(Employee employee) {
Long id = employee.getEmployeeId();
if (id != null) {
employeeService.update(employee);
} else {
employeeService.save(employee);
}
return "redirect:/employees/"; //post-redirect-get 패턴
}
- new-employee.html -
form태그 내부에 hidden type의 input태그로 id값을 넘겨줌
<input type="hidden" th:field="*{employeeId}" />
- EmployeeService -
클래스 내부에 업데이트 기능의 새 메서드 생성
public void update(Employee employee) {
// 실제 DB에서 업데이트할 직원객체를 불러옴
Employee emp = employeeRepository.findByEmployeeId(employee.getEmployeeId());
// 필요한 내용만 업데이트
emp.setFirstName(employee.getFirstName());
emp.setLastName(employee.getLastName());
emp.setEmail(employee.getEmail());
employeeRepository.save(emp);
}
=> input태그로 받아온 id값을 /save에서 검사,
id가 있으면 employeeService.update(employee)를 통해 업데이트 작업을,
id가 null이면 employeeService.save(employee)을 통해 새 직원을 입력하는 작업을 한다.
update(Employee employee)에서는 직원객체를 불러온 후 특정 내용만 업데이트하므로 다른 값을 가져온 그대로 유지된다.
id객체를 선언할 때 사용한 Long타입은 int, long타입과는 달리 클래스타입이므로 null값이 들어갈 수 있음.
수정 이후에도 참여중인 프로젝트까지 유지됨.
Validation 설정과 검사
새 직원 or 직원 업데이트시 입력한 이름, 이메일 등의 유효성을 스프링에서 검사하도록 어노테이션을 통해 설정함.
pom.xml에 validation 추가
- Employee -
@Id //기본키를 명시
@GeneratedValue(strategy = GenerationType.IDENTITY) // Id를 자동생성
private Long employeeId;
@NotBlank(message="이름을 입력해주세요")
@Size(min=1, max=20, message="이름은 1에서 20자 사이입니다.")
private String firstName;
@NotBlank(message="성을 입력해주세요")
@Size(min=1, max=2, message="성은 1에서 2자 사이입니다.")
private String lastName;
@NotBlank(message="이메일을 입력해주세요")
private String email;
@NotBlank : null 또는 ""인지 체크
@Size : 최소 최대사이즈 체크
@Email : 유효한 이메일 형식인지 체크
(여기서는 input type을 eamil로 지정했기때문에 빈칸만 체크하도록 처리.)
- EmployeeController -
@PostMapping("/save")
public String createEmployee(@Valid Employee employee, Errors errors) {
if (errors.hasErrors()) return "employees/new-employee"; // 유효성 에러 발생시
Long id = employee.getEmployeeId();
if (id != null) { // id가 있을 경우 업데이트
employeeService.update(employee);
} else { // id가 없을 경우 새로 생성
employeeService.save(employee);
}
return "redirect:/employees/"; //post-redirect-get 패턴
}
매개변수를 받아올때 @Valid 를 붙여 유효성검사를 한 객체를 매개변수로 받음을 알림.
잘못되었을 경우 Employee객체대신 Error객체가 넘어오게 됨.(이부분 대신 넘어오는건지 같이 넘어오는건지 헷갈림..)
errors.hasErrors()가 true일 경우 new-employee.html페이지로 이동
=> 매개변수를 받아올 때는 Project와 Error객체를 모두 가져옴.
유효성검사에 통과하지 못하면 error객체에 메시자가 담겨오고, 통과했을 경우 내용이 빈 상태로 객체가 넘어온다는 차이가 있음.
즉 객체는 무조건 2개를 모두 받되, 객체 내에 내용(메시지)이 있는가의 차이라고 생각하면 됨.
- new-employee.html -
<div class="row my-2">
<input class="form-control" th:field="*{lastName}" type="text" placeholder="성" />
<span style="color:red" th:if="${#fields.hasErrors('lastName')}" th:errors="*{lastName}">
</div>
<div class="row my-2">
<input class="form-control" th:field="*{firstName}" type="text" placeholder="이름" />
<span style="color:red" th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}">
</div>
<div class="row my-2">
<input type="email" class="form-control" th:field="*{email}" placeholder="이메일" />
<span style="color:red" th:if="${#fields.hasErrors('email')}" th:errors="*{email}">
</div>
에러메시지를 띄워주기 위한 span태그 추가.
th:if="${#fields.hasErrors('email')}"
=> email에 대한 error가 있을 경우 Employee클래스에 설정해둔 에러메시지가 나타남.
유효성검사를 통과하지 못하면 해당 속성입력칸 아래에 에러메시지를 띄움.
삭제
- EmployeeController -
@GetMapping("/delete")
public String deleteEmployee(@RequestParam("id") long id) {
employeeService.deleteEmployeeById(id);
return "redirect:/employees";
}
- EmployeeService -
public void deleteEmployeeById(long id) {
// 선태한 직원을 삭제하는 메서드
employeeRepository.deleteById(id);
}
employeeRepository에서 id로 직원을 찾아 삭제.
삭제 버튼 클릭 시 해당 employeeId로 직원을 찾아 삭제함. > 삭제된 후 직원리스트 페이지로 이동하여 삭제여부를 바로 확인가능.
프로젝트에 수정 삭제기능 추가
앞의 직원과 동일한 방식으로 수정 삭제 유효성 검사기능 추가.
1) 수정 기능 추가1
new-project.html에 수정, 삭제 버튼 추가
수정 버튼을 눌렀을 때 new-project.html페이지로 선택한 프로젝트의 id로 DB를 검색해 가져온 값을 input창에 채워서 출력하도록
- new-project.html -
<div class="row my-2">
<select class="form-select" th:field="*{stage}">
<option th:value="시작전">시작전</option>
<option th:value="진행중">진행중</option>
<option th:value="완료">완료</option>
</select>
</div>
<div class="row my-2">
<textarea class="form-control" th:field="*{description}" placeholder="프로젝트 설명"></textarea>
<span style="color:red" th:if="${#fields.hasErrors('description')}" th:errors="*{description}">
</div>
<!-- 직원 선택 태그 추가 -->
<div class="row my-2">
<p>직원들을 선택</p>
<!-- 선택태그의 매핑은 employee임. ${project.employees} = *{employees} -->
<select class="form-select" th:field="*{employees}" multiple>
<!-- 직원 전체를 옵션으로 출력 -->
<option th:each="employee : ${empList}" th:value="${employee.employeeId}" th:text="${employee.firstName}"></option>
</select>
</div>
2) 수정 기능 추가2
new-project.html페이지에 input hidden속성으로 projectId값을 ProjectController의 /save로 이동.
- new-project.html -
form 태그 내부에 추가
<input type="hidden" th:field="*{projectId}" />
3) 수정 기능 추가3
ProjectController의 /save에서 id를 검사해 null이 아닐 경우 update를, null일 경우 save를 진행.
- ProjectController -
@PostMapping("/save")
public String createProject(@Valid Project project, Errors errors, Model model) {
if (errors.hasErrors()) {
List<Employee> empList = employeeService.findAll();
model.addAttribute("empList", empList); // 프로젝트에 할당된 직원정보도 필요하므로 가져옴
return "projects/new-project";
}
Long id = project.getProjectId();
System.out.println("받아온 projectId= " + id);
if (id != null) {
projectService.update(project);
} else {
projectService.save(project);
}
return "redirect:/projects"; // post-redirect-get 패턴(new > save > new)
}
4) 삭제기능 추가
ProjectController의 /delete에서 삭제하도록 ProjectService, ProjeceRepository 차례로 수정
- ProjectController -
@GetMapping("/delete")
public String deleteProject(@RequestParam("id") long id) {
projectService.deleteProjectById(id);
return "redirect:/projects";
}
- ProjectService -
public void deleteProjectById(long id) {
// 선태한 프로젝트를 삭제하는 메서드
projectRepository.deleteById(id);
}
5) 유효성 검사 기능 추가
project클래스에 어노테이션으로 유효성검사기능을 추가.
ProjectController의 /save의 매개변수를 @Valid Project project, Errors errors로 수정하여 유효성검사를 마친 project객체와 errors객체(에러발생 시 에러메시지를 담고 이동, 없을 시 내용이 빈 객체만 이동됨)를 받아 error의 내용을 검사하여 에러발생여부를 판단.
- Project클래스 -
@NotBlank(message="프로젝트 이름을 입력해주세요")
private String name; //프로젝트 이름
private String stage; //프로젝트 상태 (시작전, 진행중, 완료)
@NotBlank(message="설명을 입력해주세요")
private String description; //설명
@PostMapping("/save")
public String createProject(@Valid Project project, Errors errors, Model model) { ...내용생략... }
1 수정 시 수정기능, 2 삭제 시 삭제기능 구현.
REST란?
웹 서비스를 만들때 사용되는 제약의 모음.
HTTP URI를 통해 자원을 명시하고 HTTP Method(GET, POST, PUT, DELETE)를 통해 해당 자원에 대한 CURD OPERATION을 적용하는 긋.
HTTP Method
-
GET
리소스를 조회할 때 사용
서버에 데이터를 전송할 때는 query를 사용하여 전달 (?data=hello&value=hello) -
POST
요청 데이터 처리, 주로 등록에 사용
message body를 통해 서버로 요청데이터를 전달함 -
PUT
리소스가 있으면 해당 리소스를 업데이트함 -
DELETE
리소스를 제거할 때 사용
Non RESTful
- GET - /GetUserDetailsServlet?userId=1
- POST - /RegisterUserServlet
- PUT - /UpdateUserDetailsServlet
- DELETE - /DeleteUserDetailsServlet?userId=1
쉽게말해 jsp를 사용했을때 url으로 넘겨주던것을 생각하면 됨.
RESTful
- GET - /users1
- POST - /users
- PUT - /users1
- DELETE - /users1
Non RESTful처럼 parameter를 사용하지않고 경로로 처리함. 이 개념은 아직 정확히 알지 못하므로 차차 학습하며 고칠것.
GET - 유저 조회
POST - 유저 생성
PUT - 유저정보 수정
DELETE - 유저 삭제
웹 뿐만 아니라 다른 환경에서도 사용할 수 있는 REST프로젝트 진행.
=> 하기 전 작업부터.
포스트맨 사용하기
서버의 API에 HTTP를 요청하여 확인하기 위함.
사진속 순서에 따라 새 collection을 만들어 이름을 simple book API로 수정, GET방식을 하나 생성하여 이름을 Server로 지정.
URL창에 https://simple-books-api.glitch.me/ 주소 입력.
send해보면 결과가 리턴됨.
GET
GET https://simple-books-api.glitch.me/status 전송 시
위 사진처럼 ok리턴.
https://simple-books-api.glitch.me/books send시 위 사진처럼 6권의 책이 리턴됨.
https://simple-books-api.glitch.me/books?type=fiction&limit=3 주소를 send하면 fiction타입의 3개의 책이 리턴됨.
해당 번호의 책을 한 권 가져옴
POST
주문을 진행하려면 가입이 선행되어야하므로 아래사진대로 가입을 먼저 진행
위 사진대로 가입하기. 이후 나온 토큰을 사용함.
가입 후 발급받은 토큰을 위 사진처럼 넣은 후
{
"bookId": 1,
"customerName": "0829kuj"
}
다시 주문내역을 넣어 send하면 정상적으로 주문이 완료되어 주문번호가 리턴됨.
GET으로 https://amazon.com/s?k=iphone 검색 시 아마존의 아이폰 판매주소를 리턴받는다.
Author And Source
이 문제에 관하여(스프링수업 6일차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@0829kuj/스프링수업-6일차저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)