Spring Formatter<T> 对Spring MVC接受的参数格式化

Formatter和Converter一样,也是将一种类型转换成另一种类型。但是,Formatter的源类型必须是一个String。

在使用时,必须编写一个实现org.springframework.format.Formatter接口的java类。这个接口的声明如下

注意点就是:此Formatter的应用场景多在Spring MVC中接受String的值将其转化为相应的Java对象

public interface Formatter<T> extends Printer<T>, Parser<T> {
}
public interface Printer<T> {
    String print(T var1, Locale var2);
}
public interface Parser<T> {
    T parse(String var1, Locale var2) throws ParseException;
}

例子:

将DateFormatter作为Formatter的例子:  (DateFormatter Spring自带支持,当然也可以自定义)

1.编写处理类

public class DateFormatter implements Formatter<Date> {

    private String pattern;

    public DateFormatter(String pattern) {
        this.pattern = pattern;
    }

    @Override
    public Date parse(String formatted, Locale locale) throws ParseException {
        if (StringUtils.isEmpty(formatted)) {
            return null;
        }
        return getDateFormatter(locale).parse(formatted);
    }

    @Override
    public String print(Date object, Locale locale) {
        return Objects.isNull(object) ? "" :
                getDateFormatter(locale).format(object);

    }

    protected DateFormat getDateFormatter(Locale local) {
        DateFormat dateFormat = new SimpleDateFormat(this.pattern, local);
        dateFormat.setLenient(false);
        return dateFormat;
    }
}

2.将处理类注册到容器  容器会默认的奖器注册到解析器中

    @Bean
    public DateFormatter dateFormatterDate() {
        return new DateFormatter("yyyy-MM/dd");
    }

3.由于容器会默认的注册到解析器中,因而该步骤也可以不要  注册到解析器

    @Bean
    public FormatterRegistrar formatterRegistrarDate() {
        return registry -> registry.addFormatter(dateFormatterDate());
    }

FormatterRegistrar用于注册多个相关的转换器或格式化器(根据给定的格式化目录注册,例如Date格式化)在直接注册不能实现时FormatterRegistrar就派上用场了,例如,当格式化程序需要在不同于自身<T>的特定字段类型下进行索引时,或者在注册Printer/Parser对时。

4.测试:

编写测试类

@Data
public class MyModel {

    private Date decimal;
}
    /**
     * 127.0.0.1:8886/get3?decimal=2017-01/01
     *
     * @return
     */
    @GetMapping(value = "/get3")
    public Object get(MyModel myModel) throws IOException {
        System.out.println(myModel);
        return myModel;
    }

同时Spring也提供了基于注解的格式化

例如 :如果使用下列注解,默认默认的解析器就会加载

@DateTimeFormat(pattern="yyyy-MM/dd")

@NumberFormat(style = NumberFormat.Style.CURRENCY)

使用注解的例子:

1.编写测试类

@Data
public class MyModel {

    @DateTimeFormat(pattern="yyyy-MM/dd")
    private Date decimal;
}
/**
     * 127.0.0.1:8886/get3?decimal=2017-01/01
     *
     * @return
     */
    @GetMapping(value = "/get3")
    public Object get(MyModel myModel) throws IOException {
        System.out.println(myModel);
        return myModel;
    }

可以达到和上面同样的效果。

同时也可以自定义注解,需要实现AnnotationFormatterFactory<T> 例如下面的Spring中用于将String转化为Number的实现

public class NumberFormatAnnotationFormatterFactory implements
        AnnotationFormatterFactory<NumberFormat> {  //NumberFormat为注解类型

    @Override
    public Set<Class<?>> getFieldTypes() {
        /**
         * 返回支持的转换类型
         */
        return new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Short.class, Integer.class, Long.class,
                Float.class, Double.class, BigDecimal.class, BigInteger.class}));
    }

    @Override
    public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
        return configureFormatterForm(annotation, fieldType);
    }

    @Override
    public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
        return configureFormatterForm(annotation, fieldType);
    }

    private Formatter<Number> configureFormatterForm(NumberFormat annotation, Class<?> fieldType) {
        if (!annotation.pattern().isEmpty()) {
            return new NumberFormatter(annotation.pattern());
        } else {
            NumberFormat.Style style = annotation.style();
            if (style == NumberFormat.Style.PERCENT) {
                return new PercentFormatter();
            } else if (style == NumberFormat.Style.CURRENCY) {
                return new CurrencyFormatter();
            } else {
                return new NumberFormatter();
            }
        }
    }
}

这是想要触发格式化,只需要在字段上添加上@NumberFormat注解即可,如下

@Data
public class MyModel {

    @NumberFormat(style = NumberFormat.Style.CURRENCY)
    private Date decimal;
}

配置全局的日期和时间格式

默认情况下,不带@DateTimeFormat注解的日期和时间字段适用DateFormat.SHORT(短日期)的格式转化字符串,开发者也可以使用自定义的全局格式覆盖默认的格式。

此时需要确保Spring不注册默认的格式化器。而应该手动注册所有的格式化器,如下

    @Bean
    public FormattingConversionService conversionService() {
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false);

        //保证仍旧支持@NumberFormat
        conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());

        //修改默认的时间格式
        DateFormatterRegistrar registrar = new DateFormatterRegistrar();
        registrar.setFormatter(new DateFormatter("yyyyMMdd"));
        registrar.registerFormatters(conversionService);
        
        return conversionService;
    }



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值