需求:

将http报文请求(保护body和url)中的参数传递给Controller时支持使用别名。

举例:

下面两条请求报文的结果是一致的。

http://example.com/foo?jobType=permanent&location=Stockholm

http://example.com/foo?jt=permanent&loc=Stockholm

返回响应

解决方法

Spring MVC3 提供了丰富的参数映射机制, 详细信息可以参见这里

同时对于Spring MVC默认的提供的映射机制不能涵盖的对象,我们可以通过扩展HandlerMethodArgumentResolver和HttpMessageConverter的机制来实现。

HandlerMethodArgumentResolver对应输入, HttpMessageConverter对应输出

1.预备代码

  1. package com.davidwang456.web.model;
  2.  
  3. import com.davidwang456.web.annotation.ParamName;
  4.  
  5. public class Job {
  6. @ParamName("jt")
  7. private String jobType;
  8. @ParamName("loc")
  9. private String location;
  10. public String getJobType() {
  11. return jobType;
  12. }
  13. public void setJobType(String jobType) {
  14. this.jobType = jobType;
  15. }
  16. public String getLocation() {
  17. return location;
  18. }
  19. public void setLocation(String location) {
  20. this.location = location;
  21. }
  22.  
  23. @Override
  24. public String toString(){
  25. return "jobType="+jobType+",location="+location;
  26. }
  27.  
  28. }

2.注解

  1. package com.davidwang456.web.annotation;
  2.  
  3. import java.lang.annotation.Documented;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.Target;
  6. import java.lang.annotation.ElementType;
  7. import java.lang.annotation.RetentionPolicy;
  8. /**
  9. * Overrides parameter name
  10. */
  11.  
  12. @Target(ElementType.FIELD)
  13. @Retention(RetentionPolicy.RUNTIME)
  14. @Documented
  15. public @interface ParamName {
  16.  
  17. /**
  18. * The name of the request parameter to bind to.
  19. */
  20. String value();
  21.  
  22. }

3.注解处理器

  1. package com.davidwang456.web.processor;
  2.  
  3. import java.lang.reflect.Field;
  4. import java.util.Collections;
  5. import java.util.HashMap;
  6. import java.util.Map;
  7. import java.util.concurrent.ConcurrentHashMap;
  8.  
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.web.bind.WebDataBinder;
  11. import org.springframework.web.context.request.NativeWebRequest;
  12. import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
  13. import org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor;
  14.  
  15. import com.davidwang456.web.annotation.ParamName;
  16.  
  17. /**
  18. * Method processor supports {@link ParamName} parameters renaming
  19. *
  20. */
  21.  
  22. public class RenamingProcessor extends ServletModelAttributeMethodProcessor {
  23.  
  24. @Autowired
  25. private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
  26.  
  27. //Rename cache
  28. private final Map<Class<?>, Map<String, String>> replaceMap = new ConcurrentHashMap<Class<?>, Map<String, String>>();
  29.  
  30. public RenamingProcessor(boolean annotationNotRequired) {
  31. super(annotationNotRequired);
  32. }
  33.  
  34. @Override
  35. protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest nativeWebRequest) {
  36. Object target = binder.getTarget();
  37. Class<?> targetClass = target.getClass();
  38. if (!replaceMap.containsKey(targetClass)) {
  39. Map<String, String> mapping = analyzeClass(targetClass);
  40. replaceMap.put(targetClass, mapping);
  41. }
  42. Map<String, String> mapping = replaceMap.get(targetClass);
  43. ParamNameDataBinder paramNameDataBinder = new ParamNameDataBinder(target, binder.getObjectName(), mapping);
  44. requestMappingHandlerAdapter.getWebBindingInitializer().initBinder(paramNameDataBinder, nativeWebRequest);
  45. super.bindRequestParameters(paramNameDataBinder, nativeWebRequest);
  46. }
  47.  
  48. private static Map<String, String> analyzeClass(Class<?> targetClass) {
  49. Field[] fields = targetClass.getDeclaredFields();
  50. Map<String, String> renameMap = new HashMap<String, String>();
  51. for (Field field : fields) {
  52. ParamName paramNameAnnotation = field.getAnnotation(ParamName.class);
  53. if (paramNameAnnotation != null && !paramNameAnnotation.value().isEmpty()) {
  54. renameMap.put(paramNameAnnotation.value(), field.getName());
  55. }
  56. }
  57. if (renameMap.isEmpty()) return Collections.emptyMap();
  58. return renameMap;
  59. }
  60. }

