繁体   English   中英

与Spring引导devtools相关的推土机映射异常

[英]A dozer map exception related to Spring boot devtools

我遇到了一个非常奇怪的异常,我不知道如何找到原因。

商业背景:添加商品并同时列出价格表,商品有差价水平用户的5个价格。

在控制器中,首先使用dozer将goodForm转换为商品,然后调用goodsService来保存商品。 在货物服务保存货物后,遍历货物价格表并填充货物ID到货物价格,

GoodsForm:
@Mapping("priceList")
List<GoodsPriceForm> goodsPriceFormList;
Goods:
List<GoodsPrice> priceList;

Controller: 
Goods goods = BeanMapper.map(goodsForm, Goods.class);
goodsService.saveGoods(adminId, goods);

GoodsService:
goodsDao.save(goods);
goods.getPriceList().forEach(p -> p.setGoodsId(goods.getId()));
goodsPriceDao.save(goods.getPriceList());

但它抛出异常:

2015-11-27 17:10:57,042 [http-nio-8081-exec-8] ERROR o.a.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: com.foo.goods.model.GoodsPrice cannot be cast to com.foo.goods.model.GoodsPrice] with root cause
java.lang.ClassCastException: com.foo.goods.model.GoodsPrice cannot be cast to com.foo.goods.model.GoodsPrice
at com.foo.goods.service.GoodsService$$Lambda$11/310447431.accept(Unknown Source) ~[na:na]
at java.util.ArrayList.forEach(ArrayList.java:1249) ~[na:1.8.0_51]
at com.foo.goods.service.GoodsService.saveGoods(GoodsService.java:34) ~[classes/:na]

这个错误信息让我感到很困惑。 另外我写一个单元测试想重复这个,但失败了。

GoodsForm form = new GoodsForm();
form.setGoodsPriceFormList(Lists.newArrayList(new GoodsPriceForm((byte) 1, BigDecimal.valueOf(10)),
new GoodsPriceForm((byte) 2, BigDecimal.valueOf(9)),
new GoodsPriceForm((byte) 3, BigDecimal.valueOf(8))));

Goods goods = BeanMapper.map(form, Goods.class);
goods.getPriceList().forEach(p -> p.setGoodsId(goods.getId()));

运行此单元测试,执行正常。 那么为什么在真实的网络情况下(Spring boot + Jpa)它失败了,但在单元测试情况下它还可以吗?


Controller:
System.out.println("PriceList: " + goods.getPriceList().getClass().getClassLoader());//PriceList: null
System.out.println(goods.getPriceList().get(0).getClass().getClassLoader()); //java.lang.ClassCastException: com.foo.goods.model.GoodsPrice cannot be cast to com.foo.goods.model.GoodsPrice

如果我生成了一个打包的jar,那么执行这个jar

java -jar target/myapp.jar

在这种情况下没有上述例外。


我在pom.xml中评论了spring-boot-devtools,然后启动了应用程序,没有异常。

默认情况下,将使用“restart”类加载器加载IDE中的任何打开项目,并使用“base”类加载器加载任何常规.jar文件。 如果您处理多模块项目,而不是将每个模块导入IDE,则可能需要自定义项目。 为此,您可以创建META-INF / spring-devtools.properties文件。

spring-devtools.properties文件可以包含restart.exclude。 并重新启动。包含。 前缀属性。 include元素是应该被提升到“restart”类加载器中的项,而exclude元素是应该被下推到“base”类加载器中的项。 属性的值是将应用于类路径的正则表达式模式。

我的解决方案:将META-INF/spring-devtools.properties放在资源文件夹中,并添加此内容

restart.include.dozer=/dozer-5.5.1.jar

请参阅: http//docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-devtools-customizing-classload

您在这里使用两个不同的ClassLoader 相同的Class装载有两个不同的ClassLoader被认为是两个不同的 Class由JVM。

解决此问题的解决方案很简单:使用Interface

接口能够解决这个问题,只要不直接引用实现,就可以无限制地在ClassLoader之间交换它们实现的对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM