需求:

将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.预备代码

package com.davidwang456.web.model;

import com.davidwang456.web.annotation.ParamName;

public class Job {
@ParamName("jt")
private String jobType;
@ParamName("loc")
private String location;
public String getJobType() {
return jobType;
}
public void setJobType(String jobType) {
this.jobType = jobType;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
} @Override
public String toString(){
return "jobType="+jobType+",location="+location;
} }

2.注解

package com.davidwang456.web.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
/**
* Overrides parameter name
*/ @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ParamName { /**
* The name of the request parameter to bind to.
*/
String value(); }

3.注解处理器

package com.davidwang456.web.processor;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor; import com.davidwang456.web.annotation.ParamName; /**
* Method processor supports {@link ParamName} parameters renaming
*
*/ public class RenamingProcessor extends ServletModelAttributeMethodProcessor { @Autowired
private RequestMappingHandlerAdapter requestMappingHandlerAdapter; //Rename cache
private final Map<Class<?>, Map<String, String>> replaceMap = new ConcurrentHashMap<Class<?>, Map<String, String>>(); public RenamingProcessor(boolean annotationNotRequired) {
super(annotationNotRequired);
} @Override
protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest nativeWebRequest) {
Object target = binder.getTarget();
Class<?> targetClass = target.getClass();
if (!replaceMap.containsKey(targetClass)) {
Map<String, String> mapping = analyzeClass(targetClass);
replaceMap.put(targetClass, mapping);
}
Map<String, String> mapping = replaceMap.get(targetClass);
ParamNameDataBinder paramNameDataBinder = new ParamNameDataBinder(target, binder.getObjectName(), mapping);
requestMappingHandlerAdapter.getWebBindingInitializer().initBinder(paramNameDataBinder, nativeWebRequest);
super.bindRequestParameters(paramNameDataBinder, nativeWebRequest);
} private static Map<String, String> analyzeClass(Class<?> targetClass) {
Field[] fields = targetClass.getDeclaredFields();
Map<String, String> renameMap = new HashMap<String, String>();
for (Field field : fields) {
ParamName paramNameAnnotation = field.getAnnotation(ParamName.class);
if (paramNameAnnotation != null && !paramNameAnnotation.value().isEmpty()) {
renameMap.put(paramNameAnnotation.value(), field.getName());
}
}
if (renameMap.isEmpty()) return Collections.emptyMap();
return renameMap;
}
}

4.数据绑定

package com.davidwang456.web.processor;

import java.util.Map;

import javax.servlet.ServletRequest;

import org.springframework.beans.MutablePropertyValues;
import org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder; /**
* ServletRequestDataBinder which supports fields renaming using {@link ParamName}
*
*/
public class ParamNameDataBinder extends ExtendedServletRequestDataBinder { private final Map<String, String> renameMapping; public ParamNameDataBinder(Object target, String objectName, Map<String, String> renameMapping) {
super(target, objectName);
this.renameMapping = renameMapping;
} @Override
protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) {
super.addBindValues(mpvs, request);
for (Map.Entry<String, String> entry : renameMapping.entrySet()) {
String from = entry.getKey();
String to = entry.getValue();
if (mpvs.contains(from)) {
mpvs.add(to, mpvs.getPropertyValue(from).getValue());
}
}
}
}

5.注册处理器

    <mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="com.davidwang456.web.processor.RenamingProcessor">
<constructor-arg name="annotationNotRequired" value="true"/>
</bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>

或者java config模式

package com.davidwang456.web.configurer;

import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import com.davidwang456.web.processor.RenamingProcessor; @Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter{
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
RenamingProcessor renameResolver = new RenamingProcessor(true);
argumentResolvers.add(renameResolver);
}
}

参考文献:

【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. start_kernel——boot_cpu_init及PER_CPU

    init/main.c /* * Activate the first processor. */ static void __init boot_cpu_init(void) { int cpu = ...

  2. 为什么不能用memcached存储Session?

    Memcached创建者Dormando非常早就写过两篇文章[1][2].告诫开发者不要用memcached存储Session. 他在第一篇文章中给出的理由大致是说,假设用memcached存储Ses ...

  3. event内存泄漏

    C#内存泄漏--event内存泄漏 内存泄漏是指:当一块内存被分配后,被丢弃,没有任何实例指针指向这块内存, 并且这块内存不会被GC视为垃圾进行回收.这块内存会一直存在,直到程序退出.C#是托管型代码 ...

  4. Nodemailer 报错

    { [Error: connect ECONNREFUSED] code: ‘ECONNREFUSED’, errno: ‘ECONNREFUSED’, syscall: ‘connect’ } 如果 ...

  5. js 关于height()、innerHeight()、outerHeight()函数的区别

  6. 浅谈Android和IOS系统的差异

    总结:事件响应级别.GPU加速.进程前后台.代码运行速度.内存管理机制. 进程管理机制.内存管理机制.cpu效率.GPU加速.事件响应级别. 1.    渲染机制不同 IOS的UI渲染采用实时优先级, ...

  7. ajax请求携带 cookie

    之前都有这样一个理解:ajax请求时是不会自动带上cookie的,要是想让他带上的话,必须哟啊设置withCredential为true.这个说法会让人产生完全扭曲的误解,我就是其中之一.完整的无歧义 ...

  8. vue.js的<slot>

    使用插槽分发内容在封装vue组件的时候,很多时候就不得不使用到vue的一个内置组件<slot>.slot是插槽的意思,顾名思义,这个<slot>组件的意义是预留一个区域,让其中 ...

  9. caioj 1204 Catalan数(模板)

    题目中对卡特兰数的总结很不错 以下copy自题目 Catalan数列:1,1,2,5,14,42,(前面几个要背) 即 h(0)=1,h(1)=1,h(2)=2,h(3)=5...公式:h(n)=C( ...

  10. pointer-events的css属性。使用该属性可以决定是否能穿透绝对定位元素去触发下面元素的某些行为

    pointer-events的css属性.使用该属性可以决定是否能穿透绝对定位元素去触发下面元素的某些行为,比如当一个元素盖住了某个点击事件时可用. 现在Firefox3.6+/Safari4+/Ch ...