自定义转换器

基本介绍

1.SpringBoot在响应客户端请求时, 将提交的数据封装成对象时, 使用了内置转换器

2.SpringBoot也支持自定义转换器, 这个内置转换器在debug的时候, 可以看到, 提供了124个内置转换器, 看下源码. GenericConverter类-ConvertiblePair(内部类)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n64zfgcT-1721040003162)(https://i-blog.****img.cn/direct/50b34f1225eb4971a8f3dba5bba7b470.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AI0JIntt-1721040003163)(https://i-blog.****img.cn/direct/27193c8fb918421d948762777329f940.png)]

应用实例

需求说明: 演示自定义转换器使用

1.修改save.html

<!--使用自定义转换器关联car, 字符串整体提交, 使用,号间隔-->
坐骑: <input name="name" value="碧水金睛兽,666.6"><br/

2.创建src/main/java/com/zzw/springboot/config/WebConfig.java, 增加自定义转换器
springboot系列四: sprintboot容器功能

/**
 * @Configuration(proxyBeanMethods = false)
 * 1.表示 WebConfig 是一个配置类
 * 2.proxyBeanMethods = false 表示使用Lite模式
 */
@Configuration(proxyBeanMethods = false)
public class WebConfig {

    //注入bean WebMvcConfiger
    @Bean
    public WebMvcConfigurer webMvcConfigurer() {

        //整个是WebMvcConfigurer接口的匿名内部类
        return new WebMvcConfigurer() {
            @Override
            public void addFormatters(FormatterRegistry registry) {
                /**
                 * 解读
                 * 1.在addFormatters方法中, 增加一个自定义转换器
                 * 2.增加自定义转换器 String -> Car
                 * 3.增加的自定义转换器会注册到 converters 容器中
                 * 4.converters 底层结构是 ConcurrentHashMap, 内置有124个转换器[不同版本个数不一样~]
                 * 5.一会我们debug查看这些转换器
                 */
                registry.addConverter(new Converter<String, Car>() {//传入Converter接口的匿名内部类
                    @Override
                    public Car convert(String source) {//source就是 传入的字符串 碧水金睛兽,666.6
                        //这里加入自定义的转换业务代码
                        if (!ObjectUtils.isEmpty(source)) {
                            String[] split = source.split(",");
                            Car car = new Car();
                            car.setVehicleName(split[0]);
                            car.setVehiclePrice(Double.parseDouble(split[1]));
                            return car;
                        }
                        return null;
                    }
                });
            }
        };
    }
}

3.测试
monster = Monster(id=100, name=张三, age=30, maritalStatus=false, birthday=Sat Jan 01 00:00:00 CST 1994, car=Car(vehicleName=碧水金睛兽, vehiclePrice=666.6))

查看源码

1.debug, 可以看到我们新增的Converter

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nPqeHa29-1721040003163)(https://i-blog.****img.cn/direct/9c05a54db2244cb192a287f7d98dfce2.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9skR4MEM-1721040003164)(https://i-blog.****img.cn/direct/fec0688d49f046c6bc8d80573fde9053.png)]

快捷键查看有多少元素

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wR5q4B80-1721040003164)(https://i-blog.****img.cn/direct/9c79994680b44d28bc42a0bc0c159103.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HqZ2NF1q-1721040003164)(https://i-blog.****img.cn/direct/973caedb153249e7a1b70425eef87598.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xmAQCBcX-1721040003165)(https://i-blog.****img.cn/direct/3c6e6978aae644d080553e9b6dedd401.png)]

注意事项和细节

1.注册转换器换种写法, 方便理解

/**
 * @Configuration(proxyBeanMethods = false)
 * 1.表示 WebConfig 是一个配置类
 * 2.proxyBeanMethods = false 表示使用Lite模式
 */
@Configuration(proxyBeanMethods = false)
public class WebConfig {

    //注入bean WebMvcConfiger
    @Bean
    public WebMvcConfigurer webMvcConfigurer() {

        //整个是WebMvcConfigurer接口的匿名内部类
        return new WebMvcConfigurer() {
            @Override
            public void addFormatters(FormatterRegistry registry) {
                /**
                 * 解读
                 * 1.在addFormatters方法中, 增加一个自定义转换器
                 * 2.增加自定义转换器 String -> Car
                 * 3.增加的自定义转换器会注册到 converters 容器中
                 * 4.converters 底层结构是 ConcurrentHashMap, 内置有124个转换器[不同版本个数不一样~]
                 * 5.一会我们debug查看这些转换器
                 */
                /*registry.addConverter(new Converter<String, Car>() {//传入Converter接口的匿名内部类
                    @Override
                    public Car convert(String source) {//source就是 传入的字符串 碧水金睛兽,666.6
                        //这里加入自定义的转换业务代码
                        if (!ObjectUtils.isEmpty(source)) {
                            String[] split = source.split(",");
                            Car car = new Car();
                            car.setVehicleName(split[0]);
                            car.setVehiclePrice(Double.parseDouble(split[1]));
                            return car;
                        }
                        return null;
                    }
                });*/

                //换种写法注册自定义转换器, 方便理解

                //1.先创建一个自定义的转换器
                Converter<String, Car> zzwConverter = new Converter<String, Car>() {//传入Converter接口的匿名内部类
                    @Override
                    public Car convert(String source) {//source就是 传入的字符串 碧水金睛兽,666.6
                        //这里加入自定义的转换业务代码
                        if (!ObjectUtils.isEmpty(source)) {
                            String[] split = source.split(",");
                            Car car = new Car();
                            car.setVehicleName(split[0]);
                            car.setVehiclePrice(Double.parseDouble(split[1]));
                            return car;
                        }
                        return null;
                    }
                };
                //添加转换器到converters容器
                registry.addConverter(zzwConverter);

                //还可以增加更多的转换器....
            }
        };
    }
}

2.假如我们不添加自定义转换器, 会报typeMismatch错误, 报400错误. 而400错误是客户端的错误, 请求包含语法错误.
JavaWeb系列八: WEB 开发通信协议(HTTP协议)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D4ZOyjUN-1721040003165)(https://i-blog.****img.cn/direct/0130ecd4d2aa4422a3f432287e1cdd91.png)]

3.创建两个自定义转换器

/**
 * @Configuration(proxyBeanMethods = false)
 * 1.表示 WebConfig 是一个配置类
 * 2.proxyBeanMethods = false 表示使用Lite模式
 */
@Configuration(proxyBeanMethods = false)
public class WebConfig {

    //注入bean WebMvcConfiger
    @Bean
    public WebMvcConfigurer webMvcConfigurer() {

        //整个是WebMvcConfigurer接口的匿名内部类
        return new WebMvcConfigurer() {
            @Override
            public void addFormatters(FormatterRegistry registry) {
                /**
                 * 解读
                 * 1.在addFormatters方法中, 增加一个自定义转换器
                 * 2.增加自定义转换器 String -> Car
                 * 3.增加的自定义转换器会注册到 converters 容器中
                 * 4.converters 底层结构是 ConcurrentHashMap, 内置有124个转换器[不同版本个数不一样~]
                 * 5.一会我们debug查看这些转换器
                 */
                /*registry.addConverter(new Converter<String, Car>() {//传入Converter接口的匿名内部类
                    @Override
                    public Car convert(String source) {//source就是 传入的字符串 碧水金睛兽,666.6
                        //这里加入自定义的转换业务代码
                        if (!ObjectUtils.isEmpty(source)) {
                            String[] split = source.split(",");
                            Car car = new Car();
                            car.setVehicleName(split[0]);
                            car.setVehiclePrice(Double.parseDouble(split[1]));
                            return car;
                        }
                        return null;
                    }
                });*/

                //换种写法注册自定义转换器, 方便理解

                //1.先创建一个自定义的转换器
                Converter<String, Car> zzwConverter = new Converter<String, Car>() {//传入Converter接口的匿名内部类
                    @Override
                    public Car convert(String source) {//source就是 传入的字符串 碧水金睛兽,666.6
                        //这里加入自定义的转换业务代码
                        if (!ObjectUtils.isEmpty(source)) {
                            String[] split = source.split(",");
                            Car car = new Car();
                            car.setVehicleName(split[0]);
                            car.setVehiclePrice(Double.parseDouble(split[1]));
                            return car;
                        }
                        return null;
                    }
                };

                //还可以增加更多的转换器....
                //第2个自定义的转换器
                Converter<String, Monster> zzwConverter2 = new Converter<String, Monster>() {
                    @Override
                    public Monster convert(String source) {
                        return null;
                    }
                };

                //添加转换器到converters容器
                registry.addConverter(zzwConverter);
                registry.addConverter(zzwConverter2);
            }
        };
    }
}

debug, 看一看 converters容器 是不是变成了 126 个.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Eo32GPY-1721040003166)(https://i-blog.****img.cn/direct/65d365997f984b26bf3e9a2267b72d07.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WEFtnsU6-1721040003166)(https://i-blog.****img.cn/direct/d2ca48c92c664208b106daa3e9ec59d4.png)]

4.创建三个自定义转换器, 由于key是[源类型->目标类型], 所以会覆盖掉一个.

//1.先创建一个自定义的转换器
Converter<String, Car> zzwConverter = new Converter<String, Car>() {//传入Converter接口的匿名内部类
    @Override
    public Car convert(String source) {//source就是 传入的字符串 碧水金睛兽,666.6
        //这里加入自定义的转换业务代码
        if (!ObjectUtils.isEmpty(source)) {
            String[] split = source.split(",");
            Car car = new Car();
            car.setVehicleName(split[0]);
            car.setVehiclePrice(Double.parseDouble(split[1]));
            return car;
        }
        return null;
    }
};

//还可以增加更多的转换器....
//第2个自定义的转换器
Converter<String, Monster> zzwConverter2 = new Converter<String, Monster>() {
    @Override
    public Monster convert(String source) {
        return null;
    }
};
//第3个自定义的转换器
Converter<String, Car> zzwConverter3 = new Converter<String, Car>() {
    @Override
    public Car convert(String source) {
        return null;
    }
};

//添加转换器到converters容器
registry.addConverter(zzwConverter);
registry.addConverter(zzwConverter2);
registry.addConverter(zzwConverter3);

1)测试, 是否覆盖.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tCQzI29s-1721040003167)(https://i-blog.****img.cn/direct/cf4a77912c5c4cdc9bbb14349ccf6ffc.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G63TxTQP-1721040003167)(https://i-blog.****img.cn/direct/bbcb6f8b0d714c3389a6c2ca75b96b7d.png)]

2)查看 converters 容器. 因为第三个转换器和第一个转换器 key 是相同的, 所以覆盖掉了.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ot1aXvcC-1721040003168)(https://i-blog.****img.cn/direct/5226ced93f7343b4a0383e0a727ec890.png)]

上一篇:Leetcode算法题(移除链表中的元素)


下一篇:UI组件库(element 、antdesign 等)下拉组件值为id不回显的坑