2011-03-03

Spring MVC 3.0.5 之二

  • Handler mappings
    • Spring 2.5 以後 DispatcherServlet 預設使用 DefaultAnnotaionHandlerMapping 去找 @Controller 裡的 @RequestMapping,所以不用在 xml 裡定義 handler mapping 了。
    • DefaultAnnotaionHandlerMapping 有些屬性可以設定:
      • interceptors
      • defaultHandler - 找不到符合的 handler 時,設定預設的 handler。
      • order - 設定多筆 handler mapping 時使用。
      • alwaysUseFullPath - 假設 servlet 過濾的 url pattern 為 /abc/*,一個 request 的 url 為 /abc/def.do,若設為 true,則用 /abc/def.do 去找 handler,若設為 false,則用 /def.do 去找,預設為 false。
      • urlDecode - 預設為 true。
      • lazyInitHandlers - 用來將 singleton handler lazy init,預設為 false。
        <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
            <property name="interceptors">
                <bean class="example.MyInterceptor"/>
            </property>
        </bean>
    • HandlerInterceptor
      • 可以實作 HandlerInterceptor 或繼承 HandlerInterceptorAdapter。
      • preHandle - handler 執行前呼叫,可回傳 false,表示已自行處理 request,不用再執行 handler。
      • postHandle - handler 執行完成後呼叫。
      • afterCompletion - 整個 request 處理完畢時呼叫。
  • Resolving views
    • Spring 在 view 的處理上有兩個 interface:
      • ViewResolver - 將 view name 對應到 view 物件上。
      • View - view 物件。
    • handler method 必須回傳 view name:
      • 精確的方式,可以回傳 view name、ModelAndView、View。
      • 模糊的方式,使用程式慣例。
    • Spring 支援的 view resolver:
      • AbstractCachingViewResolver - 支援 view cache,可以設定 cache 為 false 來關閉 cache 功能。
      • XmlViewResolver - 使用 Spring XML bean 風格的設定檔。
      • ResourceBundleViewResolver - 使用 properties 風格的設定檔。
      • UrlBasedViewResolver - 模糊的方式,將 url 視為 view name。
      • InternalResourceViewResolver - 繼承 UrlBasedViewResolver,支援像 JstlView 或 TilesView 之類的 InternalResourceVie,可以自訂 view class。
      • VelocityViewResolver / FreeMarkerViewResolver - 繼承 UrlBasedViewResolver,支援 Velocity / FreeMarker。
      • ContentNegotiatingViewResolver 
    • 使用 JSP view
      <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
          <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
          <property name="prefix" value="/WEB-INF/jsp/"/>
          <property name="suffix" value=".jsp"/>
      </bean>
    • 使用多種 view
      • 以 [view name].(class) 設定 view class。
      • 以 [view name].url 設定 view url。
      • 可以設定 defaultParentView,其他 view 都會繼承這個 defaultParentView。
        <bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
            <property name="basename" value="views"/>
            <property name="defaultParentView" value="parentView"/>
        </bean>
    • Spring 支援同時使用多種 view resolver,可以用 order 屬性決定執行順序,數值愈大優先權愈低。
      • Spring 從 order 數值小的開始找,如果沒找到才會往下一個 view resolver 去找。
      • 有些 view resolver 找不到合適的 view 時會回傳 null,這種的 view resolver 適合放在隊伍前面,而像 InternalResourceViewResolver 這種無法決定是否有符合的 view 存在的就一定要排在後面。
    • Redirect
      • 使用 RedirectView class。
      • 使用 redirect: 字首,用在 UrlBasedViewResolver 與其子類別。
    • Forward
      • UrlBasedViewResolver 與其子類別支援 forward: 字首。
  • Locale
  • Theme
  • File upload
    • Spring 預設不處理 file upload,必須加上以下的設定,並加入commons-fileupload.jar。
      <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
          <!-- maximum file size in bytes -->
          <property name="maxUploadSize" value="100000"/>
      </bean>
    • form 要加上 enctype="multipart/form-data"。
      <form method="post" action="/form" enctype="multipart/form-data">
          <input type="text" name="name"/>
          <input type="file" name="file"/>
          <input type="submit"/>
      </form>
    • handler 的 request 要用 MultipartHttpServletRequest,用 MultipartFile 取檔案。
      @RequestMapping(value = "/form", method = RequestMethod.POST)
      public String handleFormUpload(@RequestParam("name") String name, @RequestParam("file") MultipartFile file) {
          if (!file.isEmpty()) {
              byte[] bytes = file.getBytes();
              // ...
              return "redirect:uploadSuccess";
          } else {
              return "redirect:uploadFailure";
          }
      }
  • Exception
    • 可以實做 HandlerExceptionResolver。
    • 或者直接使用 SimpleMappingExceptionResolver 設定 exception 與 view name 的對應,
    • 或者使用 @ExceptionHandler,僅是用於該 @Controller 裡的 @RequestMapping,傳入的 method param 與回傳值與 @RequestMapping 一樣有彈性,@ExceptionHandler 也可以傳入 exception array,或者不輸入,以 method param 定義為依據。
      @ExceptionHandler(IOException.class)
      public String handleIOException(IOException ex, HttpServletRequest request) {
          return ClassUtils.getShortName(ex.getClass());
      }
  • Convention over configuration
    • 主要用在 model、view、controller 三部份。
    • 有了 annotation 之後,coc 幾乎沒用了,只剩下 view 有用。
    • Spring 提供 ReqeustToViewNameTranslator 與其實作 DefaultRequestToViewNameTranslator,當 handler method 沒有提供 view name 時,就會以 url 為 view name。
  • mvc namespace
    • mvc:annotation-driven
      • 為了使用 @Controller,必須註冊 DefaultAnnotationHandlerMapping 與 AnnotationHandlerMethodAdapter 這兩個 bean,mvc:annotation-driven 就是用合理的預設值來註冊這兩個 bean。
    • mvc:interceptors
      • 設定 HandlerInterceptor 或 WebReqeustInterceptor。
      • 可以套用到所有的 request,或者指定 url pattern。
        <mvc:interceptors>
            <bean class="org.example.SecurityInterceptor" />
            <mvc:interceptor>
                <mapping path="/secure/*"/>
                <bean class="org.example.SecurityInterceptor" />
            </mvc:interceptor>
        </mvc:interceptors>
    • mvc:view-controller
      • 用來註冊 ParameterizableViewController。
      • 不用經過 handler,直接跳到 view 去。
        <mvc:view-controller path="/" view-name="home"/>
    • mvc:resources
      • 用於靜態檔案 mapping 與 cache。
      • mapping 屬性使用 Ant pattern。
      • location 屬性可以設定一或多個目錄位置,用逗號區隔多筆,順序有關係,可以用 classpath: 字首。
      • 可以加上 cache-period 來設定暫存時間,以秒為單位,建議搭配 version 字串來強制更新版本。
        <mvc:resources mapping="/resources/**" location="/public-resources/"/>
    • mvc:default-servlet-handler
      • ...

沒有留言:

張貼留言