spring mvc 给参数起别名

本文由 简悦 SimpRead 转码, 原文地址 www.bbsmax.com

需求:

需求:

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

举例:

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

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

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

返回响应

https://bbsmax.ikafan.com/static/L3Byb3h5L2h0dHBzL2ltYWdlczIwMTUuY25ibG9ncy5jb20vYmxvZy80ODYwNzQvMjAxNzA0LzQ4NjA3NC0yMDE3MDQyODE0NTE0NTQ1OS0xNzg4MDQ5ODc1LnBuZw==.jpg

解决方法

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

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

HandlerMethodArgumentResolver 对应输入, HttpMessageConverter 对应输出

  1. 预备代码
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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;

    }
 
}
  1. 注解
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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();
 
}
  1. 注解处理器
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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;

    }

}
  1. 数据绑定
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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());

           }

       }

   }

}
  1. 注册处理器
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<mvc:annotation-driven>

        <mvc:argument-resolvers>

            <bean>

                <constructor-arg />

            </bean>

        </mvc:argument-resolvers>

    </mvc:annotation-driven>

或者 java config 模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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 会从上到下挨个执行. < …

  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. ASP.Net MVC 开发基础学习笔记(2):HtmlHelper 与扩展方法

    一. 一个功能强大的页面开发辅助类—HtmlHelper 初步了解 1.1 有失必有得 在 ASP.Net MVC 中微软并没有提供类似服务器端控件那种开发方式, 毕竟微软的 MVC 就是传统的请求处理响应的回归. …

  2. DELPHI 相应鼠标滚轮

    在鼠标的 MouseWheel 事件里写入以下内容 if WheelDelta < 0 then    SendMessage(scrollBox1.Handle, WM_VSCROLL, SB_L …

  3. UIPickerView 简单操作和实际应用

    1.UIPickerView 选择指示器控件 // 选择器的初始化 UIPickerView * pickerView = [[UIPickerView alloc] initWithFrame:CGR …

  4. php 连接到数据库

    html 代码:

    用户名: <input typ …

  5. oracle 的 substr 和 replace

    // 我个人做的是更新表中某个字段下的所有内容带有中文括号的信息变为英文括号, 具体做法如下 update 表名 set 列名 =replace(要修改的字段名, 要替换掉的内容, 要替换上去的新内容) su …

  6. TortoiseGit 和 msysGit 安装及使用笔记(windows 下使用上传数据到 GitHub)[转]

    TortoiseGit 和 msysGit 安装及使用笔记 (windows 下使用上传数据到 GitHub) Git-1.7.11-preview+GitExtensions244SetupComplete+T …

  7. Nginx 与 Tomcat 安装、配置与优化

    Nginx 与 Tomcat 安装. 配置与优化 Nginx 与 Tomcat 安装. 配置与优化 Nginx 的安装与使用 Nginx 是一款优秀的反向代理服务器 安装: rpm(或者是 pkg 安装), 是预编译好的程序包 …

  8. HTML 静态网页(css 样式表)

    CSS(Cascading Style Sheet, 叠层样式表), 作用是美化 HTML 网页. /* 注释区域 */    此为注释语法 一. 样式表 (一) 样式表的分类 1. 内联样式表 和 HTML 联合显示, 控 …

  9. 阿里云 CentOS7 服务器利用 LVM 分区挂载磁盘全记录

    1. 进入服务器后, 首先利用 fdisk -l 来观察磁盘信息, 可以看出红线标注处, 有两块硬盘信息, 分别是 40G 和 300G 2. 同时你也可以观察到分区信息, 40G 的硬盘已经分了一个区 vda1, 大小 (Bloc …
  10. js 画布与图片的相互转化 (canvas 与 img)

    使用 js 将图片拷贝进画布 // 将图片对象转化为画布, 返回画布 function ImageToCanvas(image) { var canvas = document.createElement(&q …