从零开始 Spring Boot 29:类型转换

从零开始 Spring Boot 29:类型转换

spring boot

图源:简书 (jianshu.com)

PropertyEditor

Spring使用PropertyEditor进行String和具体类型之间的转换:

public interface PropertyEditor {
   
	void setValue(Object value);
	Object getValue();
	String getAsText();
	void setAsText(String text) throws java.lang.IllegalArgumentException;
	// ...
}

这个接口主要有这几个方法:

  • setValue,设置修改后的属性值。
  • getValue,获取属性值。
  • getAsText,获取属性值对应的字符串。
  • setAsText,用字符串设置属性值。

PropertyEditor和之后介绍的ProertyEditorSupport并不属于Spring框架,这都是java标准包的一部分,属于java.beans包。这个包定义了java bean相关的组件,更多信息可以阅读java.beans (Java Platform SE 8 ) — beans(Java Platform SE 8) (oracle.com)

自定义PropertyEditor时并不需要直接实现PropertyEditor接口,只需要从PropertyEditorSupport继承即可:

public class PropertyEditorSupport implements PropertyEditor {
   
	// ...
}

下面具体举例如何在Spring Boot中使用PropertyEditor进行类型转换。

假设有这么两个实体类:

public class Dog {
   
    private String name;

    public Dog(String name) {
   
        this.name = name;
    }

    @Override
    public String toString() {
   
        return "Dog(%s)".formatted(name);
    }
}

@Data
public class Person {
   

    private String name;
    private int age = 0;

    public Person(String name) {
   
        this.name = name;
    }

    public Person(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
   
        return "Person(name:%s,age:%d)".formatted(name, age);
    }
}

我们想直接在Controller中通过传递字符串形式的参数来获取相应的实体类对象:

@RestController
@RequestMapping("/hello")
public class HelloController {
   
    @GetMapping("")
    public String hello(@RequestParam Person person, @RequestParam Dog dog){
   
        System.out.println(person);
        System.out.println(dog);
        return Result.success().toString();
    }
}

比如我们希望能处理这样的请求:[localhost:8080/hello?person=tom:11&dog=jerry](http://localhost:8080/hello?person=tom:11&dog=jerry)

为了能让Spring将字符串转换为实体类,我们需要为实体类创建对应的PropertyEditor

public class PersonEditor extends PropertyEditorSupport {
   
    @Override
    public String getAsText() {
   
        Person person = (Person) this.getValue();
        return "%s:%d".formatted(person.getName(), person.getAge());
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
   
        if (text == null || text.isEmpty()) {
   
            throw new IllegalArgumentException("字符串不能为空");
        }
        int index = text.indexOf(":");
        if (index <= 0) {
   
            throw new IllegalArgumentException("缺少:符号");
        }
        if (text.length() <= index + 1) {
   
            throw new IllegalArgumentException("缺少年龄信息");
        }
        String name = text.substring(0, index);
        String ageText = text.substring(index + 1);
        int age;
        try {
   
            age = Integer.parseInt(ageText);
        } catch (NumberFormatException e) {
   
            throw new IllegalArgumentException("年龄不是整数");
        }
        setValue(new Person(name, age));
    }
}

public class DogEditor extends PropertyEditorSupport {
   
    @Override
    public String getAsText() {
   
        Dog dog = (Dog) this.getValue();
        return super.getAsText();
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
   
        setValue(new Dog(text));
    }
}

将自定义PropertyEditor命名为xxxEditor是一种习惯。

主要覆盖getAsTextsetAsText方法,并实现字符串与具体类型的转换逻辑即可。

只有实体类和对应的ProertyEditor也是不行的,我们还需要将对应关系注册到Spring中:

@RestController
@RequestMapping("/hello")
public class HelloController {
   
    // ...
    @InitBinder
    void initBinder(WebDataBinder binder) {
   
        binder.registerCustomEditor(Person.class, new PersonEditor());
        binder.registerCustomEditor(Dog.class, new DogEditor());
    }
}

这样做在HelloController中,所有请求处理都可以直接将字符串形式的参数转换为对应的实体类对象。

如果将实体类和对应的PropertyEntity放在同一个包下面,并且PropertyEntity类被命名为xxxEditor,Spring会自动识别检测,不需要手动进行注册。

CustomEditorConfigurer

上面示例中这种通过@InitBinder注解绑定自定义属性编辑器的做法,只针对当前Controller有效,如果要让Spring框架默认生效,需要使用CustomEditorConfigurer,这是一个BeanFactoryPostProcessor,所以可以利用它来改变IoC的行为:

@Configuration
public class AppConfig 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值