 
 
스프링 MVC 적용하면서 대강 정리한 "노트"입니다. 팁이라고하기엔 좀 모자란듯...^^ (오류가 있을수도 있으니 너무 맹신하지는 마세요..-.-); 
 -. 한 웹app에 여러개의 *-servlet.xml 사용하기 - web.xml에서 원하는 만큼 DispatcherServlet을 선언하고 그 서블릿이름에 대응하는 [servlet-name]-servlet.xml을 작성한다. - 이렇게 하면 한개의 웹APP 내부에서 웹자원을 몇개의 그룹으로 나누어 별도로 설정하는 것이 가능해진다. 
 -. 웹자원에 AOP 적용하기 - 핸들러 매핑에 인터셉터를 걸면 된다. 
  <bean id="signonInterceptor" class="xxx.SignonInterceptor">     <property name="signonView">       <value>redirect:/login_form.html</value>     </property>   </bean> 
  <bean id="handlerMapping"     class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">     <property name="interceptors">       <list>         <ref bean="signonInterceptor"/>       </list>     </property>     <property name="mappings">       .... .... 
    </property>   </bean> 
- 그럼 Controller를 통하지 않고 호출되는 JSP에 AOP 적용하려면? => 우선은 web.xml에서 jsp 자원들이 DispatcherServlet을 타도록 만든다음 UrlFilenameViewController를 이용한다. - 위의 SimpleUrlHandlerMapping 의 mappings 속성을 아래처럼 설정한다.(패턴은 적절히 수정) 
      <property name="mappings">          <props>             <prop key="*">jspViewController</prop>          </props>       </property>      .... .... 
   <bean id="jspViewController"       class="org.springframework.web.servlet.mvc.UrlFilenameViewController" /> 
 - 그럼 특정 자원에 대해서만 AOP를 적용하지 않으려면?(ex: 로그인폼과 로그인콘트롤러에는 인증인터셉터를 걸면 안된다...) => AOP적용하면 안되는 자원에 대한 핸들러 매핑을 추가로 설정하고 우선 순위를 부여한다. (아래에서 publicHandlerMapping에는 인증인터셉터가 없다) 
  <bean id="publicHandlerMapping"     class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">     <property name="order"><value>1</value></property>     <property name="mappings">          <props>             <prop key="/signon/LoginForm.do">jspViewController</prop>             <prop key="/signon/Login.do">signonController</prop>          </props>     </property>   </bean> 
  <bean id="protectedHandlerMapping"     class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">     <property name="order"><value>2</value></property>     <property name="interceptors">       <list>         <ref bean="signonInterceptor"/>       </list>     </property>     <property name="mappings">          <props>             <prop key="*">jspViewController</prop>          </props>     </property>   </bean> 
- 위와 같은 설정에서 /signon/Login.do 요청이 들어오면 url패턴은 publicHandlerMapping과 protectedHandlerMapping에 모두 해당된다 할지라도 order 순위에 의해 publicHandlerMapping이 그 요청을 처리하게 된다. 
 -. ModelAndView에 여러 개의 객체를 저장하기 - Map을 만들어 거기에 적절한 이름으로 저장하면 된다. 
 return new ModelAndView(this.successView, map); 
- JSP에서는 Map에 저장된 키로 request 스코프에서 꺼내어 쓰면된다. 
 -. 콘트롤러 실행후 특정 url로 redirect하는 방법 - ModelAndView에 넘길 url 앞에 redirect: 접두문자열을 붙여주면 된다. 
 <bean name="xxxController" class="xxx.XxxController">     <property name="successView"><value>redirect:/admin/XXXForm.do</value></property>   </bean> 
 -. 에러 종류별로 에러페이지 다르게 지정하기- exception resolver 빈을 설정한다. exception resolver는 콘트롤러에서 발생한 에러를 잡아낸다. 
 <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">   <property name="exceptionMappings">    <props>     <prop key="org.springframework.dao.DataIntegrityViolationException">DupError.jsp</prop>     <prop key="org.springframework.dao.DataAccessException">DBError.jsp</prop>     <prop key="java.lang.Exception">Error.jsp</prop>    </props>   </property>  </bean> 
