记录一下使用springmvc实现自定义参数类型转换

在我们的实际开发中,我们知道,springmvc会对前端传递的参数进行解析,反序列化,反射等机制来映射到我们需要接收请求参数的实体类中,但是对于有些引用类型的参数映射,springmvc并未提供默认的实现,好在Springmvc是一个强大的轻量级框架,它为我们提供了一个WebMvcConfigurer接口(只应用于controller层),供我们实现我们自定义的参数类型转换器,自定义拦截器,自定义消息转换器等等。

1. 介绍WebMvcConfigurer => springmvc框架的配置类

/**
 * Defines callback methods to customize the Java-based configuration for
 * Spring MVC enabled via {@code @EnableWebMvc}.
 *
 * <p>{@code @EnableWebMvc}-annotated configuration classes may implement
 * this interface to be called back and given a chance to customize the
 * default configuration.
 *
 * @author Rossen Stoyanchev
 * @author Keith Donald
 * @author David Syer
 * @since 3.1
 */
public interface WebMvcConfigurer {
    /**
	 * Add {@link Converter Converters} and {@link Formatter Formatters} in addition to the ones
	 * registered by default.
	 */
	default void addFormatters(FormatterRegistry registry) {
	}

	/**
	 * Add Spring MVC lifecycle interceptors for pre- and post-processing of
	 * controller method invocations. Interceptors can be registered to apply
	 * to all requests or be limited to a subset of URL patterns.
	 * <p><strong>Note</strong> that interceptors registered here only apply to
	 * controllers and not to resource handler requests. To intercept requests for
	 * static resources either declare a
	 * {@link org.springframework.web.servlet.handler.MappedInterceptor MappedInterceptor}
	 * bean or switch to advanced configuration mode by extending
	 * {@link org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
	 * WebMvcConfigurationSupport} and then override {@code resourceHandlerMapping}.
	 */
	default void addInterceptors(InterceptorRegistry registry) {
	}
}

如上图所示: 上图大致介绍了webmvcconfigurer所做的事情。废话不多说,今天做一个示例,仅实现对于参数类型转换的自定义实现。(将字符串转换为BigDecimal类型)

第一步, 首先,通过WebMvcConfigurer我们可以发现:

/**
	 * Add {@link Converter Converters} and {@link Formatter Formatters} in addition to the ones
	 * registered by default.
	 */
	default void addFormatters(FormatterRegistry registry) {
	}

此方法的注释的大致意思为:FormatterRegistry实现了springmvc自带的默认注册器,我们只需要添加一个Converter和Formatter后,注册到FormatterRegistry中即可。由此我们来查看一下Converter接口的相关介绍:

/**
 * A converter converts a source object of type {@code S} to a target of type {@code T}.
 *
 * <p>Implementations of this interface are thread-safe and can be shared.
 *
 * <p>Implementations may additionally implement {@link ConditionalConverter}.
 *
 * @author Keith Donald
 * @since 3.0
 * @param <S> the source type
 * @param <T> the target type
 */
@FunctionalInterface
public interface Converter<S, T> {

	/**
	 * Convert the source object of type {@code S} to target type {@code T}.
	 * @param source the source object to convert, which must be an instance of {@code S} (never {@code null})
	 * @return the converted object, which must be an instance of {@code T} (potentially {@code null})
	 * @throws IllegalArgumentException if the source cannot be converted to the desired target type
	 */
	@Nullable
	T convert(S source);

}

从介绍中我们可以看到,Converter接口主要是用来将一个参数类型转换成另外一个参数类型,Converter<S, T>中的S代表源类型,也就是我们现在要做的String转BigDecimal类型中String 类型,那T就是代表BigDecimal类型,通过介绍我们还知道,实现此接口的类是线程安全的并且可被共享使用,这里为什么实现成安全的原因是它作用于方法体内,每次都用都是实例化一次,所以说它是线程安全的,除此之外,我们还可实现ConditionalConverter接口(在一定条件下才执行的类型转换器,在此请读者自去研究,在这里就不累述了),此外,Converter接口支持lambda表达式编程,在实现方法 T convert(S source) 中,source必须为S的类型或其子类,不可为空,当转换类型错误时,springmvc将抛出IllegalArgumentException异常。

自定义类实现Converter接口如下:

@Slf4j
public class MyConverter implements Converter<String, BigDecimal> {

    @Override
    public BigDecimal convert(String s) {
        log.info("获取到的s: " + s);
        return new BigDecimal(s);
    }
}

自定义类实现WebMvcConfigurer接口如下:

/**
 * 添加参数转换器
 */
@Slf4j
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {

    /**
     *
     * @param registry
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        log.info("添加自定义参数转换器");
        registry.addConverter(new MyConverter());
    }

}

将转换器注册到registry中.

定义一个测试类:

@Data
public class TestConverter {

    private BigDecimal num1;

    private String message;
}

定义一个测试controller:

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("test222")
    public void test1(TestConverter testConverter) {
        System.out.println("testConverter = " + testConverter);
    }
}

测试:http://localhost:8080/user/test222?message="bibi"&num1=12343.66

结果如下所示:

这样,我们就完成了自定义的参数类型转换了,是不是超级简单。 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值