SpringMVC 前端传递参数的自定义转换方式实现

我们知道,前端传递给后端的参数只能是String类型的文本.

而在后端Controller中,接收的参数类型可以是String,Integer,Boolean,Collection等各种Java支持的类型.

这中间就需要有一个参数转换的过程.

Spring中默认的转换方式,定义在PropertyEditorRegistrySupport类中createDefaultEditors方法内:

	/**
	 * Actually register the default editors for this registry instance.
	 */
	private void createDefaultEditors() {
		this.defaultEditors = new HashMap<Class<?>, PropertyEditor>(64);

		// Simple editors, without parameterization capabilities.
		// The JDK does not contain a default editor for any of these target types.
		this.defaultEditors.put(Charset.class, new CharsetEditor());
		this.defaultEditors.put(Class.class, new ClassEditor());
		this.defaultEditors.put(Class[].class, new ClassArrayEditor());
		this.defaultEditors.put(Currency.class, new CurrencyEditor());
		this.defaultEditors.put(File.class, new FileEditor());
		this.defaultEditors.put(InputStream.class, new InputStreamEditor());
		this.defaultEditors.put(InputSource.class, new InputSourceEditor());
		this.defaultEditors.put(Locale.class, new LocaleEditor());
		this.defaultEditors.put(Pattern.class, new PatternEditor());
		this.defaultEditors.put(Properties.class, new PropertiesEditor());
		this.defaultEditors.put(Reader.class, new ReaderEditor());
		this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor());
		this.defaultEditors.put(TimeZone.class, new TimeZoneEditor());
		this.defaultEditors.put(URI.class, new URIEditor());
		this.defaultEditors.put(URL.class, new URLEditor());
		this.defaultEditors.put(UUID.class, new UUIDEditor());
		if (zoneIdClass != null) {
			this.defaultEditors.put(zoneIdClass, new ZoneIdEditor());
		}

		// Default instances of collection editors.
		// Can be overridden by registering custom instances of those as custom editors.
		this.defaultEditors.put(Collection.class, new CustomCollectionEditor(Collection.class));
		this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class));
		this.defaultEditors.put(SortedSet.class, new CustomCollectionEditor(SortedSet.class));
		this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class));
		this.defaultEditors.put(SortedMap.class, new CustomMapEditor(SortedMap.class));

		// Default editors for primitive arrays.
		this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor());
		this.defaultEditors.put(char[].class, new CharArrayPropertyEditor());

		// The JDK does not contain a default editor for char!
		this.defaultEditors.put(char.class, new CharacterEditor(false));
		this.defaultEditors.put(Character.class, new CharacterEditor(true));

		// Spring's CustomBooleanEditor accepts more flag values than the JDK's default editor.
		this.defaultEditors.put(boolean.class, new CustomBooleanEditor(false));
		this.defaultEditors.put(Boolean.class, new CustomBooleanEditor(true));

		// The JDK does not contain default editors for number wrapper types!
		// Override JDK primitive number editors with our own CustomNumberEditor.
		this.defaultEditors.put(byte.class, new CustomNumberEditor(Byte.class, false));
		this.defaultEditors.put(Byte.class, new CustomNumberEditor(Byte.class, true));
		this.defaultEditors.put(short.class, new CustomNumberEditor(Short.class, false));
		this.defaultEditors.put(Short.class, new CustomNumberEditor(Short.class, true));
		this.defaultEditors.put(int.class, new CustomNumberEditor(Integer.class, false));
		this.defaultEditors.put(Integer.class, new CustomNumberEditor(Integer.class, true));
		this.defaultEditors.put(long.class, new CustomNumberEditor(Long.class, false));
		this.defaultEditors.put(Long.class, new CustomNumberEditor(Long.class, true));
		this.defaultEditors.put(float.class, new CustomNumberEditor(Float.class, false));
		this.defaultEditors.put(Float.class, new CustomNumberEditor(Float.class, true));
		this.defaultEditors.put(double.class, new CustomNumberEditor(Double.class, false));
		this.defaultEditors.put(Double.class, new CustomNumberEditor(Double.class, true));
		this.defaultEditors.put(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, true));
		this.defaultEditors.put(BigInteger.class, new CustomNumberEditor(BigInteger.class, true));

		// Only register config value editors if explicitly requested.
		if (this.configValueEditorsActive) {
			StringArrayPropertyEditor sae = new StringArrayPropertyEditor();
			this.defaultEditors.put(String[].class, sae);
			this.defaultEditors.put(short[].class, sae);
			this.defaultEditors.put(int[].class, sae);
			this.defaultEditors.put(long[].class, sae);
		}
	}

可以看到,每种参数类型对应一个编译器的示例.

而编辑器则继承了PropertyEditorSupport类.

其中有两个重要方法:

  • void setAsText(String text) : 由外部编辑器传入一个String类型的文本,配合setValue()方法更新属性值.
  • String getAsText() : 将属性对象用一个字符串表示,以便外部的属性编辑器能以可视化的方式显示。缺省返回null,表示该属性不能以字符串表示;

如果我们自己实现一个编辑器,并加载到Spring中,就可以指定某种入参类型的转换规则了.

 

实现方式

我们需求将前端传入的13位时间戳转换为Date类型,以此为例来看下如何实现自定义参数转换.

1.创建一个继承PropertyEditorSupport的类,并重写setAsText和getAsText方法

package com.lgeek.smarthotel.common.propertyeditors;

import java.beans.PropertyEditorSupport;
import java.util.Date;

import org.springframework.util.StringUtils;


/**
 * 将前端传入的时间戳转换为Date类型放入Controller.
 *
 * @author lxy
 * @since 2018.9.12
 */

public class CustomDateTimeEditor extends PropertyEditorSupport  {

		private boolean allowEmpty=true;

		/** 无参构造*/
		public CustomDateTimeEditor() {
		}
		/** allowEmpty=true表示入参可以为null */
		public CustomDateTimeEditor(boolean allowEmpty) {
			this.allowEmpty = allowEmpty;
		}

		
		@Override
		public void setAsText(String text) throws IllegalArgumentException {
			if (this.allowEmpty && !StringUtils.hasText(text)) {
				// Treat empty String as null value.
				setValue(null);
			}
			else {
				try {
					//此处实现时间戳与Date的转换
					setValue(new Date(Long.parseLong(text)));
				}
				catch (Exception ex) {
					throw new IllegalArgumentException("Could not parse date from long: " + ex.getMessage(), ex);
				}
			}
		}

		@Override
		public String getAsText() {
			Date value = (Date) getValue();
			return value != null ? value.toString() : "";
		}

}

2.在Controller类中注册自定义的转换器,使用@InitBinder注解:

@RestController
@RequestMapping("/test")
public class OrderController {

	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		binder.registerCustomEditor(Date.class, new CustomDateTimeEditor());
	}

	@RequestMapping("/date_demo")
	@ResponseBody
	public String dateDemo(Date start, Date end)  {
		
		//TODO xxx

	}
}

以上简单的2步,就实现了前端文本参数与Controller中入参类型的转换.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值