4.数据绑定

  1. package com.davidwang456.web.processor;
  2.  
  3. import java.util.Map;
  4.  
  5. import javax.servlet.ServletRequest;
  6.  
  7. import org.springframework.beans.MutablePropertyValues;
  8. import org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder;
  9.  
  10. /**
  11. * ServletRequestDataBinder which supports fields renaming using {@link ParamName}
  12. *
  13. */
  14. public class ParamNameDataBinder extends ExtendedServletRequestDataBinder {
  15.  
  16. private final Map<String, String> renameMapping;
  17.  
  18. public ParamNameDataBinder(Object target, String objectName, Map<String, String> renameMapping) {
  19. super(target, objectName);
  20. this.renameMapping = renameMapping;
  21. }
  22.  
  23. @Override
  24. protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) {
  25. super.addBindValues(mpvs, request);
  26. for (Map.Entry<String, String> entry : renameMapping.entrySet()) {
  27. String from = entry.getKey();
  28. String to = entry.getValue();
  29. if (mpvs.contains(from)) {
  30. mpvs.add(to, mpvs.getPropertyValue(from).getValue());
  31. }
  32. }
  33. }
  34. }

5.注册处理器

  1. <mvc:annotation-driven>
  2. <mvc:argument-resolvers>
  3. <bean class="com.davidwang456.web.processor.RenamingProcessor">
  4. <constructor-arg name="annotationNotRequired" value="true"/>
  5. </bean>
  6. </mvc:argument-resolvers>
  7. </mvc:annotation-driven>

或者java config模式

  1. package com.davidwang456.web.configurer;
  2.  
  3. import java.util.List;
  4.  
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.web.method.support.HandlerMethodArgumentResolver;
  7. import org.springframework.web.servlet.config.annotation.EnableWebMvc;
  8. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  9.  
  10. import com.davidwang456.web.processor.RenamingProcessor;
  11.  
  12. @Configuration
  13. @EnableWebMvc
  14. public class WebConfig extends WebMvcConfigurerAdapter{
  15. @Override
  16. public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
  17. RenamingProcessor renameResolver = new RenamingProcessor(true);
  18. argumentResolvers.add(renameResolver);
  19. }
  20. }

参考文献:

【1】http://stackoverflow.com/questions/8986593/how-to-customize-parameter-names-when-binding-spring-mvc-command-objects

【2】http://geekabyte.blogspot.tw/2014/08/how-to-inject-objects-into-spring-mvc.html

【3】http://www.cnblogs.com/daxin/p/3296493.html

