前情
几个月前我为公司写一个用于实现RESTful API的项目基础框架,它是一个位于spring cloud项目中的open service内的基础框架,用来统一处理请求和返回。其中,为了实现数据的转换,我开发了一个小工具,叫做“FastConverter”。最初它被用来将数据实体转换为json string,在转换的过程中,使用注解的方式来定义数据转换逻辑。
后来在完成其他一些公司任务的过程中,我发现,这个FastConverter比我预期的还好用。它成功的将那些修饰数据形式的代码从业务逻辑代码中分离了出去。我不用在开发过程中去关心数据最后要呈现的样子,它们会被注解安全的修饰,并优雅的解决。
FastConvert好用的原因:BeanToMapConverterHandler
完整的FastConvert原理在我的另一篇博客《记一个小小的转换工具的开发:FastConverter》中。
public class CommonConverterFilter extends AbstractConverterFilter {
[@Override](https://my.oschina.net/u/1162528)
protected void initConverters(List<Converter<?, ?>> converters) {
converters.add(new StringConverterHandler());
converters.add(new NumberToStringConverterHandler());
converters.add(new BooleanToStringConverterHandler());
converters.add(new DateToTimeStampStringConverterHandler());
converters.add(new NullConverterHandler());
converters.add(new MapToMapConverterHandler<>(this));
converters.add(new ArrayToListConverterHandler<>(this));
converters.add(new CollectionToListConverterHandler<>(this));
converters.add(new BeanToMapConverterHandler(this));
}
}
在fastconverter中,有转换器过滤器(ConverterFilter)这一概念,你可以编写一个依赖于ConverterFilter的转换器,ConverterFilter能够为你提供一些默认数据的转换逻辑。比如上面代码所示的ConverterFilter。它是FastConverter提供的通用ConverterFilter,该ConverterFilter提供了对String,Number(包括int,long,double,float,BigDecimal),布尔值,日期,空,Map,数组,Collection,以及java Bean的默认转换方式的支持。当然你可以去实现你自己的ConverterFilter。
其中,BeanToMapConverterHandler的实现是对ConverterFilter使用的最好示例,同时BeanToMapConverterHandler成为了FastConverter好用的关键。简单来说,BeanToMapConverterHandler使用ConverterFilter提供的默认转换器来执行默认转换,而你,可以通过在Bean的域上配置@FieldConverter注解来指定特定的转换器对数据进行转换。
我的某些Bean长这个样
public class LoanApplyInfoFileUploadEntity implements BaseEntity {
private String name;
@Field(name = "pid")
private String idCard;
@FieldConverter(converter = LoanPurposeConverter.class)
private String loanPurpose;
@FieldConverter(converter = DateToFormatStringConverterHandler.class, tip = "yyyy-MM-dd'T'HH:mm:ss")
private Date uploadTs;
@FieldConverter(converter = DateToFormatStringConverterHandler.class, tip = "yyyy-MM-dd")
private Date dueDate;
@FieldConverter(converter = DateListToStringConverter.class, tip = "yyyy-MM-dd")
private List<Date> targetRepayDateList;
... 省略getter,setter
我只需要使用数据的原始java类型来组装bean,组装时也不用关心数据将来需要变成什么样子,无论数据将来会变成什么样,都有与逻辑分离的转换器可以一键解决(当然,你可以不使用BeanToMapConverterHandler,你可以编写适用于自己的BeanToXXXConverterHandler,或者其他任何ConverterHandler)。
小悟
关注点分离真的是编程工作中最得力的一把利器,是写出优雅代码的关键。记得《java编程思想》的“并发”一章,在聊到并发的作用时,举了一个事件驱动的例子。
实际上,使用并发最吸引人的一个原因就是要产生具有可响应的用户界面。考虑这样一个程序,它因为将执行某些长期运行的操作,所以最终用户输入会被忽略,从而成为不可响应的程序。如果有一个‘退出’按钮,那么你肯定不想在你写的每一段代码中都检查它的状态。因为这会产生非常尴尬的代码,而我们也无法保证程序员不会忘记检查。如果不使用并发,则产生可响应用户界面的唯一方式就是所有的任务都周期性地检查用户输入。
这虽是一个对并发能力的场景描述,但它也让我想到了关注点分离,写一个专门的并发程序去监听按钮的状态,就是一种关注点分离。虽然关注点分离是如此的重要和常见,但不得不说,我还是见到了许多“在每一段代码中都检查它的状态”的代码。实际上,代码上出现这种问题,还不是最可怕的,最可怕的是项目架构上出现这种问题,我相信有很多程序员在遭受这种架构的折磨。
如果你在开发的过程中遇到了数据转换方面的需求,不妨来试一试FastConverter吧,如果你有好的想法,欢迎交流,欢迎RP,它在这里(FastConverter的Github地址)