스프링은 어노테이션을 활용하여 매우 유연하고 실용적인 컨트롤러를 만들었는데 @ReqeustMapping을 사용하는 컨트롤러가 그것이다.
핸들러 매핑과 핸들러 어댑터의 우선순위가 있는데
HandlerMapping
0 = RequestMappingHandlerMapping : 애노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
1 = BeanNameUrlHandlerMapping : 스프링 빈의 이름으로 핸들러를 찾는다.
HandlerAdapter
0 = RequestMappingHandlerAdapter : 애노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
1 = HttpRequestHandlerAdapter : HttpRequestHandler 처리
2 = SimpleControllerHandlerAdapter : Controller 인터페이스(애노테이션X, 과거에 사용)
처리
다음과 같은 우선순위를 가진다. 그 중 가장 우선순위가 높은 핸들러 매핑과 어댑터를 사용하는 @RequestMapping은 스프링에서 주로 사용되는 컨트롤러 어노테이션이다. 이제 컨트롤러 어노테이션을 활용하여 컨트롤러를 만들어보자!
회원 등록
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으로 구현해봤다.
이전의 하나의 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를 작성해보자
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";
}
}
위 코드는 이전 코드와 동일하게 동작하는 코드들이다. 차이점을 보자면
또한 어노테이션을 사용하며 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";
}