依赖冲突导致的问题定位
主要流程
现象: 项目提示某个依赖的方法不存在, 通过点击源码发现是存在的, 可能是依赖冲突导致的
猜测: 即使IDEA点击进去是一个版本,但是可能实际中打包编译的使用的是另一个版本导致找不到源码的对应方法
解决思路:
- 查看对应的日志提示看具体是哪个依赖包报错
- 定位实际编译具体使用的是哪个版本
- 最后使用pom中的exclude进行排除不想要的版本
怎么查看实际使用版本
点击源码对应的方法,再到左侧定位对应的版本即我们想要的版本
项目启动会有一个编译后的路径
找到对应的jar文件, 直接修改为.zip后缀然后再解压得到对应的META-INF
文件夹
使用编辑工具打开文件MANIFEST.MF
全局搜索找到对应的依赖,查看版本号
所以实际上使用的并不是common-io-2.11
这时候就可以插件maven helper
对冲突的依赖快速定位
找到冲突的依赖是common-fileupload
内部使用的common-io
是2.2版本,所以需要对其进行exclude排除
常见代码问题
easyExcel的坑
问题描述: 在easyExcel 2.2.6版本中, Excel中金额使用的是会计专用类型填充值, 读取数据时代码没有指定具体的dto进行解析, listener直接每行转成List<Object> data 进行获取, 再值自己根据业务逻辑进行类型转换. 这时候拿到的data 里面已经将Excel中金额数值超过10位长度(包含小数位)的数据进行了精度转换.
示例: 10,105,936,285.92 -> 10105936286, 最后得到10105936286的字符串, 这时候再自行转换已经没有意义
复现代码片段:
package pwc.taxtech.biz.output.dto.excel;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
import java.util.Date;
@Getter
@Setter
public class OutputNonOrderDto {
private String companyCode;
private String deptCode;
private String voucherNumber;
private Date voucherDate;
private String customerCode;
private String customerName;
private String invoiceType;
private String entityType;
private String productCode;
private String productName;
private String specification;
private String unit;
private BigDecimal quantity;
private BigDecimal unitPrice;
private BigDecimal amountWithOutTax;
private BigDecimal taxRate;
private BigDecimal taxAmount;
private BigDecimal discountAmount;
private Long rowIndex;
private String originalOrderNumber;
private String remark;
private Long deptId;
private String deptName;
/**
* 业务实体id
*/
private Integer ouId;
/**
* 税收分类编码
*/
private String taxClassificationCode;
}
List<OutputNonOrderDto> orderList;
ExcelOutputInvoiceNonOrderListenerAbstract listener = new ExcelOutputInvoiceNonOrderListenerAbstract();
ReadSheet readSheet =
EasyExcel.readSheet(0).head(OutputNonOrderDto.class).registerReadListener(listener).build();
ExcelReader excelReader = EasyExcel.read(new BufferedInputStream(file.getInputStream())).build();
excelReader.read(readSheet);
// 调用其它服务进行保存
errorMessages = listener.getMessageList();
orderList = listener.getOrderList();
public class ExcelOutputInvoiceNonOrderListenerAbstract extends AbstractNoneOrderListener {
private final Logger logger = LoggerFactory.getLogger(ExcelOutputInvoiceNonOrderListenerAbstract.class);
private final List<OutputNonOrderDto> orderList = new ArrayList<>();
private final List<ImportDataErrorMessage> messageList = new ArrayList<>();
private Long rowIndex = 0L;
private static final Integer COLUMN_SIZE = 17;
@Override
public void invoke(Object data, AnalysisContext context) {
List<Object> row = (List<Object>) data;
rowIndex++;
if (row.stream().allMatch(Objects::isNull)) {
return;
}
if (row.size() < COLUMN_SIZE) {
int size = COLUMN_SIZE - row.size();
for (int i = 0; i < size; i++) {
row.add(null);
}
}
OutputNonOrderDto order = new OutputNonOrderDto();
if (row.get(0) == null || row.get(0).toString().equals("")) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError49"); // ouId不能为空
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
} else {
try {
order.setOuId(Integer.parseInt(row.get(0).toString()));
}catch (Exception e) {
logger.error("ouId转换异常", e);
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError52"); // ouId格式或类型不正确
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
}
}
if (row.get(1) == null || row.get(1).toString().equals("")) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.voucherImportCheckError1"); // (单据编号) 凭证编号不能为空
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
} else {
order.setVoucherNumber(row.get(1).toString());
}
if (row.get(2) == null || row.get(2).toString().equals("")) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.voucherImportCheckError2"); // (单据日期) 凭证日期不能为空
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
} else {
try {
//兼容2023/12/31格式
String date = row.get(2).toString().replaceAll("/", "").replaceAll("-", "");
order.setVoucherDate(DateUtils.parseDate(date, "yyyyMMdd"));
} catch (ParseException e) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.voucherImportCheckError3"); // 凭证日期格式或类型不正确
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
order.setVoucherDate(null);
}
}
if (row.get(3) == null || row.get(3).toString().equals("")) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError10"); // 客户编码不能为空
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
} else {
// 22657 需要兼容 只取数字
order.setCustomerCode(handleSpecialStr(row.get(3).toString()));
}
//发票类型变更为非必填
if (row.get(4) != null && !row.get(4).toString().equals("")) {
if (!OutputVatInvoiceTypeEnum.SpecialInvoice.getCode().toString().equals(row.get(4))
&& !OutputVatInvoiceTypeEnum.NormalInvoice.getCode().toString().equals(row.get(4))) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError12"); // 发票类型数值不正确,只能是专票或普票
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
} else {
order.setInvoiceType(row.get(4).toString());
}
}
//发票实体变更为非必填
if (row.get(5) != null && !row.get(5).toString().equals("")) {
if (!InvoiceEntityEnum.getCodeStrList().contains(row.get(5).toString())) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError34");
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
} else {
order.setEntityType(row.get(5).toString());
}
}
order.setRemark(row.get(6) == null ? null : row.get(6).toString());
//商品编码 可以为空
order.setProductCode(row.get(7) == null ? "" : row.get(7).toString());
//"商品名称" 不能为空
if (row.get(8) == null || row.get(8).toString().equals("")) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError11"); // 商品名称不能为空
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
}else {
order.setProductName(handleSpecialStr(row.get(8).toString()));
}
//"税收分类编码 index 9
//TaxClassificationCode() < 19 后面补齐0到19位
order.setTaxClassificationCode(row.get(9) == null ? StrUtil.fillAfter("", '0', 19) : row.get(9).toString().length() < 19 ? StrUtil.fillAfter(row.get(9).toString(), '0', 19) : row.get(9).toString());
if (row.get(10) == null || row.get(10).toString().equals("")) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError14"); // 数量不能为空
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
order.setQuantity(new BigDecimal(0));
} else {
try {
order.setQuantity(row.get(10) == null ? null : new BigDecimal(row.get(10).toString()));
} catch (NumberFormatException e) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError15"); // 数量格式或类型不正确
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
order.setQuantity(new BigDecimal(0));
}
}
if (row.get(11) == null || row.get(11).equals("")) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError30"); // 不含税金额不能为空
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
order.setAmountWithOutTax(new BigDecimal(0));
} else {
try {
//兼容千分位格式
order.setAmountWithOutTax(new BigDecimal(StrUtil.removeAll(row.get(11).toString(), ",")));
} catch (NumberFormatException e) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError33"); // 不含税金额格式或类型不正确
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
order.setAmountWithOutTax(new BigDecimal(0));
}
}
if (row.get(12) == null || row.get(12).toString().equals("")) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError20"); // 税率不能为空
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
order.setTaxRate(new BigDecimal(0));
} else {
try {
//处理百分号
if (row.get(12).toString().contains("%")) {
order.setTaxRate(new BigDecimal(StrUtil.removeAll(row.get(12).toString(), "%")).divide(new BigDecimal(100)));
} else {
order.setTaxRate(new BigDecimal(row.get(12).toString()));
}
} catch (NumberFormatException e) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("invoice.output.orderImportCheckError21"); // 税率格式或类型不正确
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
order.setTaxRate(new BigDecimal(0));
}
}
// 凭证暂时没有折扣金额
//order.setDiscountAmount(new BigDecimal(0));
//单位 非必填
order.setUnit(row.get(13) == null ? "" : handleSpecialStr(row.get(13).toString()));
//规格型号 非必填
order.setSpecification(row.get(14) == null ? "" : handleSpecialStr(row.get(14).toString()));
order.setUnitPrice(order.getAmountWithOutTax().divide(order.getQuantity(), 8, RoundingMode.HALF_UP));
//根据需求,税额四舍五入保留2位
BigDecimal calculateTaxAmount = order.getAmountWithOutTax().multiply(order.getTaxRate()).setScale(2, RoundingMode.HALF_UP);
//折扣金额
if (row.size()<16 || row.get(15) == null || row.get(15).equals("")) {
order.setDiscountAmount(new BigDecimal(0));
} else {
try {
//兼容千分位格式
order.setDiscountAmount(new BigDecimal(StrUtil.removeAll(row.get(15).toString(), ",")));
} catch (NumberFormatException e) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("折扣金额格式或者类型不正确"); // 不含税金额格式或类型不正确
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
order.setDiscountAmount(new BigDecimal(0));
}
}
//税额
if (row.get(16) != null && !row.get(16).toString().equals("")) {
try {
//兼容千分位格式
BigDecimal taxAmount = new BigDecimal(StrUtil.removeAll(row.get(16).toString(), ","));
//若【税额】与【【不含税金额】*【税率】的值差异>0.6则提示税额有错不允许导入
if (calculateTaxAmount.subtract(taxAmount).abs().compareTo(new BigDecimal(0.6)) > 0) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("税额与不含税金额*税率的值差异大于0.6"); // 税额与不含税金额*税率的值差异大于0.6
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
}
order.setTaxAmount(taxAmount);
} catch (NumberFormatException e) {
ImportDataErrorMessage message = new ImportDataErrorMessage();
message.setErrorMessage("税额格式或者类型不正确"); // 税额格式或者类型不正确
message.setRowIndex(rowIndex);
message.setMessageCode("-1");
messageList.add(message);
order.setTaxAmount(new BigDecimal(0));
}
}else {
order.setTaxAmount(calculateTaxAmount);
}
order.setRowIndex(rowIndex);
orderList.add(order);
}
private String handleSpecialStr(String str) {
return str.replace("\u202D", "").replace("\u202C", "");
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// System.out.println(context.get());
}
public List<OutputNonOrderDto> getOrderList() {
return this.orderList;
}
public List<ImportDataErrorMessage> getMessageList() {
return this.messageList;
}
}
看了下最新版的源码, 确实是个bug, 使用已修复的版本即可, 如果项目上直接上新版本不兼容就只能手动指定类型进行解析
最新版本easyExcel3.3.4解析正常
Lombok的坑
第一个字母小写第二个字母大写的字段默认方法set赋值问题
https://www.cnblogs.com/aaacarrot/p/17448281.html
BigDecimal类型的0值比较
场景: 参与除法运算, 判断分母数据不能为0
不能直接使用equals比较, 否则比较时实际会参考小数位精度
源码:
@Override
public boolean equals(Object x) {
if (!(x instanceof BigDecimal))
return false;
BigDecimal xDec = (BigDecimal) x;
if (x == this)
return true;
if (scale != xDec.scale)
return false;
long s = this.intCompact;
long xs = xDec.intCompact;
if (s != INFLATED) {
if (xs == INFLATED)
xs = compactValFor(xDec.intVal);
return xs == s;
} else if (xs != INFLATED)
return xs == compactValFor(this.intVal);
return this.inflated().equals(xDec.inflated());
}
所以只能使用compareTo方法和BigDecimal.ZERO进行比较 等于0则说明是0值,不等则非0
data.compareTo(BigDecimal.ZERO) == 0
sql统计转换decimal类型导致的精度丢失
sql内置的cast直接转为decimal默认小数位的精度默认为0, 所以会导致精度丢失
需要指明精度大小
金额相关业务需要注意decimal的精度比较和数据库的精度存储保持一致
比如代码中BigDecimal(18,4), 那么数据库中的Decimal存储类型需要和使用的精度保持一致
sql对join查询的维度问题
对于
from organization org left join analysis_monthly_tax amt on org.id = amt.org_id
还是
from analysis_monthly_tax amt right join organization org on org.id = amt.org_id
如果关联到第三张表, 则存在维度统计的问题
如果是left join 那么
select sum(cast(ifnull(amt.val, 0) as decimal(18,2))) sumVal,
count(distinct org.id),
country.name countryName
from organization org
left join analysis_monthly_tax amt on org.id = amt.org_id
and amt.source = 'DATA.ZBKSH002'
and amt.col_name in ('税金合计')
and org.tenant_id = 'EMS_Default'
and amt.tenant_id = 'EMS_Default'
AND amt.period >= 202211
AND amt.period <= 202312
join country_list country on country.id = org.jurisdiction_of_formation
and country.tenant_id = 'EMS_Default'
where 1=1
and country.tenant_id = 'EMS_Default'
group by countryName;
out of range value for column mysql decimal
https://juejin.cn/s/out%20of%20range%20value%20for%20column%20mysql%20decimal
Date类型存入数据库中的datetime多了一秒?
使用的工具是: cn.hutool.core.date.DateUtil
public static void main(String[] args) throws Exception {
DateTime dateTime = DateUtil.lastMonth();
Date end = DateUtil.endOfMonth(dateTime);
System.out.println("工具日期: " + end + " 精度: " + end.getTime());
String time = "2023-11-30 23:59:59";
System.out.println("转换: " + time + " 精度: " + DateUtil.parseDateTime(time).getTime());
System.out.println(DateUtil.date(1701359999999L));
}
// 工具日期: 2023-11-30 23:59:59 精度: 1701359999999
// 转换: 2023-11-30 23:59:59 精度: 1701359999000
// 2023-11-30 23:59:59
说明hutool的精度更高, 得到的截止最后的时间是毫秒级别, 而数据库中的使用的时间类型是datetime类型
字段用的mysql的datetime类型,这个字段的长度默认是0,也就是说,默认不保存秒级以下的,就是不保存毫秒值,但会做四舍五入,如果是500毫秒以下,就省略,如果是500毫秒以上的时间,就会多一秒
如果直接将当前得到的截止时间存入数据库则会导致数据库显示的时间为 2023-12-01 00:00:00
提交的表单或者excel读取因为Unicode不可见字符导致的数据匹配不上
Unicode U202D 和 U202C 会导致看起来一样的文本在匹配逻辑中实际上是匹配不上的
Unicode U202D 和 U202C 问题总结_%u202d-CSDN博客
常见配置问题
yml配置导致的启动失败
文件重复, resources下和config下保留一份即可, 不然会导致解析异常, 导致循环解析栈溢出
17:09:27.924 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.StackOverflowError: null
at java.lang.String.indexOf(String.java:1503)
at java.net.URLStreamHandler.parseURL(URLStreamHandler.java:143)
at sun.net.www.protocol.file.Handler.parseURL(Handler.java:67)
at java.net.URL.<init>(URL.java:640)
at java.net.URL.<init>(URL.java:508)
at sun.misc.URLClassPath$FileLoader.getResource(URLClassPath.java:1384)
at sun.misc.URLClassPath.getResource(URLClassPath.java:253)
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:757)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:473)
at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:757)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:473)
at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:403)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.lambda$null$1(Binder.java:435)
at org.springframework.boot.context.properties.bind.Binder$Context.withSource(Binder.java:566)
at org.springframework.boot.context.properties.bind.Binder$Context.access$700(Binder.java:537)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindAggregate$2(Binder.java:436)
at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:106)
at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:86)
at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:70)
at org.springframework.boot.context.properties.bind.CollectionBinder.bindAggregate(CollectionBinder.java:49)
at org.springframework.boot.context.properties.bind.AggregateBinder.bind(AggregateBinder.java:56)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindAggregate$3(Binder.java:438)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.access$100(Binder.java:537)
at org.springframework.boot.context.properties.bind.Binder.bindAggregate(Binder.java:438)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:399)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:472)
at org.springframework.boot.context.properties.bind.ValueObjectBinder$ConstructorParameter.bind(ValueObjectBinder.java:299)
at org.springframework.boot.context.properties.bind.ValueObjectBinder.bind(ValueObjectBinder.java:73)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576)
at org.springframework.boot.context.properties.bind.Binder$Context.access$300(Binder.java:537)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:332)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:262)
at org.springframework.boot.context.config.ConfigDataProperties.get(ConfigDataProperties.java:107)
at org.springframework.boot.context.config.ConfigDataEnvironmentContributor.withBoundProperties(ConfigDataEnvironmentContributor.java:241)
at org.springframework.boot.context.config.ConfigDataEnvironmentContributorPlaceholdersResolver.isActive(ConfigDataEnvironmentContributorPlaceholdersResolver.java:90)
at org.springframework.boot.context.config.ConfigDataEnvironmentContributorPlaceholdersResolver.resolvePlaceholder(ConfigDataEnvironmentContributorPlaceholdersResolver.java:70)
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:153)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.boot.context.config.ConfigDataEnvironmentContributorPlaceholdersResolver.resolvePlaceholders(ConfigDataEnvironmentContributorPlaceholdersResolver.java:60)
at org.springframework.boot.context.properties.bind.Binder.bindProperty(Binder.java:458)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:403)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.lambda$null$1(Binder.java:435)
at org.springframework.boot.context.properties.bind.Binder$Context.withSource(Binder.java:566)
at org.springframework.boot.context.properties.bind.Binder$Context.access$700(Binder.java:537)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindAggregate$2(Binder.java:436)
at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:106)
at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:86)
at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:70)
at org.springframework.boot.context.properties.bind.CollectionBinder.bindAggregate(CollectionBinder.java:49)
at org.springframework.boot.context.properties.bind.AggregateBinder.bind(AggregateBinder.java:56)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindAggregate$3(Binder.java:438)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.access$100(Binder.java:537)
at org.springframework.boot.context.properties.bind.Binder.bindAggregate(Binder.java:438)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:399)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:472)
at org.springframework.boot.context.properties.bind.ValueObjectBinder$ConstructorParameter.bind(ValueObjectBinder.java:299)
at org.springframework.boot.context.properties.bind.ValueObjectBinder.bind(ValueObjectBinder.java:73)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576)
at org.springframework.boot.context.properties.bind.Binder$Context.access$300(Binder.java:537)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:332)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:262)
at org.springframework.boot.context.config.ConfigDataProperties.get(ConfigDataProperties.java:107)
at org.springframework.boot.context.config.ConfigDataEnvironmentContributor.withBoundProperties(ConfigDataEnvironmentContributor.java:241)
at org.springframework.boot.context.config.ConfigDataEnvironmentContributorPlaceholdersResolver.isActive(ConfigDataEnvironmentContributorPlaceholdersResolver.java:90)
at org.springframework.boot.context.config.ConfigDataEnvironmentContributorPlaceholdersResolver.resolvePlaceholder(ConfigDataEnvironmentContributorPlaceholdersResolver.java:70)
雪花ID浏览器获取精度丢失问题
自测正常展示
浏览器端精度丢失, 最后两位都变成00
解决方案:
添加 @JsonSerialize(using = ToStringSerializer.class)