当前位置: 首页 > 知识库问答 >
问题:

与Spring boot devtools相关的推土机地图异常

萧心远
2023-03-14

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

业务背景:添加商品同时是价目表,一个商品对不同级别的用户有5个价格。

在controller中,首先使用推土机将goodForm转换为商品,然后调用goodsService保存商品。在goodsService中,保存商品后,遍历商品价格表,将goodsId填充到商品价格中,

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()));

运行这个单元测试,它执行正常。那么为什么在真实的Web情况下(Spring bootJpa)它失败了,但在单元测试情况下它没问题呢?

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中评论了spring boot开发工具。xml,然后启动应用程序,没有上述异常。

共有2个答案

沈凯康
2023-03-14

您在这里使用了两个不同的ClassLoader。JVM将加载有两个不同ClassLoader的相同Class视为两个不同的Class

解决这个问题的方法很简单:使用一个界面。

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

岳池暝
2023-03-14

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

Spring开发工具。属性文件可以包含重新启动。排除然后重新启动。包括前缀属性。include元素是应该向上拉入“重新启动”类加载器的项,exclude元素是应该向下推入“基本”类加载器的项。该属性的值是将应用于类路径的正则表达式模式。

我的解决方案是:放置META-INF/spring开发工具。属性,并添加此内容

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

请参见:http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-引导devtools自定义类加载

 类似资料:
  • 我正在使用推土机从一个对象映射到另一个对象。我知道Dozer可以做递归映射,但也许我对Dozer施加了太大的压力:p我想从类a映射到类B 当我从A映射到B时,我得到了一个B的实例,但在映射中我得到了一个ObjectA的列表。明确地说,我得到了这个(想象的)对象的一个实例: 如何使推土机正确执行此映射? 注意:ObjectA和ObjectB具有相同的属性(以及int和字符串)。

  • 我想让推土机地图成为我的职业: 到生成的,如下所示: . 也就是说,我正在尝试将嵌套类的字段映射到平面键目标。我使用的是JavaAPI的Dozer,而不是xml。我无法找到适当的构建器配置来管理它。基本代码类似于:

  • 我有一个类,我们用一个映射字段将其称为a,它被转换为B类,用于数据库存储/检索,其中该字段映射到字符串。从A到B的映射非常有效。然而,当从B到A时,我得到了一个IllegalArgument异常,它表示无法将字符串转换为映射。让我困惑的是,Dozer的文档中说,这确实适用于以下情况: 数据类型转换由Dozer映射引擎自动执行。目前,Dozer支持以下类型的转换:(这些都是双向的) 然后它继续列出要

  • 我试图使用Dozer映射UUID字段,遇到了Dozer github上提到的一个问题: https://github.com/DozerMapper/dozer/issues/83 问题是-显然,Dozer依赖于UUID中不存在的默认无参数构造函数。因此,该链接显示了如何告知推土机执行参考复制。然而,使用该提示并没有帮助,我仍然会遇到以下异常: org.dozer.java.lang.java.u

  • 我有四门课: 从我在dozer留档中读到的关于继承的内容来看,它必须非常简单,我需要将超级类相互映射,以及子类。以下是它在xml中的外观: 所有这些类都是相同的,我的意思是D和D具有相同的属性,C和C等等。 问题:在我传递给dozer的对象中,我有一个类型为B的属性,它可以由C或D(多态性)初始化。当dozer返回新的映射对象时,它总是将属性类型B返回给我,而不是C或D。如何解决这个问题?

  • 我在Spring启动时使用推土机映射器。如果我将数据从实体映射到EntityDTO,那么dozer maper的工作就是将数据从实体类复制到EntityDTO,对于原语也是如此。但是假设我有这样一门课 和名称为EntityDTO的DTO 那么它不会将数据从entityChild映射到EntityChildTos,有人能帮我解决这个问题吗?