spring mvc给参数起别名的更多相关文章

  1. spring mvc绑定参数之 类型转换 有三种方式:

    spring mvc绑定参数之类型转换有三种方式: 1.实体类中加日期格式化注解(上次做项目使用的这种.简单,但有缺点,是一种局部的处理方式,只能在本实体类中使用.方法三是全局的.) @DateTim ...

  2. Spring MVC接收参数(Map,List,JSON,Date,2个Bean)(记录一次面试惨状)

    题目Spring MVC 接收参数 MapListDate2个BeanJSON Spring MVC接收参数 -Map Spring MVC接收参数 -List Spring MVC接收参数 -dat ...

  3. spring mvc 复杂参数注入

    过了这么久,又重新把博客拾起来了 来上海工作也已经有将近两周的时间了, 今天在整理项目的时候,遇到了一个关于参数注入的问题 背景: 我的开发前台用的是extjs4,在对后台spring mvc提交表单 ...

  4. Spring MVC温故而知新 – 参数绑定、转发与重定向、异常处理、拦截器

    请求参数绑定 当用户发送请求时,根据Spring MVC的请求处理流程,前端控制器会请求处理器映射器返回一个处理器,然后请求处理器适配器之心相应的处理器,此时处理器映射器会调用Spring Mvc 提 ...

  5. Spring MVC请求参数绑定

    所谓请求参数绑定,就是在控制器方法中,将请求参数绑定到方法参数上 @RequestParam 绑定单个请求参数到方法参数上 @RequestParam("id") Integer ...

  6. Spring MVC处理参数Convert

    Springmvc.xml 配置convert,xml中配置多个相同的泛型时,xml里配置的convert会从上到下挨个执行. <!-- 配置注解驱动,并配置convert --> < ...

  7. Spring MVC Action参数类型 List集合类型(简单案例)

    题目:定义一个员工实体(Employee),实现批量添加员工功能,在表单中可以一次添加多个员工,数据可以不持久化 1,新建一个项目 2, 然后选择Maven框架选择 maven-archetype-w ...

  8. Spring MVC请求参数绑定 自定义类型转化 和获取原声带额servlet request response信息

    首先还在我们的框架的基础上建立文件 在domian下建立Account实体类 import org.springframework.stereotype.Controller; import org. ...

  9. Spring MVC初始化参数绑定

    初始化参数绑定与类型转换很类似,初始化绑定时,主要是参数类型 ---单日期 在处理器类中配置绑定方法  使用@InitBinder注解 在这里首先注册一个用户编辑器 参数一为目标类型   proper ...

随机推荐

  1. poj 3259 bellman最短路推断有无负权回路

    Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 36717   Accepted: 13438 Descr ...

  2. 基础数位DP小结

    HDU 3555 Bomb dp[i][0] 表示含 i 位数的方案总和. sp[i][0] 表示对于位数为len 的 num 在区间[ 10^(i-1) , num/(10^(len-i)) ] 内 ...

  3. Android Studio 修改注释模板中的${USER}变量以及修改默认的头部注释

    引言 通常我们创建类文件都会自动生成一段头部注释. 有时候这不是我们想要的效果. 它默认是Created By XXX. 而我们要的是@author XXX. 而且这里面的XXX是系统的的用户名,不一 ...

  4. m_Orchestrate learning system---十三、thinkphp的验证器支持多语言么

    m_Orchestrate learning system---十三.thinkphp的验证器支持多语言么 一.总结 一句话总结:支持,不仅验证器支持,其它的插件应该都支持 不仅thinkphp支持多 ...

  5. ES API 备忘

    本文所列的所有API在ElasticSearch文档是有详尽的说明,但它的结构组织的不太好. 这篇文章把ElasticSearch API用表格的形式供大家参考. https://www.iteblo ...

  6. MySQL学习(五)——使用JDBC完成用户表CRUD的操作

    通过案例我们发现“获得连接”和“释放资源”两次代码将在之后的增删改查所有功能中都存在,开发中遇到此种情况,将采用工具类的方法进行抽取,从而达到代码的重复利用. 1.使用properties配置文件 开 ...

  7. swift语言点评八-枚举

    总结:swift中的枚举可以看作变量可以作为case匹配参数的类 Enumerations 枚举的作用:状态列举与匹配 枚举值与类型 If a value (known as a “raw” valu ...

  8. 使用dispatch_group来进行线程同步

    我的上篇文章iOS中多个网络请求的同步问题总结中用到了dispatch_group来进行线程同步,对用法不是特别熟悉所以整理这篇文章来加深记忆(闲着也是闲着). 一.简单介绍下将会用到的一些东西 英语 ...

  9. Calling Mojo from Blink

    Variants Let's assume we have a mojom file such as this:   module example.mojom;   interface Foo {   ...

  10. 路飞学城Python-Day4

    29.二进制转换计算机使用的语言就是二进制古时候,人们使用信鸽.书信.千里马等方式.但是这样的方式是不可靠的,时间也长.古时候的军方,通过烽火狼烟进行简单的信息交流 30.二进制的转换(II)8 4 ...