Spring MVC : 가장 간단하게 시작하기

    @RequestMapping과 @Controller


    @Controller가 하는 일

    • 1. @Controller안에는 @Component가 있어, 내부적으로 스프링 빈으로 등록해준다.
    • 2. @Controller가 붙으면 어노테이션 기반의 컨트롤러라는 것으로 내부적으로 인식하게 된다.
    • 3. @Contoller가 붙으면 RequestMappingHandler로 이해를 한다.

    @RequestMapping 어노테이션이 하는 일

    • 1. 해당 클래스 또는 URL을 컨트롤러에 맵핑 시켜준다.
      • 이 때, URL 기준으로 맵핑되기 때문에 메서드 이름은 아무 상관이 없다.
    • 2. RequestMapping이 붙으면 RequestHandlerAdapater, RequestMappingHandlerMapping으로 사용된다.
      • 이 때, @Component + @RequestMapping으로 등록해서 위와 동일하게 인식한다.

    붙이게 되면 RequestHandlerAdapter / RequestMappingHandlerMapping이 되도록 도와준다. 

     

    컨트롤러 Version1


    FormController, ListController, SaveController를 하나씩 만든다.

    @Controller
    public class SpringMemberFormControllerV1 {
        @RequestMapping("/springmvc/v1/members/new-form")
        public ModelAndView process(){
            return new ModelAndView("new-form");
        }
    }
    
    @Controller
    public class SpringMemberListControllerV1 {
    
        private MemberRepository memberRepository = MemberRepository.getInstance();
    
        @RequestMapping("/springmvc/v1/members")
        public ModelAndView process(){
            List<Member> members = memberRepository.findAll();
            ModelAndView mv = new ModelAndView("members");
    
            mv.addObject("members", members);
            return mv;
        }
    }
    
    @Controller
    public class SpringMemberSaveControllerV1 {
    
        private MemberRepository memberRepository = new MemberRepository();
    
        @RequestMapping("/springmvc/v1/members/save")
        public ModelAndView process(HttpServletRequest request, HttpServletResponse response){
            String username = request.getParameter("username");
            int age = Integer.parseInt(request.getParameter("age"));
    
            Member member = new Member(username, age);
            System.out.println("member = " + member);
    
            memberRepository.save(member);
            ModelAndView mv = new ModelAndView("save-result");
    
            mv.addObject("member", member);
            return mv;
        }
    
    
    }

    위와 같은 형태로 3개의 클래스를 각각 만들고, 각각을 컨트롤러로 등록해줄 수 있다. 이 경우 반복되는 부분을 보면 다음과 같다.

    • @RequestMapping URL이 반복된다 "/springmvc/v1/members/save"
    • @RequestMapping이 비슷한 컨트롤러인데 각 클래스로 만들었다.

    위 내용을 개선한 Version 2를 만들 수 있다.

    컨트롤러 Version2


    FormController, ListController, SaveController를 하나의 클래스에 몰아둔 다음에 만들 수 있다.

    @Controller
    @RequestMapping("/springmvc/v2/members")
    public class SpringMemberControllerV2 {
    
        private MemberRepository memberRepository = new MemberRepository();
    
        @RequestMapping("/save")
        public ModelAndView process1(HttpServletRequest request, HttpServletResponse response) {
            String username = request.getParameter("username");
            int age = Integer.parseInt(request.getParameter("age"));
    
            Member member = new Member(username, age);
            System.out.println("member = " + member);
    
            memberRepository.save(member);
            ModelAndView mv = new ModelAndView("save-result");
    
            mv.addObject("member", member);
            return mv;
        }
    
        @RequestMapping
        public ModelAndView process2() {
            List<Member> members = memberRepository.findAll();
            ModelAndView mv = new ModelAndView("members");
    
            mv.addObject("members", members);
            return mv;
        }
        @RequestMapping("/new-form")
        public ModelAndView process3() {
            return new ModelAndView("new-form");
            }
    
    
    }
    • @RequestMapping URL이 반복된다 "/springmvc/v1/members/save"
      • → Class 레벨에 @RequestMapping을 사용해서 반복되는 "/springmvc/v2/members"를 처리해줌
    • 하나의 컨트롤러로 만듦.
      • 하나의 컨트롤러에 메서드 맵핑을 통해서 통합으로 Handler를 관리하도록 설정함.

    여기서 하나의 개선점이 더 있는 것을 볼 수 있다. 매번 ModelAndView를 생성해서 만들고 있는데, 이걸 어떻게 해결할 수 있는 방법이 없을까? 

    컨트롤러 Version3


    지금까지는 항상 ModelAndView를 반환했지만, 반환 타입을 String으로 해줄 수 있다. @Controller에서 반환타입을 String을 할 경우, 이 때는 ViewName으로 인식을 한다. 그렇다면 이 때 Model이 필요한데, Model이 필요한 경우 매개변수에 Modle을 넣어주면 된다.

    이 모든 것은 HandlerAdapter에서 ArgumentResolver와 ReturnValueResolver가 필요한 것을 찾아서 해결해준다. 또한, 현재 어떤 Http Method로 오든 상관없이 URL 매핑이 되는 것을 볼 수 있다. 이것을 @GetMapping, @PostMapping, @PutMapping등의 어노테이션 등을 활용해 해결할 수 있다.

    @Controller
    @RequestMapping("/springmvc/v3/members")
    public class SpringMemberControllerV3 {
    
        private MemberRepository memberRepository = new MemberRepository();
    
        @GetMapping("/new-form")
        public String process3() {
            return "new-form";
        }
    
        @PostMapping("/save")
        public String process1(
                @RequestParam String username,
                @RequestParam int age,
                Model model) {
    
            Member member = new Member(username, age);
            System.out.println("member = " + member);
    
            memberRepository.save(member);
            model.addAttribute("member", member);
    
            return "save-result";
        }
    
        @GetMapping
        public String process2(Model model) {
            List<Member> members = memberRepository.findAll();
            ModelAndView mv = new ModelAndView("members");
    
            model.addAttribute("members", members);
            return "members";
        }
    
    
    
    }

     

     

    댓글

    Designed by JB FACTORY