스프링 Controller와 RequestMapping 어노테이션
개요
: 스프링 프로젝트의 편리한 기능으로 컨트롤러 동작방식을 살펴본다.
참고한 블로그
https://yeonyeon.tistory.com/m/116
핵심 어노테이션
- @Controller
- 내부에 @Component 어노테이션이 존재해 컴포넌트 스캔의 대상
- 스프링이 자동으로 스프링 빈으로 등록
- 스프링 MVC에서 어노테이션 기반 컨트롤러로 인식하게 함
- @RequestMapping
- 요청 정보를 매핑
- 해당 url이 호출되면 해당 메소드가 호출
- 어노테이션 기반 동작이기 때문에 메소드 이름은 자유
핸들러 매핑과 핸들러 어댑터 중 가장 우선순위가 높은 것은 RequestMappingHandlerMapping, RequestMappingHandlerAdapter이다. @RequestMapping의 앞글자를 따서 만들어졌다
V1 구현
: 버전1의 구현 예제를 살펴본다.
SpringMemberFormControllerV1
@Controller
public class SpringMemberFormControllerV1 {
// 새로운 멤버를 생성하기위한 폼 화면을 호출하는 맥락이다.
@RequestMapping("/springmvc/v1/members/new-form")
private ModelAndView process() {
return new ModelAndView("new-form");
}
}
SpringMemberSaveControllerV1
@Controller
public class SpringMemberSaveControllerV1 {
private MemberRepository memberRepository = MemberRepository.getInstance();
// 폼에 입력한 멤버를 DB에 저장하는 맥락이다.
@RequestMapping("/springmvc/v1/members/save")
private ModelAndView process(HttpServletRequest req, HttpServletResponse res) {
String username = req.getParameter("username");
int age = Integer.parseInt(req.getParameter("age"));
Member member = new Member(username, age);
memberRepository.save(member);
ModelAndView mv = new ModelAndView("save-result");
mv.addObject("member", member);
return mv;
}
}
SpringMemberListControllerV1
@Controller
public class SpringMemberListControllerV1 {
MemberRepository memberRepository = MemberRepository.getInstance();
// DB에 저장된 멤버들을 꺼내어 화면에 전달하는 맥락이다.
@RequestMapping("/springmvc/v1/members")
public ModelAndView process() {
List<Member> members = memberRepository.findAll();
ModelAndView mv = new ModelAndView("members");
mv.getModel().put("members", members);
return mv;
}
}
결론
: V1 컨트롤러 동작과정은 맥락만 파악하여 전체적인 흐름을 살펴본다.
- 코드가 훨씬 간편해진 것이 보이지만 @RequestMapping이 클래스가 아닌 메소드 단위에 적용되어 있다.
V2 컨트롤러에서 클래스를 좀 더 유연하게 통합해보자.
V2 구현
: 버전1보다 유연한 버전2의 구현 예제를 살펴본다.
SpringMemberControllerV2
@Controller
@RequestMapping("/springmvc/v2/members")
public class SpringMemberControllerV2 {
MemberRepository memberRepository = MemberRepository.getInstance();
// 새로운 멤버를 생성하기위한 폼 화면을 호출하는 맥락이다.
@RequestMapping("/new-form")
private ModelAndView newForm() {
return new ModelAndView("new-form");
}
// DB에 저장된 멤버들을 꺼내어 화면에 전달하는 맥락이다.
@RequestMapping
public ModelAndView members() {
List<Member> members = memberRepository.findAll();
ModelAndView mv = new ModelAndView("members");
mv.getModel().put("members", members);
return mv;
}
// 폼에 입력한 멤버를 DB에 저장하는 맥락이다.
@RequestMapping("/save")
private ModelAndView save(HttpServletRequest req, HttpServletResponse res) {
String username = req.getParameter("username");
int age = Integer.parseInt(req.getParameter("age"));
Member member = new Member(username, age);
memberRepository.save(member);
ModelAndView mv = new ModelAndView("save-result");
mv.addObject("member", member);
return mv;
}
}
결론
: V2 컨트롤러 동작과정은 V1 컨트롤러의 분리된 내용이 통합되어있다. 이로인해 java 컨트롤러를 추가로 작성할 필요가 없어졌다.
- 클래스 3개로 분리되었던 작업이 단 하나의 파일로 줄어들었다.
- 통합시 리턴타입은 전과 동일하지만 기존 process() 메소드명이 각각의 역할별 메소드명으로 정의되었다.
- RequestMapping이 클래스에도 붙고 메소드에도 붙는다.
- RequestMapping를 클래스레벨에 적용한 경로는 생략한 경로를 메소드레벨에서 리턴 경로로 이어서 작성한 모습이 보인다.
- 위와 같은 경우에 save()를 부르려면 /spingmvc/v2/members/save로 접근하면 된다.
V2 컨트롤러에서 아직 불편한점이 남아있다.
ModelAndView를 매번 생성하고 반환해주는게 좀 번거롭게 느껴진다. 실무에서 사용하는 것과 가깝게 개선해보자.
V3 구현
: 버전3의 구현 예제를 살펴본다.
SpringMemberControllerV3
@Controller
@RequestMapping("/springmvc/v3/members")
public class SpringMemberControllerV3 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@RequestMapping("/new-form")
private String newForm() {
return "new-form";
}
@RequestMapping
public String members(Model model) {
List<Member> members = memberRepository.findAll();
model.addAttribute("members",members);
return "members";
}
@RequestMapping("/save")
private String save(@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";
}
}
결론
: V3 컨트롤러 동작과정은 V2 컨트롤러의 중복된 객체 생성을 제거했다.
- 리턴타입이 ModelAndView 에서 String 타입으로 변경되었다.
- 이로인해 ModelAndView 를 매번 생성하지 않아도 된다.
- (기타내용)@RequestParam: HttpServletRequest가 아니라 파라미터를 직접 받아올 수 있다.
Leave a comment