SpringMVC使用(4) 数据绑定

来源:互联网 发布:mac电量消耗变快 编辑:程序博客网 时间:2024/05/17 01:01

1. 数据绑定

将用户界面元素的属性绑定到一个类型(对象)的实例上


2. 简单类型绑定

  • 基本类型(如int, long等):传入元素必须不为空,且范围必须在基本类型范围内,否则会抛出异常。
  • 数组类型:有多个相同名称的传入参数,可以自动绑定。
  • 包装类型(如Integer, Long等):可以为空,数据类型必须在范围内,否则会抛出异常。

3. 对象绑定

  • 如果是单级属性,可以直接使用属性名进行简单类型绑定。
  • 如果是多级属性,可以使用 前级属性名.后级属性名。

4. @InitBinder注释

4.1. 综述

  • 作用域是当前Controller
  • 有value属性,可以指定需要操作的输入参数名

4.2. 使用实例

//指定了("user"),则表示只对输入数据名为"user"的参数进行该处理。如果没有指定参数,则表示对所有参数进行处理。@InitBinder("user")public void initUserBinder(WebDataBinder binder) {    //可以指定默认前缀,具体实例请看下面的类    binder.setFieldDefaultPrefix("user.");}//假设有User类,Admin类,其中都有name属性//输入表单中有user.name=Emma,那么user对象中的name属性为Emma,admin对象中的name属性为null//输入表单中有name=Emma,那么user对象与admin对象中的name均为Emma@RequestMapping("objects")@ResponseBodypublic Object objects(User user, Admin admin) {    return user.toString()+"\n"+admin.toString();}

5. 集合类型数据绑定

5.0. 综述

集合类型绑定,不能直接使用List<> Set<> Map<>,必须使用数据收集对象。

//集合类型绑定,不能直接使用List Set Map对象,必须包括在POJO中//http://localhost:8080/Spring-Mvc-Study/binding/list1?list[0]=name&list[1]=lucy//这个操作会报错@RequestMapping("list1")@ResponseBodypublic Object list(List<String> list) {    StringBuilder sb = new StringBuilder();    for( String name: list) {        sb.append(name+" ");    }    return sb.toString();}

5.1. List

//List对象绑定可以直接设置下标// http://localhost:8080/Spring-Mvc-Study/binding/list2?list[0].name=Emma&list[5].name=lucy//此时会有6个User对象,其中1-4对象均为空@RequestMapping("list2")@ResponseBodypublic Object list2(UserListTest users) {    StringBuilder sb = new StringBuilder();    for( User user: users.getList()) {        sb.append(user.toString()+" ");    }    return sb.toString();}

5.2. Set

public class UserSetTest {    private Set<User> set;    public UserSetTest() {        //Set必须初始化        set = new HashSet<User>();        set.add(new User());        set.add(new User());    }    public Set<User> getSet() {        return set;    }    public void setSet(Set<User> set) {        this.set = set;    }}//以下代码是Controller中部分代码//Set对象绑定//可以直接设置下标赋值,不能越界//Set对象必须先初始化容器大小// http://localhost:8080/Spring-Mvc-Study/binding/set?set[0].name=lucy&set[0].age=12@RequestMapping("set")@ResponseBodypublic Object set(UserSetTest users) {    StringBuilder sb = new StringBuilder();    for(User user : users.getSet() ) {        sb.append(user.toString()+" ");    }    return sb.toString();}

5.3. Map数据绑定

public class UserMapTest {    private Map<String,User> map;    public Map<String, User> getMap() {        return map;    }    public void setMap(Map<String, User> map) {        this.map = map;    }}//Map数据绑定//http://localhost:8080/Spring-Mvc-Study/binding/map?map['X'].name=Emma&map['X'].age=12@RequestMapping("map")@ResponseBodypublic Object map(UserMapTest users) {    StringBuilder sb = new StringBuilder();    for(Entry<String, User> set : users.getMap().entrySet() ) {        sb.append("["+set.getKey()+"]="+set.getValue().toString());    }    return sb.toString();}

6. 自定义类型转换器

6.1. 概述

  • PropertyEditor:
  • Formatter:
  • Converter:

6.2. PropertyEditor

