top.codef
对于跟多系统中对于金钱的计算是必不可少的,而且关于钱的计算,就连最基础的程序猿也知道不能用基础的加减乘除计算。网上关于钱的计算解决方案也很多,本框架主要基于JSR-354的一个实现框架:org.javamoney.moneta的基础上建立了一整套的javamoney的使用,序列化与持久化处理;同时,还支持了mongodb、gson、redis等序列化与存储
JavaMoney是Java™平台以及相关项目和库的新货币API。API(JSR 354)提供了用于处理货币模型的可移植且可扩展的API,而Moneta提供了可用于生产的参考实现。货币API是基于ISO 4217标准而指定的,JavaMoney库添加了在API之上构建的其他功能,例如
ISO 4217用于代表货币和资金。本标准规定了一个三个字母的字母代码和相当于3位数的代码来代表货币和资金。对于那些小单位货币,它也显示了这些单位和货币本身的十进制关系。对于ISO 4217具体信息请参照百度百科 https://baike.baidu.com/item/ISO%204217/11018231?fromtitle=ISO4217&fromid=11174838&fr=aladdin
本框架主要基于Moneta而实现了在web-mvc与jpa中的对外的数据格式化以及对内货币使用,主要包含了3个大块,分别是:
将此工程通过mvn clean install
打包到本地仓库中。
在你的spring-boot(web工程)项目的pom.xml
中引入:
<dependency>
<groupId>com.kuding</groupId>
<artifactId>mercury-spring-boot-starter</artifactId>
<version>0.1.5</version>
</dependency>
application.properties(yml)
区域信息mercury.money.locale=simplified-chinese
public class MyPocket {
private Long id;
@Money
private MonetaryAmount money;
//getters and setters
}
@Money(com.kuding.anno.Money)
是本框架的核心注解,用户解析请求中金钱相关的数据结构,MonetaryAmount
是javamoney
中货币的基础数据结构
@RestController
@RequestMapping("/money")
public class MoneyTestController {
@Autowired
private MercuryProperties mercuryProperties;
@PostMapping("/getMoney")
public MyPocket genericPocket() {
MyPocket myPocket = new MyPocket(1L, FastMoney.of(new BigDecimal(1111111L),
Monetary.getCurrency(mercuryProperties.currentLocale())));
return myPocket;
}
}
调用接口就可以出现如下结果:
返回的结果中,
money
返回值为"CNY1,111,111.00"
,其中CNY
表示的是ISO4217标准中人民币的对应代码(人民币 China Yuan Renminbi (CNY)),后面的数字表示的是货币金额的标准化输出(三位逗号分隔,保留两位小数)
在controller层再加入一个请求接口:
@PostMapping("/createMoneyByBody")
public MyPocket createPocket(@RequestBody MyPocket myPocket) {
return myPocket;
}
调用接口后会有如下效果:
在controller中再加入一个接口:
@PostMapping("/createMoney")
public MyPocket createPocket(@RequestParam @ApiParam(value = "id", required = true) Long id,
@RequestParam @Money @ApiParam MonetaryAmount money) {
MyPocket myPocket = new MyPocket(id, money);
return myPocket;
}
调用接口会有如下结果:
mercury.money.locale=simplified-chinese
mercury.money.strict-currency=false
mercury.money.pattern=#0.00
- ``mercury.money.locale``表示货币的区域选择,目前只包含了Locale中常见区域选择
- ``strict-currency``表示是否是严格的货币单位,对于假如解析货币的过程中没有匹配到对应的货币单位,就会抛出异常
- ``pattern``表示的是货币格式化的表达式,主要是通过``java.text.DecimalFormat``进行的解析,类似于正则表达式,具体的一些符号与意义如下表
符号 | 表示位置 | 是否是局部使用 | 说明 |
---|---|---|---|
0 | 数字 | 是 | 表示一个数字,没有的话用0占位 |
# | 数字 | 是 | 表示一个数字,没有的话不显示 |
. | 数字 | 是 | 表示小数点 |
- | 数字 | 是 | 表示负号 |
, | 数字 | 是 | 表示数字分组 |
E | 数字 | 是 | 科学技术法标识符 |
; | 子表达式边界符号 | 是 | 用来区分正数与负数表达式的 |
% | 前缀或后缀 | 是 | 百分数表示(格式化输出数会乘以100) |
‰(\u2030) | 前缀或后缀 | 是 | 千分数表示 |
¤ (\u00A4) | 前缀或后缀 | 否 | 货币符号(重要) |
例如:
在配置中:mercury.money.pattern=#,##0.00
表示的是:每三位用,
分隔,保留两位小数,0
格式化为0.00
。
Locale
所展现的格式是不一样的,pattern
与locale
配置之间存在冲突,所以这里有这样一个优先级:优先比配pattern
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface Money {
MoneyFormatStyle value() default MoneyFormatStyle.DEFAULT;
MoneyFormatStyle in() default MoneyFormatStyle.DEFAULT;
MoneyFormatStyle out() default MoneyFormatStyle.DEFAULT;
}
@Money
注解主要用于controller层的参数传入与结果输出的格式化问题,目前格式化风格包含三种:
1. 默认格式化类型
2. 数字类型
3. 对象类型
@Money
private MonetaryAmount money;
配置项如下(yml):
mercury:
money:
locale: simplified-chinese
pattern: '¤#0.00'
strict-currency: false
server:
port: 9001
返回结果如下:
{ ... "money": "CNY12345678.90" }
若只需要数字,只需要将注解变为@Money(MoneyFormatStyle.NUM_ONLY)
,输出就会变为"money": "12345678.90000"
,实际上若需要显示货币金额且要有一定格式化的话,可以通过pattern
进行处理,如pattern: '#,##0.00'
,@Money(MoneyFormatStyle.DEFAULT)
, 则返回结果为:"money": "12,345,678.90"
前面的所有的处理主要面向的是服务端请求的输入与输出问题,主要是基于fasterxml
序列化框架而开发(spring web引用),服务端向数据层的输入与输出主要依靠spring data jpa
,其底层则是基于JPA(Java Persistence API)
规范,由hibernate实现。所以这里就是将MonetaryAmount
结构类型与数据库的基本类型进行了对接,主要是通过TypeContributor
与BasicJavaDescriptor
来实现,具体实现可以看本项目源码。
application.properties(yml)
开启money类型的的配置项:mercury:
money:
persist:
open-monetary-basic-type-persist: true
money-data-type: bigint
persist-on-multiply100: true #表示数据库数值与服务中的数值差100倍,即存入数据库前会把money的数值乘以100
@Entity
注解使用了@Getter
@Setter
@Entity
public class Pocket {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long personId;
private MonetaryAmount moneyAmount;
private LocalDateTime createTime = LocalDateTime.now();
}
名称 | 参数类型 | 说明 | 必要配置 |
---|---|---|---|
open-monetary-basic-type-persist | boolean | 用于开启项目配置,属于总控开关(默认false) | 是 |
money-data-type | enum | 数据库字段类型(enum),目前支持三种:DECIMAL,VARCHAR,BIGINT | 是 |
persist-on-multiply100 | boolean | 在存入数据前是否乘以100?默认为(false) | 否 |
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。