이번 포스팅은 실습 위주이기 때문에 완성 코드와 중간중간 중요했던 내용을 추가로 적어야겠다
요청 매핑 어노테이션을 이용한 경로 매핑
첫 번째로 @Controller 어노테이션을 이용해 컨트롤러 클래스를 구현한다. 컨트롤러 클래스는 요청 매핑 어노테이션을 사용해서 메서드가 처리할 요청 경로를 지정한다.
@Controller
public class RegisterController {
@RequestMapping("/register/step1")
public String handleStep1() {
return "register/step1";
}
요청 매핑 어노테이션에는 @RequestMapping, @GetMapping, @PostMapping 등이 있다. @RequestMapping은 GET/POST 상관없이 지정한 경로와 일치하는 요청을 처리하고, @Get/PostMapping 은 말그대로 해당 방식으로 들어온 요청만 처리한다.
@PostMapping("/register/step2")
public String handleStep2() {
@GetMapping("/register/step2")
public String handleStep2Get() {
참고로 @Get/PostMapping 어노테이션은 스프링 4.3 버전에 추가된 것으로 이전까지는 @RequestMapping 어노테이션의 method 속성을 사용해서 HTTP 방식을 제한했다!
요청 파라미터 접근
컨트롤러 메서드에서 요청 파라미터를 사용하는 첫번째 방법은 HttpServletRequest를 직접 이용하는 것이다.
@PostMapping("/register/step2")
public String handleStep2(HttpServletRequest request) {
String agreeParam = request.getParamter("agree");
두번째는 @RequestParam 어노테이션을 사용하는 것이다. 요청 파라미터 개수가 몇 개 안되면 이 어노테이션을 사용해서 간단하게 요청 파라미터의 값을 구할 수 있다.
@PostMapping("/register/step2")
public String handleStep2(@RequestParam(value = "agree", defaultValue = "false") Boolean agree) {
(여기서 "agree"는 요청 파라미터의 name 값이다.)
@RequestParam 어노테이션의 속성
리다이렉트 처리
잘못된 경로로 요청이 들어왔을 경우 에러 화면보단 리다이렉트 처리를 하는것이 좋을 때가 있다.
리다이렉트는 "redirect:경로" 를 뷰 이름으로 리턴하기만 하면 끝이다!
@GetMapping("/register/step2")
public String handleStep2Get() {
return "redirect:/register/step1";
}
커맨드 객체를 이용해서 요청 파라미터 사용하기
@PostMapping("/register/step3")
public String handleStep3(HttpServletRequest request) {
String email = request.getParameter("email");
String name = request.getParameter("name");
...생략...
위 코드는 정상 작동하긴 하지만 요청 파라미터의 개수가 증가할 때마다 메서드의 코드 길이도 함께 길어지는 단점이 있다. 스프링은 이런 불편함을 줄이기 위해 요청 파라미터의 값을 커맨드 객체에 담아주는 기능을 제공한다.
@PostMapping("/register/step3")
public String handleStep3(RegisterRequest regReq) {
RegisterRequest 클래스에는 요청 파라미터들의 set 메서드가 존재하므로 스프링은 이들 메서드를 사용해서 요청 파라미터의 값을 커맨드 객체에 복사한 뒤 regReq 파라미터로 전달한다.
즉 ❗️ 스프링 MVC가 handleStep3() 메서드에 전달할 RegisterRequest 객체를 생성하고 그 객체의 세터 메서드를 이용해 일치하는 요청 파라미터의 값을 전달한다.
뷰 JSP 코드에서 커맨드 객체 사용하기
스프링 MVC는 커맨드 객체의 (첫 글자를 소문자로 바꾼) 클래스 이름과 동일한 속성 이름을 사용해서 커맨드 객체를 뷰에 전달한다.(ex. RegisterRequest -> registerRequest)
JSP 코드는 registerReqeust.email 이런 식으로 커맨드 객체에 접근가능하다.
@PostMapping("/register/step3")
public String handleStep3(@ModelAttribute("formData") RegisterRequest regReq) {
커맨드 객체에 접근할 때 사용할 속성이름을 변경하고 싶다면 @ModelAttribute 어노테이션을 적용해주면 된다.
컨트롤러 구현 없는 경로 매핑
WebMvcConfigurer 인터페이스의 addViewControllers() 메서드를 사용하면 요청 경로와 뷰 이름을 연결할 수 있다.
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/main").setViewName("main");
}
}
완성된 컨트롤러는 이렇다
package controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import spring.DuplicateMemberException;
import spring.MemberRegisterService;
import spring.RegisterRequest;
@Controller
public class RegisterController {
private MemberRegisterService memberRegisterService;
public void setMemberRegisterService(MemberRegisterService memberRegisterService) {
this.memberRegisterService = memberRegisterService;
}
@RequestMapping("/register/step1")
public String handleStep1() {
return "register/step1";
}
@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";
}
@GetMapping("/register/step2")
public String handleStep2Get() {
return "redirect:/register/step1";
}
@PostMapping("/register/step3")
public String handleStep3(RegisterRequest regReq) {
try {
memberRegisterService.regist(regReq);
return "register/step3";
} catch (DuplicateMemberException e) {
return "register/step2";
}
}
}
설정 클래스와 뷰 페이지는 생략 ..! (왜냐면 크게 달라진게 없기 때문)