Spring MVC(2) - Form처리

Form

command 객체를 이용한 Form 처리

command를 이용하지 않을 때 controller는 전달되는 값을 다음과 같이 처리한다.

@Controller
@RequestMapping("/article/newArticle.do")
public class NewArticleController {
    ...
    @RequestMapping(method=RequestMethod.POST)
    public String submit(@RequestParam(“parentId”) int pid,
    				@RequestParam(“title”) String title,
    				@RequestParam(“content”) String content) {
        NewArticleCommand article = new NewArticleCommand();
        article.setParentId(pid);
        article.setTitle(title); article.setContent(content);
        ... // 입력 값 처리
        return "article/newArticleSubmitted"; // 결과 view
    }
}

요청 parameter들을 각각 추출해서 전달해야함.

form의 각 항목들과 property이름이 일치하는 command class를 다음과 같이 만든다.

public class NewArticleCommand {
    private int parentId;
    private String title;
    private String content;
    public String getTitle() {
    	return title;
    }
    public void setTitle(String title) {
    	this.title = title;
    }
    ... // getter & setter methods
}

이를 이용하면 다음과 같이 NewArticleCommand 클래스 타입의 파라미터를 지정해 객체를 전달 할 수 있다,

@Controller
@RequestMapping("/article/newArticle.do")
public class NewArticleController {
...
    @RequestMapping(method=RequestMethod.POST)
    public String submit(NewArticleCommand article) {

DispatcherServlet은 command 객체를 생성하고 form 입력값들에 대응되는 property에 저장한 후 리퀘스트 핸들러 메소드에 전달한다. 자동 타입 변환이 이루어진다.

 

view 에서 command 객체에 접근할 때에는

<html>
<head><title>게시글 쓰기</title></head>
<body>
게시글 등록됨:<br/>
제목: ${newArticleCommand.title} <br/>
내용: ${newArticleCommand.content}
</body>
</html>

command 클래스 이름과 동일하지만 첫글자가 소문자로 변환된 객체에서 변수들을 불러 올 수 있다.

@ModelAttribute 어노테이션을 사용하면 뷰에 전달될 command객체의 이름을 지정할 수 있다.

@RequestMapping(method=RequestMethod.POST)
public String submit(
@ModelAttribute(“article”) NewArticleCommand newArticle) {

이 경우 뷰에서는 article.title과 같이 불러올 수 있다.

 

Form 입력값 검증

Validator를 이용한 form 입력값을 검증을 위해서는 Validator interface를 구현해야한다.

핸들러 메소드에서 Errors 또는 BindingResult 타입의 인자를 정의 해야한다

(단, command 객체 인자 바로 뒤 인자로 정의 해야한다.)

Validator 객체를 생성한 뒤 validate()메소드를 호출한다. 이 때, Command 객체와 Errors 객체를 인자로 전달한다.

@Controller @RequestMapping("/account/create")
public class CreateAccountController {
    @RequestMapping(method = RequestMethod.POST)
    public String submit(@ModelAttribute("command") MemberInfo memberInfo,
    Errors result ) { // Errors 타입 대신 BindingResult 타입도 가능
        new MemberInfoValidator().validate(memberInfo, result); // 검증 실행
        if (result.hasErrors())
        	return "account/creationForm"; // 검증 오류 발생 시 입력 form을 다시 출력
        accountService.createAccount(memberInfo); // 오류가 없으면 service 호출
        return "account/created"; // 결과 view 출력
        } ...
}

 

@Valid 어노테이션을 이용하면 validate()메소드 호출이 불필요하다.

핸들로 메소드의 파라미터 중 검증이 필요한 객체 앞에 적용한다. 핸들러 메소드 실행 전에 먼저 실행된다.

오류 발생시 Errors나 BindingResult 타입 객체에 저장된다.

@Controller
@RequestMapping("/login/login.do")
public class LoginController {
    …
    @RequestMapping(method = RequestMethod.POST)
    public String submit(@Valid LoginCommand loginCommand, BindingResult result) {
        // new LoginCommandValidator().validate(loginCommand, result); 코드 불필요!
        if (result.hasErrors()) return "login/form"; // 검증 오류 발생 시 login form으로 이동
        …
    }
    @InitBinder // controller 범위 validator 설정을 위한 method
    protected void initBinder(WebDataBinder binder) {
    	binder.setValidator(new LoginCommandValidator());
    }
}

@InitBinder는 특정 컨트롤러에서 사용할 validator를 설정한다. 

WebDataBinder 객체를 파라미터로 전달 받는다.

setValidator() : 기존 global validator를 대체한 validator 지정

addValidator() : 기존 global validator를 유지하고 컨트롤러 범위 validator를 추가

@RequestMapping(method = RequestMethod.POST)
public String submit(@Valid LoginCommand loginCommand, BindingResult result) {
	if (result.hasErrors()) return "login/form"; // 검증 오류 발생 시 login form으로 이동
…
}

@InitBinder // controller 범위 validator 설정을 위한 method
protected void initBinder(WebDataBinder binder) {
	binder.setValidator(new LoginCommandValidator());
}

 

 

Global Validaotr는 새로운 클래스를 정의하지 않고 범용적인 validaotor를 이용하여 검증한다.

command class 내에 @NotNull, @Size, @Digits 같은 annotation을 사용.

OptionalValidatorFactoryBean 객체를 등록해야하는데

<mvc:annotation-driven />또는 @EnableWebMvc 이용한다.

command 메소드 앞에 @Valid를 적용

 

Bean Validation API 1.1의 주요 어노테이션들

@Null
@NotNull
값이 null이면 안된다 ex) @Null String userName;
@Min
@Max
@DecimalMin
@DecimalMax
값 제한 ex) @Min(5) int quanity; @DecimalMax("30.00") BigDecimal discount;
@Size String의 경우에는 길이를 Collection/Map/Array의 경우 사이즈를 제한한다
ex) @Size(min=2, max=50)String message;
@Pattern 정규식으로 내용을 검증함 ex) @Pattern(regexp= "\\(\\d{3}\\)\\d{3}-\\d{4}") String phoneNumber;
@AssertTrue
@AssertFalse
true/false 값 지정