  1. 继承PropertyEditorSupport类,重写setAsText方法。
  2. 有很多Spring中的默认实现可以使用,如CustomDateEditor。
  3. 在Controller中添加@InitBinder,并在WebDataBinder对象中注册。
//自己实现的PropertyEditorpublic class MyPropertyEditor extends PropertyEditorSupport {    @Override    public void setAsText(String text) throws IllegalArgumentException {        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");        try {            setValue(sdf.parse(text));        } catch (ParseException e) {            setValue(null);        }    }}//Controller中的代码//PropertyEditor的使用实例@RequestMapping("date")@ResponseBodypublic Object date(Date date) {    return date.toString();}@InitBinderpublic void initMeBinder(WebDataBinder binder) {//      binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));//有默认实现可以使用    binder.registerCustomEditor(Date.class, new MyPropertyEditor());//可以自己注册}

6.3. Formatter

  1. 主要用于String与其他类型的转换
  2. 是全局转换,需要修改配置文件
//自定义Formatter,需要实现Formatter接口//Formatter接口泛型,就是要转换的类型public class MyFormatter implements Formatter<Date> {    public String print(Date object, Locale locale) {        return object.toString();    }    public Date parse(String text, Locale locale) throws ParseException {        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");        return sdf.parse(text);    }}
<!-- Formatter数据绑定 --><mvc:annotation-driven conversion-service="myDateFormatter"/><bean id="myDateFormatter" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">    <property name="formatters">        <set>            <bean class="com.emmairving.springmvc.binding.MyFormatter"></bean>        </set>    </property></bean>

6.4. Converter

6.4.1. 概述

Converter能做到从任意Object向另外一个任意Object转换。

6.4.2. Converter的三种实现方式

之后注册Converter时,也就是这三种接口的实例

//1. 使用Converter接口public interface Converter<S, T> {    T convert(S source);}//2. GenericConverter接口public interface GenericConverter {    Set<ConvertiblePair> getConvertibleTypes();    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);    final class ConvertiblePair {        private final Class<?> sourceType;        private final Class<?> targetType;        public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {            Assert.notNull(sourceType, "Source type must not be null");            Assert.notNull(targetType, "Target type must not be null");            this.sourceType = sourceType;            this.targetType = targetType;        }        public Class<?> getSourceType() {            return this.sourceType;        }        public Class<?> getTargetType() {            return this.targetType;        }        @Override        public boolean equals(Object other) {            if (this == other) {                return true;            }            if (other == null || other.getClass() != ConvertiblePair.class) {                return false;            }            ConvertiblePair otherPair = (ConvertiblePair) other;            return (this.sourceType == otherPair.sourceType && this.targetType == otherPair.targetType);        }        @Override        public int hashCode() {            return (this.sourceType.hashCode() * 31 + this.targetType.hashCode());        }        @Override        public String toString() {            return (this.sourceType.getName() + " -> " + this.targetType.getName());        }    }}//3. ConverterFactory接口public interface ConverterFactory<S, R> {    <T extends R> Converter<S, T> getConverter(Class<T> targetType);}

6.4.3. ConverterService

//用于使用Converterpublic interface ConversionService {    boolean canConvert(Class<?> sourceType, Class<?> targetType);    boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);    <T> T convert(Object source, Class<T> targetType);    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);}

6.4.4. ConverterFactory

//用于注册Converterpublic interface ConverterRegistry {    void addConverter(Converter<?, ?> converter);    <S, T> void addConverter(Class<S> sourceType, Class<T> targetType, Converter<? super S, ? extends T> converter);    void addConverter(GenericConverter converter);    void addConverterFactory(ConverterFactory<?, ?> converterFactory);    void removeConvertible(Class<?> sourceType, Class<?> targetType);}

6.4.5. 其他关键类

  • GenericConversionService:实现了ConversionService接口和ConverterRegistry接口。但不能在SpringMVC配置文件中作为ConversionService。
  • ConversionServiceFactoryBean:使用了GenericConversionService类,并能够注册Converter。
  • FormattingConversionServiceFactoryBean:既可以注册Converter,也可以注册Formatter。

7. 参考资料

  1. PropertyEditor
  2. Converter
  3. Converter2
  4. 慕课网SpringMVC数据绑定课程
0 0
原创粉丝点击