需求:

将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 2296 Map Labeler(2-sat)

    POJ 2296 Map Labeler 题目链接 题意: 坐标轴上有N个点.要在每一个点上贴一个正方形,这个正方形的横竖边分别和x,y轴平行,而且要使得点要么在正方形的上面那条边的中点,或者在以下那 ...

  2. Linux内核中进程上下文和中断上下文的理解

    參考: http://www.embedu.org/Column/Column240.htm http://www.cnblogs.com/Anker/p/3269106.html 首先明白一个概念: ...

  3. Android用canvas画哆啦A梦

    先上图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/diss ...

  4. bzoj2756: [SCOI2012]奇怪的游戏(网络流+分情况)

    2756: [SCOI2012]奇怪的游戏 题目:传送门 题解: 发现做不出来的大难题一点一个网络流 %大佬 首先黑白染色(原来是套路...)染色之后就可以保证每次操作都一定会使黑白各一个各自的值加1 ...

  5. IDE-IntelliJ IDEA

    IDE-IntelliJ IDEA 主题.字体.编辑区主题.文件编码修改.乱码问题 主题修改 上图标注 1 所示为 IntelliJ IDEA 修改主题的地方,可以通过打开左上角的File -> ...

  6. Laravel-redis-订阅发布

    Laravel-redis-订阅发布 标签(空格分隔): php Redis订阅发布 理解订阅发布: publish:将信息 message 发送到指定的频道 channel publish test ...

  7. 10.ref regex unordered_set smartpoint

    ref引用不可以复制的对象 void print(std::ostream &os, int i) { os << i << endl; } //ref引用不可以复制的 ...

  8. vue组件样式添加scoped属性之后,无法被父组件修改。或者无法在本组件修改element UI样式

    在vue开发中,需要使用scoped属性避免样式的全局干扰,但是这样在父组件中是无法被修改的,不仅如此如果项目中用了UI框架比如element Ui,这个时候在本组件也无法修改样式,因为权重问题.但是 ...

  9. CDN(Content Distribution Network)概念

    CDN的全称是Content Delivery Network,即内容分发网络.其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快.更稳定.通过在网络各处放置节 ...

  10. xshell同时发送多条命令

    1.如图,勾选撰写栏 勾选全部会话 下面的是一个很方便的小技巧.分屏 如下图垂直排列 水平排列等等