Bean Validation API 2.0의 주요 어노테이션들

@NotEmpty CharSequence, Collection, Map, arrays에 null이거나 empty상태인지 확인
@NotBlank 공백인지 확인한다
@Email(regexp=,flags=) 이메일 검증

message/validation.properties에 메세지를 추가하면 오류메세지가 지정된다.

예를들어 MemberInfo클래스에 @Size(min=5, max=20) String id; 가 있을때 메세지파일에

Size.memberInfo.id=사용자 id는 {1}자 이상 {2}자 이내여야 합니다. 와 같이 지정하면 해당 오류가 출력된다.

따로 지정하지 않을 경우 validator provider가 제공하는 기본 메세지들이 출력된다.

 

@DateTimeFormat, @NumberFormat을 사용하여 타입 변환 설정이 가능하다.

@DateTimeFormat(pattern="yyyy/MM/dd") // “2015/04/20” → java.util.Date 타입 변환
private java.util.Date from;

@DateTimeFormat(iso=ISO.DATE_TIME) // “2015-04-21T13:30:55.113+08:30”
private java.util.Date to; //java.util.Date 타입 변환

@NumberFormat(patter="$###,##0.00") //"$1,234.56"
private java.math.BigDecimal amount;

'공부기록 > 스프링' 카테고리의 다른 글

스프링 view 구현 (jsp)  (0) 2023.05.23
스프링 HTTP Session 사용  (0) 2023.05.22
Spring MVC(1) - DispatcherServlet, Handler mapping, Controller  (0) 2023.04.25
스프링의 DI  (0) 2023.04.20
스프링 컨테이너와 스프링 빈  (0) 2023.03.22
myoskin