4.盘点springmvc的常用接口之PropertyEditor###
java.beans.PropertyEditor
严格上来说,其实并不能算spring框架的接口,很明显看包名就明白此类是JDK自带的。是Sun所制定的一套JavaBean规范,是为IDE图形化界面准备设置属性值的接口。看接口源码上的说明:
A PropertyEditor class provides support for GUIs that want to allow users to edit a property value of a giventype.
这接口原本是使用在GUI图形程序中,允许用户给giventype设定属性值的。(不熟悉图形化界面API,不知道giventype是什么,怎么翻译)
接口说明
public interface PropertyEditor {
void setValue(Object value);
Object getValue();
boolean isPaintable();
void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box);
String getJavaInitializationString();
String getAsText();
void setAsText(String text) throws java.lang.IllegalArgumentException;
String[] getTags();
java.awt.Component getCustomEditor();
boolean supportsCustomEditor();
void addPropertyChangeListener(PropertyChangeListener listener);
void removePropertyChangeListener(PropertyChangeListener listener);
}
不要被这么多的方法给吓到,对于我们使用者来说其实重点只有下面4个方法:
void setValue(Object value);
设置属性值Object getValue();
获取属性值String getAsText();
把属性值转换成stringvoid setAsText(String text);
把string转换成属性值
所以Java很机智地提供了一个适配器java.beans.PropertyEditorSupport
来帮助我们实现属性值的转换,它帮助我们实现了GUI部分的接口,我们只需要重写getAsText
和setAsText
的逻辑。
那么这个接口跟spring有什么鸟关系呢,这个接口有什么用呢?请看示例1。
示例1
一个由区号和号码组成的座机号码实体类:
package com.demo.domain;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Telephone {
/* 区号 */
private String areaCode;
/* 号码 */
private String phone;
@Override
public String toString() {
return areaCode + "-" + phone;
}
}
一个人的实体(屏蔽了无关属性,只有座机-_-):
package com.demo.domain;
import org.springframework.beans.factory.annotation.Value;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class PersonEntity {
@Value("010-12345")
private Telephone telephone;
}
@Value
是spring的注解,相当于xml配置<property name="" value=""/>
里面的value,给属性赋值的。但是请注意,这里赋的是字符串。
那么问题来了,这个010-12345的字符串是怎么赋到Telephone这个类对象上的呢?类型根本转不过来。
答案就是实现转换器PropertyEditor
。
package com.demo.mvc.component;
import java.beans.PropertyEditorSupport;
import com.demo.domain.Telephone;
public class TelephonePropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (text.matches("^\\d+\\-\\d+$")) {
String[] strs = text.split("\\-");
setValue(new Telephone(strs[0], strs[1]));
} else {
throw new IllegalArgumentException();
}
}
@Override
public String getAsText() {
return ((Telephone) getValue()).toString();
}
}
实现完了接口还得注册到spring容器让spring管理:
<bean class="com.demo.domain.PersonEntity" />
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="com.demo.domain.Telephone" value="com.demo.mvc.component.TelephonePropertyEditor" />
</map>
</property>
</bean>
这个CustomEditorConfigurer
类顾名思义就是配置自定义的属性转换器的。把自定义的转换器统统放进这个名叫customEditors的Map结构里。用key指定Telephone,value指定TelephonePropertyEditor。
就是告诉spring,当遇到Telephone这个类型时,使用TelephonePropertyEditor把字符串转化成Telephone。
单元测试:
package com.junit;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.demo.domain.PersonEntity;
import com.demo.domain.Telephone;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:spring/spring-context.xml")
public class PropertyEditorlJunitTest {
@Resource
private PersonEntity personEntity;
@Test
public void test() {
Telephone telephone = personEntity.getTelephone();
System.out.printf("区号:%s,号码:%s\n", telephone.getAreaCode(), telephone.getPhone());
}
}
最后控制台输出结果:
区号:010,号码:12345
示例2
示例1是普通spring情况下使用PropertyEditor
的例子,那么怎么用在springmvc上呢?
package com.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.demo.domain.Telephone;
import com.demo.mvc.component.TelephonePropertyEditor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequestMapping("demo4")
public class PropertyEditorDemoController {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Telephone.class, new TelephonePropertyEditor());
}
@ResponseBody
@RequestMapping(method = RequestMethod.POST)
public String postTelephone(@RequestParam Telephone telephone) {
log.info(telephone.toString());
return telephone.toString();
}
}
使用@InitBinder
注解,在WebDataBinder
对象上注册转换器。
这样在访问POST http://localhost:8080/demo4 传表单数据 telephone = 010-12345
010-12345的字符串会自动转换为Telephone对象。
当然这种方式有一个缺点,该转换器只在当前的controller下有效。
想要实现全局转换,那就得实现WebBindingInitializer
接口
package com.demo.mvc.component;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.context.request.WebRequest;
import com.demo.domain.Telephone;
public class MyWebBindingInitializer implements WebBindingInitializer {
@Override
public void initBinder(WebDataBinder binder, WebRequest request) {
binder.registerCustomEditor(Telephone.class, new TelephonePropertyEditor());
}
}
在这里可以批量注册转换器。
spring-boot注册:
package com.demo;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import com.demo.mvc.component.MyWebBindingInitializer;
@SpringBootApplication
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Override
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter();
adapter.setWebBindingInitializer(new MyWebBindingInitializer());
return adapter;
}
}
xml注册:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer">
<bean class="com.demo.mvc.component.MyWebBindingInitializer"/>
</property>
</bean>
p.s.:这一章介绍了这么大篇幅的PropertyEditor
的使用,最后再说一句(不要打我哦)上述介绍的方法其实都已过时-_-。
在spring3.x后,新出了一个更强大的转换器机制,Converter
!
那么下一章再来讲解强大的Converter
吧。
友情链接: