작심십일러의 스프링 시작하기(10)-2

서은경·2022년 8월 29일
0

Spring

목록 보기
18/43

커맨드 객체 : 중첩, 콜렉션 프로퍼티

스프링 MVC는 커맨드 객체가 리스트 타입의 프로퍼티를 가졌거나 중첩 프로퍼티를 가진 경우에도 요청 파라미터의 값을 알맞게 커맨드 객체에 설정해주는 기능을 제공하고 있다.

설문조사 응답자 클래스

package survey;

public class Respondent {

    private int age;
    private String location;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }
}

설문조사 답변 클래스

package survey;

import java.util.List;

public class AnsweredData {

    private List<String> responses;
    private Respondent res;

    public List<String> getResponses() {
        return responses;
    }

    public void setResponses(List<String> responses) {
        this.responses = responses;
    }

    public Respondent getRes() {
        return res;
    }

    public void setRes(Respondent res) {
        this.res = res;
    }
}
  • 규칙1 : HTTP 요청 파라미터 이름이 "프로퍼티이름[인덱스] 형식이면 List 타입 프로퍼티의 값 목록으로 처리한다.
  • 규칙2 : HTTP 요청 파라미터 이름이 "프로퍼티이름.프로퍼티이름"과 같은 형식이면 중첩 프로퍼티 값을 처리한다.

이 두 클래스로 예를 들자면 AnsweredData 클래스는 답변 목록을 저장하기 위한 List 타입의 responses 프로퍼티와 응답자 정보를 담기 위해 Respondent 타입의 프로퍼티를 사용했다.

	<p>
      <label><input type="radio" name="responses[0]" value="서버">서버개발자</label>
      <label><input type="radio" name="responses[0]" value="프론트">프론트개발자</label>
      <label><input type="radio" name="responses[0]" value="풀스택">풀스택개발자</label>
	</p>
    <p>
        <label>응답자 위치:<br/>
        <input type="text" name="res.location">
        </label>
    </p>

이런식으로~ input 태그의 name 속성이 커맨드 객체의 프로퍼티에 매핑된다.
responses[0] -> responses 프로퍼티(List 타입)의 첫번째 값
res.location -> res 프로퍼티(Respondent 타입)의 location 프로퍼티

Model을 통해 컨트롤러에서 뷰에 데이터 전달하기

컨트롤러는 뷰가 응답 화면을 구성하는데 필요한 데이터를 생성해서 전달해야 한다. 이 때 사용하는 것이 Model이다.

뷰에 데이터를 전달하는 컨트롤러는 다음 두 가지를 하면 된다.

  • 요청 매핑 어노테이션이 적용된 메서드의 파라미터로 Model을 추가
  • Model 파라미터의 addAttribute() 메서드로 뷰에서 사용할 데이터 전달
package survey;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.Arrays;
import java.util.List;

@Controller
@RequestMapping("/survey")
public class SurveyController {

    @GetMapping
    public String form(Model model) {
        List<Question> questions = createQuestions();
        model.addAttribute("questions", questions);
        return "survey/surveyForm";
    }

    // ModelAndView 를 사용하면 Model을 이용해
    // 뷰에 전달할 데이터 설정 및 결과를 보여줄 뷰 이름을 리턴할 수 있다
    public ModelAndView formModelAndView() {
        List<Question> questions = createQuestions();
        ModelAndView mav = new ModelAndView();
        mav.addObject("questions", questions);
        mav.setViewName("survey/surveyForm");
        return mav;
    }

    private List<Question> createQuestions() {
        Question q1 = new Question("당신의 역할은 무엇입니까?", Arrays.asList("서버","프론트","풀스택"));
        Question q2 = new Question("많이 사용하는 개발도구는 무엇입니까?", Arrays.asList("이클립스","인텔리J","서브라임"));
        Question q3 = new Question("하고 싶은 말을 적어주세요.");
        return Arrays.asList(q1, q2, q3);
    }

    @PostMapping
    public String submit(@ModelAttribute("ansData") AnsweredData data) {
        return "survey/submitted";
    }

}

여기서 궁금한 점 하나 ❗️
Model 객체는 도대체 어디서 생성돼서 매개변수로 받아와지는걸까 ? 검색해보니 컨트롤러는 파라미터를 자동으로 수집하는 기능이 있다고 한다.
스프링은 메소드의 파라미터에 Model 타입이 지정된 경우 Model 타입의 객체를 만들어서 메서드에 주입한다. 즉 스프링이 제공하는 기능이라는 것 ~~!!

GET 방식과 POST 방식에 동일 이름 커맨드 객체 사용하기

<form:form> 태그를 사용하려면 커맨드 객체가 반드시 존재해야 한다.

	@PostMapping("/register/step2")
    public String handleStep2(@RequestParam(value = "agree", defaultValue = "false") Boolean agree, Model model) {
        if (!agree) {
            return "register/step1";
        }
        model.addAttribute("registerRequest", new RegisterRequest());
        return "register/step2";
    }

이런 식으로 폼 표시 요청이 왔을 때 커맨드 객체를 생성해서 Model에 저장하는데

	@PostMapping("/register/step2")
    public String handleStep2(@RequestParam(value = "agree", defaultValue = "false") Boolean agree, RegisterRequest registerRequest) {
        if (!agree) {
            return "register/step1";
        }
        return "register/step2";
    }

커맨드 객체를 파라미터로 추가하면 Model에 직접 객체를 추가하지 않아도 된다.

주요 폼 태그 설명

스프링 MVC는 <form:form>, <form:input> 등 HTML 폼과 커맨드 객체를 연동하기 위한 JSP 태그 라이브러리를 제공한다.

  • <form:form>
    <form>태그를 생성할 때 사용된다.
  • <form:input>, <form:password>, <form:hidden>
    <input> 태그를 위해 해당 커스텀 태그를 제공한다.
  • <form:select>, <form:options>, <form:option>
    <select> 태그와 관련된 커스텀 태그는 이와 같이 세가지가 존재한다.
  • <form:checkboxes>, <form:checkbox>
    한 개 이상의 값을 커맨드 객체의 특정 프로퍼티에 저장하고 싶다면 배열이나 List와 같은 타입을 사용해서 값을 저장한다.
  • <form:radiobuttons>, <form:radiobutton>
    여러가지 옵션 중에서 한가지를 선택해야 하는 경우 radio 타입의 <input> 태그를 사용한다.
  • <form:textarea>
    게시글 내용과 같이 여러 줄을 입력받아야 하는 경우 <textarea> 태그를 사용한다.

0개의 댓글