菜園子

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            7 Posts :: 1 Stories :: 31 Comments :: 0 Trackbacks


          Spring MVC經過三個版本,功能已經改進和完善了很多。尤其是2.5以來采用的Annotation的參數綁定,極大的方便了開發,3.0對其進行更進一步的完善。對于一些特殊的前臺框架,傳到后臺的不是普通的request中的參數,而是request流中的xml格式,這時就不能采用SpringMVC自帶的參數綁定方法。這時候考慮是否能擴展一下。

          SpringMVC默認使用的是AnnotationMethodHandlerAdapter.java,可以修改這個類來實現擴展。關鍵位置在如下方法中:

          protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

               ServletHandlerMethodResolver methodResolver= getMethodResolver(handler);

               Method handlerMethod = methodResolver.resolveHandlerMethod(request);

               ServletHandlerMethodInvoker methodInvoker=new ServletHandlerMethodInvoker(methodResolver);

               ServletWebRequest webRequest = new ServletWebRequest(request, response);

               ExtendedModelMap implicitModel = new BindingAwareModelMap();

               Object result=methodInvoker.invokeHandlerMethod(handlerMethod,handler,webRequest, implicitModel);

               ModelAndView mav=methodInvoker.getModelAndView(handlerMethod,handler.getClass(),result, implicitModel, webRequest);    methodInvoker.updateModelAttributes(handler,(mav!=null?mav.getModel():null),implicitModel,webRequest);

               return mav;

              }

          藍色位置是關鍵點,ServletHandlerMethodInvoker.java是內部類,繼承自HandlerMethodInvoker.java,invokeHandlerMethod方法需要擴展,繼續跟蹤這個方法,發現是HandlerMethodInvoker.java這個類的方法,這個方法中的關鍵方法是resolveHandlerArguments(),關鍵部分如下

          if (RequestParam.class.isInstance(paramAnn)) {

          RequestParam requestParam = (RequestParam) paramAnn;

          paramName = requestParam.value();

          required = requestParam.required();

          defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());

          annotationsFound++;

          }

          else if (RequestHeader.class.isInstance(paramAnn)) {

          RequestHeader requestHeader = (RequestHeader) paramAnn;

          headerName = requestHeader.value();

          required = requestHeader.required();

          defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());

          annotationsFound++;

          }

          到此擴展的話需要添加自己的類型,如RequestParamExt,添加在后面,模仿如下:

          else if (RequestParamExt.class.isInstance(paramAnn)) {

          RequestParamExtrequestParam = (RequestParamExt) paramAnn;

          paramName = requestParam.value();

          defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());

          miType = requestParam.type();

          annotationsFound++;

          }

          else if (paramName != null) {

          args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);

          }

          這個方法上面添加擴展邏輯:

          if(!RequestParamExt.TYPE_NONE.equals(miType)){

          if(null == platformRequest){

          HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);

          platformRequest = new PlatformRequest((HttpServletRequest)request, "utf-8");

          platformRequest.receiveData();

          }

          if(RequestParamExt.TYPE_PLATFORMREQUEST.equals(miType)){

              args[i] = platformRequest;

          }

          else if(RequestParamExt.TYPE_STR.equals(miType)){

          args[i] = resolveRequestStrParamExt(platformRequest, methodParam);

          }else{

          args[i] = resolveRequestParamExt(miType,platformRequest,paramName, defaultValue, methodParam, webRequest, handler);

          }

          }

          兩個resolveRequest*Ext方法如下:

          protected Object resolveRequestStrParamExt(PlatformRequest platformRequest, MethodParameter methodParam){

          VariableList inVl = platformRequest.getVariableList();

          String paraName = methodParam.getParameterName();

          return inVl.getValueAsObject(paraName);

          }

          protected Object resolveRequestParamExt(String miType,PlatformRequest platformRequest, String paramName, 

          String defaultValue,MethodParameter methodParam,NativeWebRequest webRequest, Object handler)throws Exception{

          if(StringUtils.isBlank(paramName)){

          paramName = defaultValue;

          }

          Class<?> paramType = methodParam.getParameterType();

          DatasetList inDl = platformRequest.getDatasetList();

          VariableList inVl = platformRequest.getVariableList();

          if(RequestParamExt.TYPE_DS.equals(miType)){//綁定的關鍵過程

          Dataset ds = inDl.getDataset(paramName);

          Object vo = paramType.newInstance();

          MiPDataBinder dataBinder = new MiPDataBinder(vo, false);

              dataBinder.bind(inVl);

              return dataBinder.getTarget();

          }

          }

          同時還需要一個annotation的定義:示例如下:

          package com.company.springext.web.bind.annotation;

          import java.lang.annotation.Documented;

          import java.lang.annotation.ElementType;

          import java.lang.annotation.Retention;

          import java.lang.annotation.RetentionPolicy;

          import java.lang.annotation.Target;

          @Target(ElementType.PARAMETER)

          @Retention(RetentionPolicy.RUNTIME)

          @Documented

          public @interface RequestParamExt {

              public static final String TYPE_NONE            = "none";

              public static final String TYPE_DS              = "ds";

              public static final String TYPE_VL              = "vl";

              public static final String TYPE_STR             = "string";   

          String type() default TYPE_NONE

          String value() default "";    

          String defaultValue() default "ds";

          }

          最后是修改Spring配置:

          <bean class="com.company.springext.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapterExt">    

          </bean>  

          到此就實現了自定義格式的數據綁定。

          對于特定格式的輸出,如果需要自定義的話,同樣需要修改AnnotationMethodHandlerAdapterExt.java這個類,關鍵位置在getModelAndView()方法。在如下位置:

          } else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {

                      handleResponseBody(returnValue, webRequest);

                      return null;

                  }

          添加自己的擴展方法:

          else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBodyExt.class) != null) {

                          ResponseBodyExt bodyMi = AnnotationUtils.findAnnotation(handlerMethod, ResponseBodyExt.class);

                          handleResponseBodyExt(returnValue, webRequest, bodyMi);

                          return null;

                      }

          定義handleResponseBodyExt方法:

           private void handleResponseBodyExt(Object returnValue, ServletWebRequest webRequest, ResponseBodyMI bodyMi) throws Exception {

                      HttpServletResponse servletResponse = (HttpServletResponse) webRequest.getNativeResponse();

                      writeWithExtConverters(returnValue, servletResponse, bodyMi);

                  }

          writeWithExtConverters()方法如下:

           private void writeWithExtConverters(Object returnValue, HttpServletResponse response, ResponseBodyMI bodyMi) throws Exception {            

               convertToXML(...);    

              };

          使用方式如下:

              @RequestMapping(value="/getContractList")

              @ResponseBodyExt(isCheck=true, resultType="sql", sqlColumns="ID,TUREID")

               public Page<Contract> getContractList(@RequestParamExt(value = "ds_search", type = "ds") Contract cp) throws Exception {

          Page<Contract> page = method1();

          return page;

          }



          QQ:24889356
          posted on 2011-09-12 19:12 GhostZhang 閱讀(4291) 評論(6)  編輯  收藏

          Feedback

          # re: Spring MVC 數據綁定的擴展 2011-09-12 20:45 @joe
          有什么用?  回復  更多評論
            

          # re: Spring MVC 數據綁定的擴展 2011-09-13 09:05 tb
          恩 不錯 挺有用的   回復  更多評論
            

          # re: Spring MVC 數據綁定的擴展[未登錄] 2011-09-13 11:13 junxy
          不知道樓主的使用場景是什么?能否介紹下,另外對于一般的格式轉換,他的轉換器就可以滿足需求了..呵呵  回復  更多評論
            

          # re: Spring MVC 數據綁定的擴展 2011-09-13 12:45 GhostZhang
          我們用的是一個特殊的前臺框架,參數是xml格式的,所有的參數都在一個xml中,同時xml是存在request.getInputStream()中,所以不用用原來的轉換器。
            回復  更多評論
            

          # re: Spring MVC 數據綁定的擴展[未登錄] 2011-09-13 20:00 junxy
          @GhostZhang
          為啥參數要用xml格式的呢?我也就是用webservice時遇到過 呵呵   回復  更多評論
            

          # re: Spring MVC 數據綁定的擴展 2011-09-13 21:35 GhostZhang
          因為前臺框架的限制。沒辦法。  回復  更多評論
            


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 芜湖县| 贺兰县| 石泉县| 拉孜县| 赣州市| 长乐市| 姜堰市| 克拉玛依市| 建平县| 邻水| 车险| 井研县| 汽车| 健康| 北京市| 浮山县| 南陵县| 阿鲁科尔沁旗| 潢川县| 广丰县| 翼城县| 博客| 大新县| 遂溪县| 龙井市| 亚东县| 醴陵市| 锡林郭勒盟| 磐石市| 江北区| 上犹县| 皮山县| 天台县| 金堂县| 读书| 正镶白旗| 当阳市| 祁东县| 高雄市| 民县| 曲靖市|