ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • spring[16] Spring MVC 실제 사용법
    개인 공부/spring 2021. 6. 13. 10:22
    728x90
    반응형

    Spring MVC

    스프링은 어노테이션을 활용하여 매우 유연하고 실용적인 컨트롤러를 만들었는데 @ReqeustMapping을 사용하는 컨트롤러가 그것이다.

    • @RequestMapping
      • RequestMappingHandlerMapping
      • RequestMappingHandlerAdapter

    핸들러 매핑과 핸들러 어댑터의 우선순위가 있는데

    HandlerMapping

    0 = RequestMappingHandlerMapping : 애노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
    1 = BeanNameUrlHandlerMapping : 스프링 빈의 이름으로 핸들러를 찾는다.

    HandlerAdapter

    0 = RequestMappingHandlerAdapter : 애노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
    1 = HttpRequestHandlerAdapter : HttpRequestHandler 처리
    2 = SimpleControllerHandlerAdapter : Controller 인터페이스(애노테이션X, 과거에 사용) 
    처리

    다음과 같은 우선순위를 가진다. 그 중 가장 우선순위가 높은 핸들러 매핑과 어댑터를 사용하는 @RequestMapping은 스프링에서 주로 사용되는 컨트롤러 어노테이션이다. 이제 컨트롤러 어노테이션을 활용하여 컨트롤러를 만들어보자!

    1. 회원 등록

       import hello.servlet.domain.member.Member;
       import hello.servlet.domain.member.MemberRepository;
       import org.springframework.stereotype.Controller;
       import org.springframework.web.bind.annotation.RequestMapping;
       import org.springframework.web.servlet.ModelAndView;
       import javax.servlet.http.HttpServletRequest;
       import javax.servlet.http.HttpServletResponse;
       @Controller
       public class SpringMemberSaveControllerV1 {
           private MemberRepository memberRepository = MemberRepository.getInstance();
           @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); 
               memberRepository.save(member);
               ModelAndView mv = new ModelAndView("save-result");
               mv.addObject("member", member);
               return mv;
           }
       }

      지금 까지의 예제인 회원등록을 하는 컨트롤러는 @Controller와 @RequestMapping으로 구현해봤다.

      • @Controller
        -내부에 @Component가 내장되어 있어 스프링 빈으로 등록되며 스프링 MVC에서 어노테이션 기반 컨트롤러로 인식한다.
      • @RequestMapping
        • 메서드 level에서는 요청 정보를 매핑하고 URL이 호출되면 이 메서드가 호출된다. 어노테이션 기반으로 동작하기 때문에 메서드의 이름은 임의로 지어도
          된다.
        • 클래스 level에서는 RequestMappingHandlerMapping에 매핑정보로 인식할 수 있도록 동작시킨다.
      • ModelAndView
        • 모델과 뷰 정보를 담아 반환한다.

    어노테이션 기반의 Controller 통합

    이전의 하나의 url에 대해 하나의 Controller를 매핑해서 프로세스를 진행했던 과거와 달리 어노테이션을 통해 하나의 컨트롤러로 여러 url을 처리할 수 있게 되었다. 아래 코드로 확인해보자! 근데 이건 솔직히 실무나 웹을 만들어봤던 사람이라면 다 알거다...

    import hello.servlet.domain.member.Member;
    import hello.servlet.domain.member.MemberRepository;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.List;
    
    @Controller
    @RequestMapping("/springmvc/v2/members")
    public class SpringMemberControllerV2 {
    
        private MemberRepository memberRepository = MemberRepository.getInstance();
    
        @RequestMapping("/new-form")
        public ModelAndView process1(){
            return new ModelAndView("new-form");
        }
    
        @RequestMapping("/save")
        public ModelAndView process2(HttpServletRequest request, HttpServletResponse response) {
            String username = request.getParameter("username");
            Integer age = Integer.valueOf(request.getParameter("age"));
    
            Member member = new Member(username, age);
            memberRepository.save(member);
    
            ModelAndView mv = new ModelAndView("save-result");
            mv.addObject("member",member);
            return mv;
        }
    
        @RequestMapping
        public ModelAndView process3() {
            List<Member> members = memberRepository.findAll();
            ModelAndView mv = new ModelAndView("members");
            mv.addObject("members",members);
            return mv;
        }
    }

    하지만 실무에서나 실제 웹을 개발할때 봤던 코드보다 아쉬운게 ModelAndView 객체를 반환해야 한다는 것이다. 그리고 HttpServlet의 기능들도 controller에서 직접 사용하여야하고 이 아쉬운 점 어디서 많이 본거 같지 않을까? 맞다 이전 Controller를 직접 만들때 V3와 V4의 개선 점과 동일하다. 그래서 이 점을 개선하여 다시 Controller를 작성해보자

    실무에서 사용되는 Controller 코드

    import hello.servlet.domain.member.Member;
    import hello.servlet.domain.member.MemberRepository;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import java.util.List;
    
    @Controller
    @RequestMapping("/springmvc/v3/members")
    public class SpringMemberControllerV3 {
        private MemberRepository memberRepository = MemberRepository.getInstance();
    
        @RequestMapping("/new-form")
        public String process1(){
            return "new-form";
        }
    
        @RequestMapping("/save")
        public String process2(@RequestParam("username") String username, @RequestParam("age") int age, Model model) {
            Member member = new Member(username, age);
            memberRepository.save(member);
    
            model.addAttribute("member", member);
            return "save-result";
        }
    
        @RequestMapping
        public String process3(Model model) {
            List<Member> members = memberRepository.findAll();
    
            model.addAttribute("members", members);
            return "members";
        }
    }

    위 코드는 이전 코드와 동일하게 동작하는 코드들이다. 차이점을 보자면

    1. 더이상 ModelAndView 객체를 반환하지 않아도 된다.
    2. HttpServlet 기술들을 직접 사용하지 않는다.
    3. HttpServletRequest를 대체하는 @ReqeustParma을 통해 직접 사용자의 파라미터 정보를 가져온다.
    4. HttpServletResponse를 대체하는 Model 객체가 존재하므로 view로 전달되는 데이터는 모두 model 객체에 담아서 넘기면 된다.

    또한 어노테이션을 사용하며 method의 방식도 설정할 수 있는데

    @RequestMapping(value = "/new-form", method = RequestMethod.GET)
    public String process1(){
        return "new-form";
    }
    
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public String process2(@RequestParam("username") String username, @RequestParam("age") int age, Model model) {
        Member member = new Member(username, age);
        memberRepository.save(member);
    
        model.addAttribute("member", member);
        return "save-result";
    }
    
    @RequestMapping(method = RequestMethod.GET)
    public String process3(Model model) {
        List<Member> members = memberRepository.findAll();
    
        model.addAttribute("members", members);
        return "members";
    }

    다음과 같이 method를 사용하거나 @GetMapping, @PostMapping을 통해 method의 방식도 설정하여 사용할 수 있다.

    @GetMapping(value = "/new-form")
    public String process1(){
        return "new-form";
    }
    
    @PostMapping(value = "/save")
    public String process2(@RequestParam("username") String username, @RequestParam("age") int age, Model model) {
        Member member = new Member(username, age);
        memberRepository.save(member);
    
        model.addAttribute("member", member);
        return "save-result";
    }
    
    @GetMapping
    public String process3(Model model) {
        List<Member> members = memberRepository.findAll();
    
        model.addAttribute("members", members);
        return "members";
    }

    출처 https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8

    728x90
    반응형
Designed by Juno.