- 浏览: 1892 次
文章分类
最新评论
首先 自定义注解ExtModelAttribute
然后利用方法
改变默认前缀
不过到3.2.8 还是有点小问题 前缀后面要加一个字符 比如“.”
另外这样改只适合 没有 value 的 ExtModelAttribute 扩展有限
如果参数中类相同就悲剧了
因为springmvc 很多地方限制死了只能处理 ModelAttribute
虽然注解处理器可以进入,但通过继承的方式其他的东西还是在处理ModelAttribute
比如获取bind 的名称,另外涉及的两个处理器类有final 方法无法通过继承扩展
只能重新定义
以下是自定义注解对应处理器ExtServletModelAttributeMethodProcessor
加入自定义注解ExtModelAttribute 的处理器ExtServletModelAttributeMethodProcessor
控制器中使用
页面使用
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, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ExtModelAttribute { String value() default ""; }
然后利用方法
void org.springframework.web.bind.WebDataBinder.setFieldDefaultPrefix(String fieldDefaultPrefix)在对应自定义注解ExtModelAttribute的处理器ExtServletModelAttributeMethodProcessor.bindRequestParameters(WebDataBinder binder, NativeWebRequest request)
改变默认前缀
不过到3.2.8 还是有点小问题 前缀后面要加一个字符 比如“.”
另外这样改只适合 没有 value 的 ExtModelAttribute 扩展有限
如果参数中类相同就悲剧了
因为springmvc 很多地方限制死了只能处理 ModelAttribute
虽然注解处理器可以进入,但通过继承的方式其他的东西还是在处理ModelAttribute
比如获取bind 的名称,另外涉及的两个处理器类有final 方法无法通过继承扩展
只能重新定义
以下是自定义注解对应处理器ExtServletModelAttributeMethodProcessor
import javax.servlet.ServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeanUtils; import org.springframework.core.Conventions; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.Converter; import org.springframework.util.StringUtils; import org.springframework.validation.BindException; import org.springframework.validation.DataBinder; import org.springframework.validation.Errors; import org.springframework.web.bind.ServletRequestDataBinder; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.method.annotation.ModelFactory; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory; public class ExtServletModelAttributeMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler{ public ExtServletModelAttributeMethodProcessor() { this.annotationNotRequired = false; } public ExtServletModelAttributeMethodProcessor(boolean annotationNotRequired) { this.annotationNotRequired = annotationNotRequired; } //->From ModelAttributeMethodProcessor protected Log logger = LogFactory.getLog(this.getClass()); private final boolean annotationNotRequired; /** * @return true if the parameter is annotated with {@link ModelAttribute} * or in default resolution mode also if it is not a simple type. */ public boolean supportsParameter(MethodParameter parameter) { if (parameter.hasParameterAnnotation(ExtModelAttribute.class)) { return true; } else if (this.annotationNotRequired) { return !BeanUtils.isSimpleProperty(parameter.getParameterType()); } else { return false; } } /** * Resolve the argument from the model or if not found instantiate it with * its default if it is available. The model attribute is then populated * with request values via data binding and optionally validated * if {@code @java.validation.Valid} is present on the argument. * @throws BindException if data binding and validation result in an error * and the next method parameter is not of type {@link Errors}. * @throws Exception if WebDataBinder initialization fails. */ public final Object resolveArgument( MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest request, WebDataBinderFactory binderFactory) throws Exception { //change here String name = ModelFactory_getNameForParameter(parameter); Object attribute = (mavContainer.containsAttribute(name)) ? mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, request); WebDataBinder binder = binderFactory.createBinder(request, attribute, name); if (binder.getTarget() != null) { bindRequestParameters(binder, request); validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors()) { if (isBindExceptionRequired(binder, parameter)) { throw new BindException(binder.getBindingResult()); } } } // Add resolved attribute and BindingResult at the end of the model Map<String, Object> bindingResultModel = binder.getBindingResult().getModel(); mavContainer.removeAttributes(bindingResultModel); mavContainer.addAllAttributes(bindingResultModel); return binder.getTarget(); } //->Rename as native method! because ServletModelAttributeMethodProcessor has Override it,and use it! /** * Extension point to create the model attribute if not found in the model. * The default implementation uses the default constructor. * @param attributeName the name of the attribute, never {@code null} * @param parameter the method parameter * @param binderFactory for creating WebDataBinder instance * @param request the current request * @return the created model attribute, never {@code null} */ protected Object ModelAttributeMethodProcessor_CreateAttribute(String attributeName, MethodParameter parameter, WebDataBinderFactory binderFactory, NativeWebRequest request) throws Exception { return BeanUtils.instantiateClass(parameter.getParameterType()); } //->Delete! ServletModelAttributeMethodProcessor has Override it but not use it /** * Extension point to bind the request to the target object. * @param binder the data binder instance to use for the binding * @param request the current request */ // protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) { // ((WebRequestDataBinder) binder).bind(request); // } /** * Validate the model attribute if applicable. * <p>The default implementation checks for {@code @javax.validation.Valid}. * @param binder the DataBinder to be used * @param parameter the method parameter */ protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) { Annotation[] annotations = parameter.getParameterAnnotations(); for (Annotation annot : annotations) { if (annot.annotationType().getSimpleName().startsWith("Valid")) { Object hints = AnnotationUtils.getValue(annot); binder.validate(hints instanceof Object[] ? (Object[]) hints : new Object[] {hints}); break; } } } /** * Whether to raise a {@link BindException} on validation errors. * @param binder the data binder used to perform data binding * @param parameter the method argument * @return {@code true} if the next method argument is not of type {@link Errors}. */ protected boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter parameter) { int i = parameter.getParameterIndex(); Class<?>[] paramTypes = parameter.getMethod().getParameterTypes(); boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1])); return !hasBindingResult; } /** * Return {@code true} if there is a method-level {@code @ModelAttribute} * or if it is a non-simple type when {@code annotationNotRequired=true}. */ public boolean supportsReturnType(MethodParameter returnType) { if (returnType.getMethodAnnotation(ModelAttribute.class) != null) { return true; } else if (this.annotationNotRequired) { return !BeanUtils.isSimpleProperty(returnType.getParameterType()); } else { return false; } } /** * Add non-null return values to the {@link ModelAndViewContainer}. */ public void handleReturnValue( Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { if (returnValue != null) { String name = ModelFactory.getNameForReturnValue(returnValue, returnType); mavContainer.addAttribute(name, returnValue); } } //<-From ModelAttributeMethodProcessor //->From ServletModelAttributeMethodProcessor /** * Instantiate the model attribute from a URI template variable or from a * request parameter if the name matches to the model attribute name and * if there is an appropriate type conversion strategy. If none of these * are true delegate back to the base class. * @see #createAttributeFromRequestValue(String, String, MethodParameter, WebDataBinderFactory, NativeWebRequest) */ protected final Object createAttribute(String attributeName, MethodParameter parameter, WebDataBinderFactory binderFactory, NativeWebRequest request) throws Exception { String value = getRequestValueForAttribute(attributeName, request); if (value != null) { Object attribute = createAttributeFromRequestValue(value, attributeName, parameter, binderFactory, request); if (attribute != null) { return attribute; } } return ModelAttributeMethodProcessor_CreateAttribute(attributeName, parameter, binderFactory, request); } /** * Obtain a value from the request that may be used to instantiate the * model attribute through type conversion from String to the target type. * <p>The default implementation looks for the attribute name to match * a URI variable first and then a request parameter. * @param attributeName the model attribute name * @param request the current request * @return the request value to try to convert or {@code null} */ protected String getRequestValueForAttribute(String attributeName, NativeWebRequest request) { Map<String, String> variables = getUriTemplateVariables(request); if (StringUtils.hasText(variables.get(attributeName))) { return variables.get(attributeName); } else if (StringUtils.hasText(request.getParameter(attributeName))) { return request.getParameter(attributeName); } else { return null; } } @SuppressWarnings("unchecked") protected final Map<String, String> getUriTemplateVariables(NativeWebRequest request) { Map<String, String> variables = (Map<String, String>) request.getAttribute( HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST); return (variables != null) ? variables : Collections.<String, String>emptyMap(); } /** * Create a model attribute from a String request value (e.g. URI template * variable, request parameter) using type conversion. * <p>The default implementation converts only if there a registered * {@link Converter} that can perform the conversion. * @param sourceValue the source value to create the model attribute from * @param attributeName the name of the attribute, never {@code null} * @param parameter the method parameter * @param binderFactory for creating WebDataBinder instance * @param request the current request * @return the created model attribute, or {@code null} * @throws Exception */ protected Object createAttributeFromRequestValue(String sourceValue, String attributeName, MethodParameter parameter, WebDataBinderFactory binderFactory, NativeWebRequest request) throws Exception { DataBinder binder = binderFactory.createBinder(request, null, attributeName); ConversionService conversionService = binder.getConversionService(); if (conversionService != null) { TypeDescriptor source = TypeDescriptor.valueOf(String.class); TypeDescriptor target = new TypeDescriptor(parameter); if (conversionService.canConvert(source, target)) { return binder.convertIfNecessary(sourceValue, parameter.getParameterType(), parameter); } } return null; } //The ModelFactory only support ModelAttribute must change it! /** * {@inheritDoc} * <p>Downcast {@link WebDataBinder} to {@link ServletRequestDataBinder} before binding. * @see ServletRequestDataBinderFactory */ protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) { ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class); ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder; servletBinder.setFieldDefaultPrefix(servletBinder.getObjectName()+"."); servletBinder.bind(servletRequest); } //->From ServletModelAttributeMethodProcessor //The ModelFactory only support ModelAttribute must change it! //->From ModelFactory public static String ModelFactory_getNameForParameter(MethodParameter parameter) { //ModelAttribute annot = parameter.getParameterAnnotation(ModelAttribute.class); ExtModelAttribute annot = parameter.getParameterAnnotation(ExtModelAttribute.class); String attrName = (annot != null) ? annot.value() : null; return StringUtils.hasText(attrName) ? attrName : Conventions.getVariableNameForParameter(parameter); } //<-From ModelFactory }
加入自定义注解ExtModelAttribute 的处理器ExtServletModelAttributeMethodProcessor
<mvc:annotation-driven> <mvc:argument-resolvers> <bean class="ExtServletModelAttributeMethodProcessor"/> </mvc:argument-resolvers> </mvc:annotation-driven>
控制器中使用
@RequestMapping(value="/test") public String ftl(@ExtModelAttribute("testVo1")TestVo testVo1,@ExtModelAttribute("testVo2")TestVo testVo2){ System.out.println(testVo1.getValue()); System.out.println(testVo2.getValue()); return "test"; }
页面使用
<form action="" method="post"> testVo1.value<Input id="value1" name="testVo1.value" value="${testVo1.value}" /> testVo2.value<Input id="value2" name="testVo2.value" value="${testVo2.value}" /> <input type="submit" value="submit"> </form>
相关推荐
在“SpringMVC精品资源--基于springMVC实现的解决方案系统.zip”这个压缩包中,我们可以推测包含了一系列关于SpringMVC开发的教程、示例代码或完整的项目模板,用于帮助开发者更好地理解和应用SpringMVC。...
本科毕设-课设-基于SpringMVC+MyBatis开发学生管理系统.zip本科毕设-课设-基于SpringMVC+MyBatis开发学生管理系统.zip本科毕设-课设-基于SpringMVC+MyBatis开发学生管理系统.zip本科毕设-课设-基于SpringMVC+MyBatis...
1、手写springmvc框架及分析springmvc源码.zip1、手写springmvc框架及分析springmvc源码.zip1、手写springmvc框架及分析springmvc源码.zip1、手写springmvc框架及分析springmvc源码.zip1、手写springmvc框架及分析...
### 多线程解决方案 在Java中,多线程是实现并发执行任务的关键。SpringMVC提供了一种在服务层实现多线程的方法,以提高程序的执行效率和响应速度。以下是一些关键概念: 1. **ThreadPoolTaskExecutor**:Spring...
使用`@ModelAttribute`注解,我们可以将请求参数绑定到对象属性上: ```java @PostMapping("/save") public String saveUser(@ModelAttribute("user") User user) { // ... } ``` 用户类可能如下所示: ```...
springmvc_4\springmvc_4.part1.rar
分析springmvc源码(2).zip分析springmvc源码(2).zip分析springmvc源码(2).zip分析springmvc源码(2).zip分析springmvc源码(2).zip分析springmvc源码(2).zip分析springmvc源码(2).zip分析springmvc源码(2).zip分析...
分析springmvc源码(5).zip分析springmvc源码(5).zip分析springmvc源码(5).zip分析springmvc源码(5).zip分析springmvc源码(5).zip分析springmvc源码(5).zip分析springmvc源码(5).zip分析springmvc源码(5).zip分析...
springmvc基础 包含代码+知识点+详细解释 1. 什么是springmvc? 2. springmvc框架原理 前端控制器、处理器映射器、处理器适配器... 参数绑定(简单类型、pojo、集合类型) 自定义参数绑定 6. springmvc和struts2区别
"SpringMVC纯注解配置"是SpringMVC框架的一种高级用法,旨在减少XML配置文件的使用,提高开发效率和代码可读性。在这个主题中,我们将深入探讨如何利用注解实现SpringMVC的配置以及jQuery如何处理后台返回的JSON对象...
本文将详述如何在Spring MVC中实现对Set类型的参数进行绑定,以解决可能遇到的问题。 首先,理解Spring MVC的数据绑定机制是至关重要的。Spring MVC在接收到HTTP请求后,会尝试将请求参数与控制器方法的参数进行...
springmvc 笔记
SpringMVC 参数收集及乱码处理 SpringMVC 框架提供了多种参数收集方式,以满足不同的应用场景需求。 ParametersCollector 是 SpringMVC 中负责收集参数的组件,它可以从 HttpServletRequest 中获取参数,并将其...
springmvc
SpringMVC入门参数绑定SSM整合 SpringMVC是一种基于MVC模式的Web应用程序框架,它是Spring框架的一个模块,用于开发Web项目。下面是SpringMVC入门参数绑定SSM整合的知识点总结: 一、SpringMVC概述 SpringMVC是...
SpringMVC Tomcat控制台乱码问题解决方案 本文主要介绍了SpringMVC Tomcat控制台乱码问题解决方案,该解决方案通过示例代码进行了详细的介绍,对大家的学习或者工作具有一定的参考学习价值。下面将对该解决方案进行...
SpringMVC是Spring框架的一个模块,它主要用于构建Web应用程序的后端控制器。作为一个成熟的MVC(Model-View-Controller)框架,SpringMVC通过解耦应用程序的业务逻辑、数据处理和用户界面,使得开发过程更加高效和...
15. **与其他Spring模块的整合**:SpringMVC可以很好地与Spring的其他模块,如Spring AOP、Spring Security、Spring Data等集成,构建完整的应用解决方案。 学习和掌握这些核心概念是Java开发者进阶到SpringMVC领域...
Springmvc+Mybatis精品教程 专用sql。找了半天没找到。 所以上传下 配套教程地址:https://www.bilibili.com/video/BV1sb411x7VQ?p=4