Spring MVC數(shù)據(jù)綁定的擴(kuò)展
Spring MVC經(jīng)過(guò)三個(gè)版本,功能已經(jīng)改進(jìn)和完善了很多。尤其是2.5以來(lái)采用的Annotation的參數(shù)綁定,極大的方便了開發(fā),3.0對(duì)其進(jìn)行更進(jìn)一步的完善。對(duì)于一些特殊的前臺(tái)框架,傳到后臺(tái)的不是普通的request中的參數(shù),而是request流中的xml格式,這時(shí)就不能采用SpringMVC自帶的參數(shù)綁定方法。這時(shí)候考慮是否能擴(kuò)展一下。
SpringMVC默認(rèn)使用的是AnnotationMethodHandlerAdapter.java,可以修改這個(gè)類來(lái)實(shí)現(xiàn)擴(kuò)展。關(guān)鍵位置在如下方法中:
- otected 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;
- }
藍(lán)色位置是關(guān)鍵點(diǎn),ServletHandlerMethodInvoker.java是內(nèi)部類,繼承自HandlerMethodInvoker.java,invokeHandlerMethod方法需要擴(kuò)展,繼續(xù)跟蹤這個(gè)方法,發(fā)現(xiàn)是HandlerMethodInvoker.java這個(gè)類的方法,這個(gè)方法中的關(guān)鍵方法是resolveHandlerArguments(),關(guān)鍵部分如下:
- 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++;
- }
到此擴(kuò)展的話需要添加自己的類型,如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);
- }
這個(gè)方法上面添加擴(kuò)展邏輯:
- 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);
- }
- }
兩個(gè)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)){//綁定的關(guān)鍵過(guò)程
- Dataset ds = inDl.getDataset(paramName);
- Object vo = paramType.newInstance();
- MiPDataBinder dataBinder = new MiPDataBinder(vo, false);
- dataBinder.bind(inVl);
- return dataBinder.getTarget();
- }
- }
同時(shí)還需要一個(gè)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>
到此就實(shí)現(xiàn)了自定義格式的數(shù)據(jù)綁定。
對(duì)于特定格式的輸出,如果需要自定義的話,同樣需要修改AnnotationMethodHandlerAdapterExt.java這個(gè)類,關(guān)鍵位置在getModelAndView()方法。在如下位置:
- } else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {
- handleResponseBody(returnValue, webRequest);
- return null;
- }
添加自己的擴(kuò)展方法:
- 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;
- }
原文鏈接:http://www.blogjava.net/ghostzhang/archive/2011/09/12/358486.html
【編輯推薦】