Cannot construct org.apache.maven.plugin.war.util.WebappStructure as it does not have a no-args cons

工作中遇到一个问题,
使用openjdk1.8 + maven-war-plugin:2.5 进行打包时会报错。使用oraclejdk 1.8则不会报错
Cannot construct org.apache.maven.plugin.war.util.WebappStructure as it does not have a no-args constructor

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.5</version>
    </plugin>
</pligins>

当你给插件配置了时就会报上面提到的错误

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.5</version>
		<executions>
		    <execution>
		        <id>prepare-war</id>
		        <phase>prepare-package</phase>
		        <goals>
		            <goal>exploded</goal>
		        </goals>
		    </execution>
		</executions>

解决方案有2种
方案一,直接升级插件2.5到3.2.2


方案二,解决抛异常的真正原因,是由于maven-war-plugin:2.5 使用了反序列化 xstream:1.4.4抛出的异常
根据社区的信息
https://github.com/x-stream/xstream/issues/360
大致意思是:
11 年前(也就是2013年) XStream 1.4.4 发布时,所有可用的 Java 8 运行时环境都标识自己为版本 1.8。而当前的 OpenJDK Java 8 标识自己为版本 8。因此,XStream 1.4.4 不知道这个版本支持什么,于是退回到纯 Java 模式,这种模式无法创建没有默认构造函数的对象。这就是为什么存在 XStream 1.4.20 的原因……

<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4.4</version>
</dependency>

经过实验1.4.10就可以解决这个问题于是可以通过配置dependencies 去避免这个报错,同样可以解决问题

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.5</version>
                <dependencies>
                    <dependency>
                        <groupId>com.thoughtworks.xstream</groupId>
                        <artifactId>xstream</artifactId>
                        <version>1.4.10</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <warName>openjdk1.8-war2.5</warName>
                    <useCache>true</useCache>
                </configuration>
                <executions>
                    <execution>
                        <id>prepare-war</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>exploded</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
### 解决Java中Redis存储Map时出现的SerializationException问题 在使用Spring Data Redis进行对象存储时,`SerializationException`通常是因为Redis无法正确序列化或反序列化对象引起的。以下是针对此问题的详细解决方案[^1]。 #### 问题原因 当尝试将自定义对象(如`User`类)存储到Redis时,如果未正确配置序列化器,Redis默认会使用`JdkSerializationRedisSerializer`进行序列化和反序列化。然而,这种默认序列化方式可能会导致以下问题: - 如果对象没有无参构造函数,则会抛出`Cannot construct instance of`异常。 - 如果对象未实现`Serializable`接口,也会导致序列化失败。 此外,如果使用了JSON格式进行序列化,但未正确配置`ObjectMapper`,也可能导致类似问题。 #### 解决方案 ##### 方法一:使用`GenericJackson2JsonRedisSerializer` 通过配置`RedisTemplate`使用`GenericJackson2JsonRedisSerializer`作为序列化器,可以解决JSON序列化问题。以下是具体配置代码: ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); // 使用String作为Key的序列化器 template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); // 使用GenericJackson2JsonRedisSerializer作为Value的序列化器 GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer(); template.setValueSerializer(jsonSerializer); template.setHashValueSerializer(jsonSerializer); return template; } } ``` ##### 方法二:确保实体类符合序列化要求 如果继续使用默认的`JdkSerializationRedisSerializer`,则需要确保实体类满足以下条件: - 实现`Serializable`接口[^3]。 - 提供无参构造函数。 - 所有字段均为可序列化的类型。 示例实体类定义如下: ```java import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age; // 无参构造函数 public User() {} public User(String name, int age) { this.name = name; this.age = age; } // Getter和Setter方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{name='" + name + "', age=" + age + "}"; } } ``` ##### 方法三:自定义序列化器 如果项目中有特殊需求,可以实现自定义序列化器。例如,使用`ObjectMapper`手动控制JSON序列化过程。以下是一个示例: ```java import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; import java.nio.charset.StandardCharsets; public class Jackson2JsonRedisSerializer<T> implements RedisSerializer<T> { private final ObjectMapper objectMapper; public Jackson2JsonRedisSerializer(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } @Override public byte[] serialize(T t) throws SerializationException { if (t == null) { return new byte[0]; } try { return objectMapper.writeValueAsString(t).getBytes(StandardCharsets.UTF_8); } catch (Exception e) { throw new SerializationException("Could not serialize", e); } } @Override public T deserialize(byte[] bytes) throws SerializationException { if (bytes == null || bytes.length == 0) { return null; } try { return objectMapper.readValue(new String(bytes, StandardCharsets.UTF_8), (Class<T>) objectMapper.getTypeFactory().constructType(Object.class)); } catch (Exception e) { throw new SerializationException("Could not deserialize", e); } } } ``` 然后,在`RedisConfig`中使用自定义序列化器: ```java @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(objectMapper); template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setValueSerializer(serializer); template.setHashValueSerializer(serializer); return template; } ``` #### 测试代码 以下是一个测试存储和获取Map数据的示例代码: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.HashOperations; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.Map; @Service public class RedisService { @Autowired private RedisTemplate<String, Object> redisTemplate; public void storeMap() { HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash(); Map<String, Object> mapData = new HashMap<>(); mapData.put("user1", new User("frx", 21)); mapData.put("user2", new User("tiger", 18)); hashOperations.putAll("users", mapData); } public Map<String, Object> retrieveMap() { HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash(); return hashOperations.entries("users"); } } ``` #### 注意事项 - 确保所有存储到Redis中的对象都支持序列化。 - 如果使用JSON序列化,推荐使用`GenericJackson2JsonRedisSerializer`以避免复杂对象的序列化问题[^4]。 - 在高并发场景下,建议优化Redis连接池配置以提高性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诗水人间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值