11장 (2)는 목록 8 - 14까지 다루고 있습니다. (초보 웹 개발자를 위한 스프링5 프로그래밍 입문 286p~319p)
11 - (2)장의 키워드
# @ModelAttribute 애노테이션
# 커스텀 태그
# ModelAndView
@PostMappint("/register/step3")
public String handleStep3(@ModelAttribute("formData") RegisterRequest regReq) {
... //"RegisterRequest -> formData 라는 이름으로 커맨드 객체에 접근 가능
}
//입력한 email 나오게하기
<input type="text" name="email" id="email" value="${registerRequest.email}">
//입력한 name 나오게하기
<input type="text" name="name" id="name" value="${registerRequest.name}">
<form:form action="step3" modelAttribute="registerRequest">
<input id="name" name="name" type="text" value="${registerRequest.name}" />
//커스텀 태그 사용 후
<form:input path="name" />
<input id="name" name="name" type="text" value="스프링" /> //만약 폼에 입력한 name이 "스프링"이라면
3. 커맨드 객체를 모델에 넣기
//RegisterController.java
import org.stringframework.ui.Model;
@Controller
public class RegisterController{
...
@PostMapping("/register/step2") //step2일때
public String handleStep2(
@RequestParam(value="agree", defaultValue="false") Boolean agree, Model model){//모델추가
if(!agree) { //true가 아니면 [약관동의폼]인 "register/step1" 뷰를 리턴
return "register/step1";
}
model.addAttribute("registerRequest", new RegisterRequest()); //새로운 커맨드 객체를 registerRequest 로 만들고, 객체를 모델에 넣어라
return "register/step2"; //true이면 [입력 폼]인 "register/step2" 뷰를 리턴
}
...
}
//step3.jsp
<p><a href="<c:url value='/main'/>">[첫 화면 이동]</a></p>
//컨트롤러
@Controller
public class MainController{
@RequestMapping("/main")
public String main(){
return "main"; //main뷰로 이동해라. 라는 처리만 한다.
}
}
※ 문제 해결 : WebMvcConfigurer 인터페이스의 addViewControllers() 메서드를 사용한다.
//MvcConfig 파일에 추가
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
@Override
public void addViewControllers(ViewControllerRegistry regisry) {
registry.addViewController("/main").setViewName("main"); // "/main"경로는 main뷰로 이동해라.
}
404 오류 발생
HTTP Status 404 - Not Found
다음 사항을 확인해야한다.
405 오류 발생
HTTP Status 405 - Method Not Allowed
404 오류 발생
@PostMappint("/register/step2")
public String handleStep2(
//필수로 존재해야하고 기본값이 없음
@RequestParam("agree")Boolean agree, Model model){
...
}
HTTP Status 400 - Bad Request
<input type="checkbox" name="agree" value="true1"> 약관동의
HTTP Status 400 - BadRequest
public class Responded {
private int age;
private String location;
public int getAge() {
retrun age;
}
public void setAge(int age) {
this.age = age;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
public class AnsweredData {
private List<String> responses; //리스트 프로퍼티
private Respondent res; //중첩프로퍼티를 가짐
public List<Stirng> 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;
}
}
ex) List 타입 프로퍼티를 위한 파라미터 이름 : responses[0](0번 인덱스), responses[1] (1번 인덱스)
중첩 프로퍼티의 경우 파라미터 이름 : res.name
다음과 유사한 방식으로 커맨드 객체에 파라미터 값을 설정한다.
commandObj.getRes().setName(request.getParameter("res.name"));
@Controller
@RequestMappint("/survey")
public class SurveyController {
@GetMapping
public String form() { //메서드 처리 경로 "/survey" - Get방식 요청 처리
return "survey/surveyForm";
}
@PostMapping //메서드 처리 경로 "/survey" - POST방식 요청 처리
public String submit(@ModelAttribute("ansData") AnsweredData data) { //커맨드 객체로 AnsweredData 사용
return "survey/submitted";
}
}
import survey.SurveyController;
@Controller
public class ControllerConfig {
...
@Bean
public SurveyController surveyController() {
return new SurveyController();
}
}
//surveyFrom.jsp
<label><input type="radio" name="responses[0]" value="서버">서버 개발자</lavbel>
<label><input type="radio" name="responses[0]" value="프로트">프론트 개발자</lavbel>
<label><input type="radio" name="responses[0]" value="풀스택">풀스택개발자</lavbel>
<label><input type="radio" name="responses[1]" value="Eclips">Eclips</lavbel>
<label><input type="radio" name="responses[2]" value="Intellij">Intellij</lavbel>
<label><input type="radio" name="responses[1]" value="Sublime">Sublime</lavbel>
<input type="text" name="responses[2]">
<input type="text" name="res.location">
<input type="text" name="res.age">
SurveyController을 설문 항복을 컨트롤러에서 생성해서 뷰에 전달하는 방식으로 변경
1. Question 객체 생성 : 제목과 답변 정보를 보관한다.
2. 컨트롤러 수정
3. JSP 코드 수정
4. SurveyController에서 Model을 통해 전달한 Question 리스트를 이용하여 설문 폼이 생성
컨트롤러의 특징
ModelAndView를 이용하면 이 두 가지를 한번에 처리 가능하다.
import org.springframework.web.suvel.ModelAndView;
@Controller
@RequestMappint("/survey")
public class SurveyController {
@GetMapping
public ModelAndView form(){
List<Question> questions = createQuestions(); //Question 리스트 생성
ModelAndView mav = new ModelAndView(); //ModelAndView 객체 생성
mav.addObject("questions", questions); //question 이란 이름으로 모델데이터 추가
mav.setViewName("survey/surveyForm"); //뷰 이름 작성
return mav;
}
@Controller
public class RegisterController{
...
@PostMapping("/register/step2") //step2일때
public String handleStep2(
@RequestParam(value="agree", defaultValue="false") Boolean agree,
Model model){//모델 직접 추가
if(!agree) { //true가 아니면 [약관동의폼]인 "register/step1" 뷰를 리턴
return "register/step1";
}
model.addAttribute("registerRequest", new RegisterRequest()); //새로운 커맨드 객체를 registerRequest 로 만들고, 객체를 모델에 넣어라
return "register/step2"; //true이면 [입력 폼]인 "register/step2" 뷰를 리턴
}
}
변경 : GET, POST에서 사용할 커맨드 객체의 속성이 같을때
@Controller
public class RegisterController{
...
@PostMapping("/register/step2") //step2일때
public String handleStep2(
@RequestParam(value="agree", defaultValue="false") Boolean agree,
RegisterRequest registerRequest){//커맨드 객체 추가
if(!agree) {
return "register/step1";
}
return "register/step2";
}
변경 : GET, POST에서 사용할 커맨드 객체의 속성이 다를때("/login" 요청 경로일때)
@Controller
@RequestMappint("/login")
public class LoginController {
@GetMapping
public String form(@ModelAttribute("login") LoginCommand loginCommand) { //@ModelAttribute로 커맨드 객체를 파라미터로 추가
return "login/loginForm";
}
@PostMapping
public String form(@ModelAttribute("login") LoginCommand loginCommand) {
...
}
}
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
...
<form:form>
...
<input ...>
</form:form>
<form id="command" action="/sp5-chap22/register/step2" method="post"> ...
<form:form modelAttribute="loginCommand"> //커맨드 객체 이름을 loginCommand로 지정
...
</form:form>
<form:form> 태그와 관련된 속성 추가
커맨드 객체 값을 사용하여 이전에 입력한 값을 출력하기
<input type="text" name="id" value="${loginCommand.id}" /> //이전에 입력한 id값 가져오기
1. <form:input> 태그
<form:input path="email" />
<input id="email" name="email" type="text" value="abc@naver.com" />
2. <form:password> 태그와 <form:hidden> 태그
<form:from modelAttribute="loginCommand">
<form:hidden path="defaultSecurityLevel" /> //속성을 이용하여연결할 커맨드 객체의 프로퍼티를 지정
...
<form:password path="password" /> //속성을 이용하여연결할 커맨드 객체의 프로퍼티를 지정
</form:form>
1. <form:select> 태그
@GetMapping("/login")
public String form(Model model){
List<String> loginTypes = new ArrayList<>();
loginTypes.add("일반회원");
loginTypes.add("기업회원");
loginTypes.add("헤드헌터회원");
model.addAttribute("loginTypes", loginTypes);
return "login/form";
}
태그의 value 속성 : <option> 태그의 value 값 지정
태그의 label 속성 : 그 값의 텍스트로 사용
<form:option value="헤드헌터회원" label="헤드헌터" />
<option value="헤드헌터회원"> 헤드헌터</option>
1. 커맨드 객체에 접근하여 속성 이름을 변경하고 싶으면 (@ModelAttribute 애노테이션)을 사용한다.
2. 스프링 MVC가 제공하는 태그는 (커스텀 태그)이다. 예시로는 <input>을 <form:input>으로 작성한다.
3. WebMvcConfigurer 인터페이스의 (addViewControllers()) 메서드는 요청 경로와 뷰 이름을 연결해주는 역할을 한다.
4. 컨트롤러의 두 가지 역할은 (Model을 이용하여 뷰에 전달할 데이터 생성), (결과를 보여줄 뷰 이름을 리턴)하는 것이다.
5. 4번의 컨트롤러 역할을 모두 해주는 것은 (ModelAndView)이다.
6. <form:form>태그의 속성 추가는 (action), (encytpe), (method)이다.
7.컨트롤러의 파라미터에 (커맨드 객체)를 추가하면 GET 방식과 POST 방식에 동일한 커맨드 객체를 사용할 수 있다.
1. 특별한 역할이 없는 컨트롤러를 요청 경로를 매핑하여 뷰로만 연결해주려고 한다.
"/main"의 요청경로와 main 뷰 이름을 연결해서 작성하려고 할때, 다음 빈칸을 채우시오.
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
@Override
public void addViewControllers(ViewControllerRegistry regisry) {
registry.__________________("______").setViewName("_____"); // "/main"경로는 main뷰로 이동해라.
}
정답: addViewControllers, /main, main
2. 아래와 같은 두가지일을 한번에 처리하려고 한다. 다음 빈칸을 채우시오.
import org.springframework.web.suvel._______________;
@Controller
@RequestMappint("/survey")
public class SurveyController {
@GetMapping
public ModelAndView form(){
List<Question> questions = createQuestions(); //Question 리스트 생성
______________ mav = new _____________(); //ModelAndView 객체 생성
mav.addObject("questions", _________); //question 이란 이름으로 모델데이터 추가
mav.____________("survey/surveyForm"); //뷰 이름 작성
return mav;
}
정답: ModelAndView, ModelAndView, ModelAndView, questions, setViewName
[스프링2] 13. MVC 3: 세션, 인터셉터, 쿠키 (0) | 2023.01.05 |
---|---|
[스프링2] 12장. MVC 2: 메시지, 커맨드 객체 검증 (0) | 2022.12.29 |
[스프링2] 11장. MVC 1: 요청 매핑, 커맨드 객체, 리다이렉트, 폼 태그, 모델 (1) (0) | 2022.12.22 |
[스프링2] 10장. 스프링 MVC 프레임워크 동작 방식 (0) | 2022.12.01 |
[스프링2] 9장. 스프링 MVC 시작하기 (0) | 2022.11.24 |