1. Data Binding
- request parameter들은 어떻게 해당 오브젝트로 옮겨질까
-
Naive solution
- @RequestParam annotaion을 사용하여 메서드 매개 변수와 bind 해준다.
ex)
@RequestMapping("/deget")
public String doGet( @RequestParam("name") String name){... }
-> 이런 식으로 받은 매개변수를 객체를 만들어 set 해주는 방식 -
Spring Data Binding
- form에서 오는 매개변수를 자동으로 객체에 바인딩시켜준다.
ex)
@RequestMapping(value="/docreate", method=RequestMethod.POST)
public String doGet(EmployeeVo ){... }
-> Spring이 자동적으로 employeeVo객체에 받은 requestParameter를 넣어준다.- 바인딩되는 과정
- Dispatcher Servlet에서 요청을 받음
- 새로운 form bean이 인스턴스화 된다.
- form bean은 requestParameter에서 채워진다.
- form bean이 모델에 추가된다.
- bean을 Controller로 전달
- Controller에서 Dispatcher Serlvet에 Model 객체를 전달한다.
- Dispatcher Servelt에서 View로 Model 객체를 전달 후 View는 객체를 사용하여 render
- View 예시
- <body> hihi, ${employeeVo.name} </body>
- 바인딩되는 과정
2. Data Validation
- 사용자가 잘못된 입력을 한 경우 제대로 된 입력을 위해 안내를 해주어야 한다.
안내 예시) 이메일 형식이 아닙니다.(이메일 형식 예시: aaa@naver.com)
-
Hibernate Validator
- 사용자의 오류를 감지하려면 form bean에서 캡슐화된 form data의 유효성을 검증해야 한다.
(쉽게 말해 Bean을 정의한 클래스의 멤버 변수에 대해 유효성 설정이 필요하다는 것) - Bean Validation API(JSR-303)는 JavaBean 유효성 검사를 위한 API를 정의한다.
- @NotNull, @Pattern, @Size annotation을 달아 Bean의 각 속성에 유효성 검사를 할 수 있다. - Bean Validation API의 reference 구현인 Hibernate Validator 사용 예시
- Hibernate Validator는 몇 가지 커스텀 annotation을 제공한다. (예 : @Email)
- 라이브러리 추가
<dependency>
<groupId> org.hibernate </groupId>
<artifactId> hibernate-validator </artifactId>
<version>... </version>
</dependency>
- 사용자의 오류를 감지하려면 form bean에서 캡슐화된 form data의 유효성을 검증해야 한다.
Public class EmployeeVo{
private int id;
@Size(min=5, max=100)
@Pattern(regexp="^[A-Z]{1}[a-z]+$")
private String name;
@NotEmpty
@Email
private String email;
...
}
-
Message Interpolation
- 위반된 Bean 유효성 검증 제한 조건에 대한 오류 메시지를 작성하는 프로세스
- 위와 같은 결과를 얻기 위해서 각 속성에 message descriptor를 설정
예시
import java.io.Serializable;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
public class EmployeeVO implements Serializable
{
private static final long serialVersionUID = 1L;
private Integer id;
@Size(min = 3, max = 20)
private String firstName;
@Size(min = 3, max = 20)
private String lastName;
@Pattern(regexp=".+@.+\\.[a-z]+")
private String email;
//Setters and Getters
@Override
public String toString() {
return "EmployeeVO [id=" + id + ", firstName=" + firstName
+ ", lastName=" + lastName + ", email=" + email + "]";
}
}
-
Validating Object
- 검증은 @Valid annotation을 달면 된다.
- @Valid는 객체의 유효성 검사를 한 후에 Model에 추가한다.
ex) @RequestMapping(... )
public String doGet(@Valid EmployeeVo employeeVo){... } - Handler 메서드(@RequestMapping annotation이 달린 메서드)는 검증 프로세스 결과가 담긴 객체인 BindingResult를 요청할 수 있다.
ex) @RequestMapping(... )
public String doGet(@Valid EmployeeVo employeeVo, BindingResult result){... } - BindingResult 객체를 받아와 에러 검사를 할 수 있다.
- 예시
@RequestMapping(...)
public String doGet(@Valid EmployeeVo employeeVo, BindingResult result) {
if(result.hasErrors()) {
List<ObjectError> errors = result.getAllErrors();
for(ObjectError error:errors) {
System.out.println(error.getDefaultMessage());
}
return "home";
}
결론: @Valid..., BindingResult - 이 두 인자만 넣어줘도 Spring에서 자동으로 Data Binding, 검증, 결과 이 3가지 일을 전부 자동으로 해준다.
3. Data Buffering
- 사용자가 잘못된 입력을 한 뒤 페이지가 재요청되었을 때, 모든 속성을 다시 입력하는 수고를 덜어주어야 한다.
- Web form에 content를 바인딩
- 채워진 form bean들을 처리하기 위해, Spring은 data binding-aware tag들을 제공해준다.
-> 서버에서 클라이언트로 속성 값들을 보내주는 형태 - Spring form tag library를 사용하기 위해서는 JSP page 상단에
<%@ taglib prefix=”sf" uri="http://www.springframework.org/tags/form"%>를 추가해주어야 한다. - 기존 HTML 태그가 Spring form tag library로 바뀐다.
ex) <form> -> <sf:form>, <input type="text"> -> <sf:input>, <input type="password"> -> <sf:password>
JSP 수정
<%@ taglib prefix=”sf" uri="http://www.springframework.org/tags/form"%>
...
<body>
<sf:form method="post"
action="${pageContext.request.contextPath}/doget" modelAttribute="employeeVo">
<table class="formtable">
<tr>
<td class="label">Name:</td>
<td><sf:input class="control" path="name"/></td>
</tr>
...
</sf:form>
</table>
</body>
</html>
Controller 수정
//수정 예시
@RequestMapping("/getemployeeVo")
public String getEmployeeVo(Model model) {
model.addAttribute("employeeVo", new EmployeeVo());
return "home";
}
//적용
@RequestMapping(value="/doGet", method=RequestMethod.POST)
public String doGet(@Valid EmployeeVo employeeVo, BindingResult result) {
if(result.hasErrors()){
return "home";
}
}
전달 과정
참고
- Controller handler 메서드의 인자인 employeeVo는 자동으로 인스턴스화 되어 Model에 추가된다.
- Error Messages
- 사용자에게 요청이 거절된 이유를 안내하기 위해 에러 표시 코드를 추가- BindingResult 객체는 @Valid가 달린 Bean(EmployeeVo)과 같이 자동으로 Model에 삽입되어 Dispatcher Servlet을 통해 View로 전달된다.
- Input 속성 밑에 error 태그를 추가하여 거절 이유를 표시한다.
예시)
<sf:form modelAttribute="employeeVo">
Name: <sf:input path="name" />
<sf:errors path="name" sf:errors>
Email: <sf:input path="email" />
<sf:errors path="email"></sf:errors>
…
</sf:form>
- 요청이 거절된다면 Bean 속성에 설정한 message discriptor대로 message가 view 상에 나타나게 된다.
요약: 따라서 Form bean은 Data binder, Data validator, Data buffer 역할을 하는 동시에 한다.
Reference
https://howtodoinjava.com/spring-mvc/spring-bean-validation-example-with-jsr-303-annotations/
'Spring > 이론' 카테고리의 다른 글
Logging (SLF4J and Logback) (0) | 2020.04.01 |
---|---|
Spring Security (0) | 2020.03.30 |
MVC(Model-View-Controller) (0) | 2020.03.17 |
DB 연동(with Spring JDBC) (0) | 2020.03.09 |
관점 지향 프로그래밍(AOP, Aspect Oriented Programming) (0) | 2020.03.07 |
댓글