- exceptionMappings의 각 키의 속성값은 exception 타입별 jsp 페이지 경로이며 이 또한 view resolver에 의해 해석된다(만약 뷰resolver에 suffix를 .jsp로 주었다면 위의 설정에서 Error.jsp는 그냥 Error로 설정해야할 것이다). - 의문 : 위 설정이 콘트롤러에서 포워딩되는 JSP에도 적용이 되는가? => 안된다!!! - jsp에서 발생한 에러는 jsp 페이지에 선언한 error 페이지로 가거나 jsp에서 error 페이지 선언을 안했으면 web.xml에 정의한 error 페이지로 간다.
  - SimpleFormController 를 이용할 경우엔 onSubmit 메소드안에서  try {      if (siteForm.isNewSite()) {   this.siteService.insertSite(siteForm.getSite());      } else {   this.siteService.updateSite(siteForm.getSite());      }  } catch (DataIntegrityViolationException ex) {      errors.rejectValue(       "site.siteip",       "SITE_IP_ALREADY_EXISTS",       "Site IP already exists: choose a different Site ip.");      return showForm(request, response, errors);  } 이런식으로 에러처리가 가능하다. 
 -. 프로세스 처리 과정 - Handler mappings가 url을 분석하여 Controllers 선택 => Controllers는 로직수행후 지정된 View를 생성 => ViewResolvers는 뷰를 해석 => 해석된 뷰로 포워딩 
 -. 핸들러 매핑 - 여러개의 핸들러 매핑이 있을 때 순서를 부여할 수 있다. - 패턴 사용가능하다... 특정 패턴의 url을 하나의 콘트롤러에 매핑할 수 있다. - url 별로 빈네임을 설정하기 위해서 : SimpleUrlHandlerMapping 이용 - url을 바로 빈네임으로 사용하기 위해서 : BeanNameUrlHandlerMapping 이용(아래 소스) 
    <bean id="handlerMapping"           class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> 
    <bean name="/editaccount.form"           class="org.springframework.web.servlet.mvc.SimpleFormController">         <property name="formView"><value>account</value></property>         <property name="successView"><value>account-created</value></property>         <property name="commandName"><value>Account</value></property>         <property name="commandClass"><value>samples.Account</value></property>     </bean> 
- setAlwaysUseFullPath 속성에 대한 API 설명 읽어볼것. 
=> setAlwaysUseFullPath 속성이 false(default)일 때 web.xml에서 /abc/* 로 매핑한 상태에서 url요청이 /abc/test.do 로 들어왔다면 빈네임은 /test.do 로 해야한다는 것이다. 
 -. 무한루핑 피하기 
[web.xml] "test"라는 이름의 Dispatcher 서블릿에 대한 url 패턴매핑 : /test/jsp/* 
[test-servlet.xml] : test Dispatcher 서블릿에 대한 컨텍스트 파일 
<bean id="viewResolver"       class="org.springframework.web.servlet.view.UrlBasedViewResolver">     <property name="prefix"><value>/test/jsp/</value></property>     <property name="suffix"><value>.jsp</value></property> </bean> 
=> 이 상황에서 viewResolver에 의한 url 조합이 web.xml의 서블릿 매핑 패턴과 일치하면 무한루프에 빠진다. 주의할 것. 
 -. UrlFilenameViewController - UrlFilenameViewController은 url에서 파일명 부분만 빼내어 뷰 url을 만든다. 즉 url이 /foo/bar/test.do 로 들어오건 /bar/foo/test.do로 들어오건 상관없이 뷰 url은 test가 된다. - 따라서 UrlFilenameViewController를 쓸 경우에는 경로는 다르지만 이름은 동일한 매핑은 없는지 주의해야 한다. 
-. JSP에서 스프링 빈 참조하기- servlet context로부터 스프링 WebApplicationContext를 얻은 후 거기서 빈을 액세스한다. 
  WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);   SomeBean = (SomeBean)wac.getBean("beanName"); 
- 그러나 이 방법은 너무 힘들어보인다. 그래서 혹시나해서 스프링 태그라이브러리를 찾아보았다. 
- 스프링 태그라이브러리에는 빈을 직접 리턴해주는 태그가 안보인다...왜 없을까? 
=> 아시는분? JSTL 때문일까? bind 태그를 잠깐 봤는데... 잘이해안됨. 
=> 내가 바라는 건 콘트롤러 통하지 않는 JSP에서 특정 빈의 속성값을 쉽게 액세스하고 싶은거다. 
 -. web.xml에 대한 푸념 - web.xml에서 서블릿 url 패턴매핑에 *.foo 나 /foo/*는 되는데 이 둘의 조합은 왜 안될까? => 패턴의 우선 순위 등이 문제일까? 심플하게 갈려고? 
- 에러페이지 설정하는데 Exception 클래스 타입별로 다른 에러페이지를 지정했는데, 예외 클래스간의 관계가 부모자식인게 있으면 최상위 부모 클래스에 대한 에러페이지가 보여진다. => 왜 상식과 어긋나게 행동하게 했는지... 
 -. web.xml에서의 url 패턴매핑에 대한 의견 - 개인적으로 /foo/* 식의 패턴매핑은 바람직하지 않다고 생각한다. 왜냐면 static 자원(html,image 등)도 서블릿을 타게 만들기 때문이다. 물론 컨테이너 앞단에 웹서버를 둔다면 어차피 static 자원은   웹서버가 처리하기 때문에 상관은 없겠지만... 하여간 *.foo 식의 패턴을 사용하는게 좋다고 생각한다. 
 -. 정적 자원에 대한 의문 - 서블릿/jsp 에서 static 자원으로 포워딩했을 때 컨테이너에서 도대체 무슨일이 벌어지는 걸까?   쓰레드 제어권이 static 자원으로 넘어갈리는 없을테고... redirect같은 특수한 응답헤더가 존재하는가? |  
 
 |