13.11. Convention over configuration 3

마지막으로 살펴볼 CoC는 ModelAndView 객체의 View에 해당하는 논리적인 View의 이름에 관련된 것입니다.

요청 -> view 이름 :: DefaultRequestToViewNameTranslator

앞에서 살펴봤던 예제 코드를 다시 살펴보겠습니다.

    public ModelAndView list(HttpServletRequest request, HttpServletResponse response){
        return new ModelAndView(“issue/list”)
            .addObject(issueService.getAll());
    }

여기서 논리적인 뷰의 이름으로 issue/list 를 넘겨주고 있습니다. 이 이름은 다음과 같은 ViewReslover에 의해 WEB-INF/jsp/issue/list.jsp 를 랜더링 하게 됩니다.

    <bean id=”viewResolver”
        class=”org.springframework.web.servlet.view.InternalResourceViewResolver”>
        <property name=”viewClass”
            value=”org.springframework.web.servlet.view.JstlView” />
        <property name=”prefix” value=”/WEB-INF/jsp/” />
        <property name=”suffix” value=”.jsp” />
    </bean>

DefaultRequestToViewNameTranslator 를 사용하면 요청을 바탕으로 논리적인 View 이름을 생성하여 ViewResolver에 넘겨주게 됩니다. 특히나 이 클래스는 Spring의 DispatcherServlet  이 기본으로 가지고 있기 때문에 명시적으로 선언하지 않아도 됩니다.

샘플
 http://localhost:8080/gamecast/display.html -> display
 http://localhost:8080/gamecast/displayShoppingCart.html -> displayShoppingCart
 http://localhost:8080/gamecast/admin/index.html -> admin/index

위의 ModelAndView 코드를 다음과 같이 수정할 수 있습니다.

    public ModelAndView list(HttpServletRequest request, HttpServletResponse response){
        return new ModelAndView()
            .addObject(issueService.getAll());
    }

이렇게 보니까 ModelAndView 라는 이름이 어색하지 않게 보이네요. 🙂

13.11. Convention over configuration 2

이번에는 MVC중에서 M 즉 모델에 적용할 수 있는 Convention을 살펴보겠습니다.

Spring의 컨트롤러에서 모델을 넘겨줄 때 ModelAndView 객체를 사용합니다. 보통은 다음과 같이 사용합니다.

    public ModelAndView list(HttpServletRequest request, HttpServletResponse response){
        return new ModelAndView(“issue/list”, “issueList”, issueService.getAll());
    }

또는 뷰와 모델을 명확하게 구분하기 위해 다음과 같이 사용합니다.

    public ModelAndView list(HttpServletRequest request, HttpServletResponse response){
        return new ModelAndView(“issue/list”)
            .addObject(“issueList”, issueService.getAll());
    }

갑자기 기억나는 이야기지만 객체의 이름은 ModelAndView인데 View먼저 등록하니까 이름을 ViewAndModel로 해야하는 것 아니였나.. 라는 글이 생각납니다.

Anyway addObject 메소드가 오버로딩으로 또 다른 메소드 하나가 더 존재합니다. 그것을 사용하면 코드를 다음과 같이 변경 할 수 있습니다.

    public ModelAndView list(HttpServletRequest request, HttpServletResponse response){
        return new ModelAndView(“issue/list”)
            .addObject(issueService.getAll());
    }

모델의 이름이 생략됐습니다.

바로 이겁니다. 모델의 이름을 생략할 수 있습니다. 생략하고 보내면 View에서는 그럼 이 모델을 어떤 이름으로 찾게 될 것인가?

if(객체타입 == List || Set || 배열){
    객체의 camel-case 맨 뒤에 List를 붙인 이름을 가지게 됩니다.
} else {
    객체의 camel-case 이름을 가지게 됩니다.
}

샘플
x.y.Foo 타입의 객체는 foo 라는 이름을 가지게 됩니다.
x.y.z.FooBar 타입의 객체는 fooBar 라는 이름을 가지게 됩니다.
List<Foo> 타입의 객체는 fooList 라는 이름을 가지게 됩니다.
FooBar[] 타입의 객체는 fooBarList 라는 이름을 가지게 됩니다.

이 메소드를 사용할 때 한 가지 주의할 것이 있습니다.

Note: Empty Collections are not added to the model when using this method because we cannot correctly determine the true convention name. View code should check for null rather than for empty collections as is already done by JSTL tags.

비어있는 콜렉션을 추가할 수 없다는 군요.

Web Layer

Web Layer

이 계층에서 다루는 주요 기능 두가지
– Navigation Logic 담당
– Domain model 과 Service Layer의 중계자 역할

특징
– servlet 으로 간단하게 구현될 수 있다. 이런 servlet은 request 파라미터를 객체로 바꾸고 service 인터페이스의 메소드를 호출한다.
– 유저들을 위해서 비즈니스 exception들을 적당한 에러 메시지로 바꿔야 하는 책임도 있다.

Spring MVC가 하는 일
– Spring MVC는 request 파라미터를 비즈니스 로직이 직접 작동할 수 있는 POJO로 맵핑하는 등의 request 파라미터와 비즈니스 로직 계층간의 복잡한 메카니즘을 제공한다.
– Spring은 request들을 처리하고 확장이 편하도록 복잡한 업무 흐름을 구현하고 있다.

종속성
-Service Layer(web에서 받은 정보를 service layer에 전해 줄 domain 객체로 전환)
-Domain Layer
사용자 삽입 이미지Spring MVC Web Layer API
org.springframework.web.servlet.mvc.Controller 인터페이스
– HttpServletRequest와 HttpServletResponse를 받을 때 필요하다.
– client에게 정보를 돌려줄 때 ModelAndView 객체를 만든다.