温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何进行Spring MVC数据绑定的扩展

发布时间:2021-10-27 10:52:38 来源:亿速云 阅读:180 作者:柒染 栏目:编程语言

这篇文章给大家介绍如何进行Spring MVC数据绑定的扩展,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

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

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

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;     }

蓝色位置是关键点,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; }

关于如何进行Spring MVC数据绑定的扩展就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI