SpringBoot+JSF应用启动失败,抛出MalformedParameterizedTypeException异常
嘿,我之前也碰到过几乎一模一样的问题——Tomcat跑起来顺得不行,一部署到WildFly就炸,核心就是这个MalformedParameterizedTypeException,还牵扯到PrimeFaces视图和Weld组件。偶尔用mvn wildfly:run能成,但重复操作必崩对吧?别慌,这大概率是类加载冲突或者Spring与WildFly自带CDI(Weld)的兼容性问题,给你几个亲测有效的解决步骤:
1. 调整依赖范围,避免和WildFly自带组件打架
WildFly本身已经自带了很多Java EE标准的API,比如javax.servlet-api、cdi-api、jaxb-api这些,如果你的项目里还把它们当成compile依赖引入,就会和WildFly自带的版本撞车。赶紧改你的pom.xml:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <!-- JSTL WildFly不一定自带,保持compile就行 --> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> <!-- WildFly自带,设为provided让容器提供 --> </dependency> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <scope>provided</scope> <!-- JAXB也是WildFly自带的,同样设为provided --> </dependency> <dependency> <groupId>org.eclipse.jdt.core.compiler</groupId> <artifactId>ecj</artifactId> <version>4.6.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.7</version> </dependency> <dependency> <groupId>org.joinfaces</groupId> <artifactId>primefaces-spring-boot-starter</artifactId> <!-- 这里一定要指定和Spring Boot匹配的版本!比如Spring Boot 2.7.x对应JoinFaces 4.7.x --> <!-- <version>4.7.1</version> --> </dependency> <dependency> <groupId>javax.enterprise</groupId> <artifactId>cdi-api</artifactId> <scope>provided</scope> <!-- WildFly自带Weld,设为provided --> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
2. 给WildFly加类加载隔离配置
在项目的src/main/webapp/WEB-INF目录下新建jboss-deployment-structure.xml,强制WildFly避开自带的冲突组件,优先用你项目里的依赖:
<?xml version="1.0" encoding="UTF-8"?> <jboss-deployment-structure> <deployment> <!-- 排除WildFly自带的CDI、JAX-RS子系统,避免和Spring的上下文冲突 --> <exclude-subsystems> <subsystem name="cdi"/> <subsystem name="jaxrs"/> </exclude-subsystems> <!-- 排除WildFly自带的Java EE API模块,防止版本冲突 --> <exclusions> <module name="javaee.api"/> <module name="javax.servlet.jstl.api"/> <module name="javax.xml.bind.api"/> <module name="javax.enterprise.api"/> </exclusions> <!-- 让项目自己的类优先加载 --> <dependencies> <module name="deployment.你的项目名.war" export="true"/> </dependencies> </deployment> </jboss-deployment-structure>
3. 确保Spring Boot和JoinFaces版本严格匹配
这个很关键!JoinFaces的版本必须和你的Spring Boot版本一一对应,比如:
- Spring Boot 2.7.x → JoinFaces 4.7.x
- Spring Boot 3.x → JoinFaces 5.x
如果你的primefaces-spring-boot-starter没指定版本,Maven可能会拉取不兼容的版本,直接导致类加载异常,所以一定要明确写对版本号。
4. 清掉WildFly的缓存,避免旧残留
WildFly的缓存有时候会存着旧的类文件,就算你改了代码也没用,必须清干净:
- 先停掉WildFly服务
- 删除
wildfly安装目录/standalone/data/content下的所有内容 - 删除
wildfly安装目录/standalone/tmp下的所有内容 - 重新打包部署试试
5. 检查Spring Boot的WAR包配置
确保你的项目是正确的WAR包格式:
- 在
pom.xml里设置<packaging>war</packaging> - 主类要继承
SpringBootServletInitializer,这样才能在Java EE容器里正常启动:
@SpringBootApplication public class YourAppApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(YourAppApplication.class); } public static void main(String[] args) { SpringApplication.run(YourAppApplication.class, args); } }
最后验证一下
改完这些之后,先执行mvn clean package清理打包,然后用mvn wildfly:deploy部署,或者手动把WAR包扔到WildFly的deployments目录,启动WildFly看看日志——应该就不会再出现那个烦人的MalformedParameterizedTypeException了。
内容的提问来源于stack exchange,提问作者Rachel

