JPA培训———Spring MVC数据绑定的扩展



Spring MVC经过三个版本,功能已经改进和完善了很多。尤其是2.5以来采用的Annotation的参数绑定,极大的方便了开发,3.0对其进行更进一步的完善。


Spring MVC经过三个版本,功能已经改进和完善了很多。尤其是2.5以来采用的Annotation的参数绑定,极大的方便了开发,3.0对其进行更进一步的完善。对于一些特殊的前台框架,传到后台的不是普通的request中的参数,而是request流中的xml格式,这时就不能采用SpringMVC自带的参数绑定方法。这时候考虑是否能扩展一下。

SpringMVC默认使用的是AnnotationMethodHandlerAdapter.java,可以修改这个类来实现扩展。关键位置在如下方法中:

1. otected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 

2.  

3.      ServletHandlerMethodResolver methodResolver= getMethodResolver(handler); 

4.  

5.      Method handlerMethod = methodResolver.resolveHandlerMethod(request); 

6.  

7.      ServletHandlerMethodInvoker methodInvoker=new ServletHandlerMethodInvoker(methodResolver); 

8.  

9.      ServletWebRequest webRequest = new ServletWebRequest(request, response); 

10.  

11.      ExtendedModelMap implicitModel = new BindingAwareModelMap(); 

12.  

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

14.  

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

16.  

17.      return mav; 

18.     } 

蓝色位置是关键点,ServletHandlerMethodInvoker.java是内部类,继承自HandlerMethodInvoker.java,invokeHandlerMethod方法需要扩展,继续跟踪这个方法,发现是HandlerMethodInvoker.java这个类的方法,这个方法中的关键方法是resolveHandlerArguments(),关键部分如下:

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

2. RequestParam requestParam = (RequestParam) paramAnn; 

3. paramName = requestParam.value(); 

4. required = requestParam.required(); 

5. defaultValue = parseDefaultValueAttribute(requestParam.defaultValue()); 

6. annotationsFound++; 

7. 

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

9. RequestHeader requestHeader = (RequestHeader) paramAnn; 

10. headerName = requestHeader.value(); 

11. required = requestHeader.required(); 

12. defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue()); 

13. annotationsFound++; 

14. 

到此扩展的话需要添加自己的类型,如RequestParamExt,添加在后面,模仿如下:

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

2. RequestParamExtrequestParam = (RequestParamExt) paramAnn; 

3. paramName = requestParam.value(); 

4. defaultValue = parseDefaultValueAttribute(requestParam.defaultValue()); 

5. miType = requestParam.type(); 

6. annotationsFound++; 

7. 

1. else if (paramName != null) { 

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

3. 

这个方法上面添加扩展逻辑:

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

2. if(null == platformRequest){ 

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

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

5. platformRequest.receiveData(); 

6. 

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

8.     args[i] = platformRequest; 

9. 

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

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

12. }else

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

14. 

15. 

两个resolveRequest*Ext方法如下:

1. protected Object resolveRequestStrParamExt(PlatformRequest platformRequest, MethodParameter methodParam){ 

2. VariableList inVl = platformRequest.getVariableList(); 

3. String paraName = methodParam.getParameterName(); 

4. return inVl.getValueAsObject(paraName); 

5. 

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

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

8. if(StringUtils.isBlank(paramName)){ 

9. paramName = defaultValue; 

10. 

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

12. DatasetList inDl = platformRequest.getDatasetList(); 

13. VariableList inVl = platformRequest.getVariableList(); 

14. if(RequestParamExt.TYPE_DS.equals(miType)){//绑定的关键过程 

15. Dataset ds = inDl.getDataset(paramName); 

16. Object vo = paramType.newInstance(); 

17. MiPDataBinder dataBinder = new MiPDataBinder(vo, false); 

18.     dataBinder.bind(inVl); 

19.     return dataBinder.getTarget(); 

20. 

21. 

同时还需要一个annotation的定义:示例如下:

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

2. import java.lang.annotation.Documented; 

3. import java.lang.annotation.ElementType; 

4. import java.lang.annotation.Retention; 

5. import java.lang.annotation.RetentionPolicy; 

6. import java.lang.annotation.Target; 

7. @Target(ElementType.PARAMETER) 

8. @Retention(RetentionPolicy.RUNTIME) 

9. @Documented 

10. public @interface RequestParamExt { 

11.     public static final String TYPE_NONE            = "none"

12.     public static final String TYPE_DS              = "ds"

13.     public static final String TYPE_VL              = "vl"

14.     public static final String TYPE_STR             = "string";    

15. String type() default TYPE_NONE;  

16. String value() default "";     

17. String defaultValue() default "ds"

18. 

最后是修改Spring配置:

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

2. </bean>   

到此就实现了自定义格式的数据绑定。

对于特定格式的输出,如果需要自定义的话,同样需要修改AnnotationMethodHandlerAdapterExt.java这个类,关键位置在getModelAndView()方法。在如下位置:

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

2.             handleResponseBody(returnValue, webRequest); 

3.             return null

4.         } 

添加自己的扩展方法:

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

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

3.                 handleResponseBodyExt(returnValue, webRequest, bodyMi); 

4.                 return null

5.             } 

定义handleResponseBodyExt方法:

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

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

3.            writeWithExtConverters(returnValue, servletResponse, bodyMi); 

4.        } 

writeWithExtConverters()方法如下:

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

2.     convertToXML(...);     

3.    }; 

使用方式如下:

1. @RequestMapping(value="/getContractList"

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

3.  

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

5. Page<Contract> page = method1(); 

6. return page; 

7. 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值