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

서은경·2022년 8월 25일
0

Spring

목록 보기
16/43

이번 포스팅은 실습 위주이기 때문에 완성 코드와 중간중간 중요했던 내용을 추가로 적어야겠다

요청 매핑 어노테이션을 이용한 경로 매핑

첫 번째로 @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 어노테이션의 속성

  • value : String : HTTP 요청 파라미터의 이름을 지정한다.
  • require : boolean : 필수 여부를 지정한다. 이 값이 true이면서 해당 요청 파라미터에 값이 없으면 익셉션이 발생한다. 기본값은 true이다.
  • defaultValue : String : 요청 파라미터 값이 없을 때 사용할 문자열 값을 지정한다. 기본값은 없다.

리다이렉트 처리

잘못된 경로로 요청이 들어왔을 경우 에러 화면보단 리다이렉트 처리를 하는것이 좋을 때가 있다.
리다이렉트는 "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";
        }
    }
}

설정 클래스와 뷰 페이지는 생략 ..! (왜냐면 크게 달라진게 없기 때문)

0개의 댓글