迁移至Jakarta 9+JSF3后,模块化应用无法加载外部Jar中XHTML页面
解决方案:Jar中JSF资源/组件无法加载(Jakarta EE迁移)
1. 彻底替换Jar内配置文件的命名空间
检查Jar里的faces-config.xml、web-fragment.xml甚至taglib.xml,确保所有javax.*命名空间全替换为jakarta.*:
faces-config.xml需改为JSF 3的Jakarta规范:
<faces-config xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-facesconfig_3_0.xsd" version="3.0">
web-fragment.xml对应Jakarta EE 9版本:
<web-fragment xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-fragment_5_0.xsd" version="5.0">
注意:任何一个配置文件遗漏替换,都会导致JSF容器无法识别Jar内的资源和组件。
2. 修正Spring资源处理配置
确保Spring的资源处理器正确映射Jar中META-INF/resources下的内容:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**") .addResourceLocations("classpath:/META-INF/resources/") .setCachePeriod(0); } }
如果是传统Spring MVC,还要确认DispatcherServlet的映射不拦截*.xhtml请求——让FacesServlet专门处理JSF页面。
3. 验证复合组件的Taglib定义
针对<baseUtil:outputTextTruncate>这类组件,检查Jar内META-INF下的taglib.xml:
- 替换命名空间为Jakarta规范,且页面中引用的命名空间URI必须和文件内的一致:
<taglib xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-jsf-taglib_3_0.xsd" version="3.0"> <namespace>http://your-domain/baseUtil</namespace> <!-- 和页面xmlns:baseUtil的URI完全匹配 --> <tag> <name>outputTextTruncate</name> <component> <component-type>com.yourpackage.OutputTextTruncate</component-type> <renderer-type>com.yourpackage.OutputTextTruncateRenderer</renderer-type> </component> </tag> </taglib>
4. 确认Jar的编译与依赖正确性
- 重新编译外部Jar:把所有
javax.faces.*、javax.servlet.*依赖替换为jakarta.faces.*、jakarta.servlet.*,旧的javax编译的Jar在Jakarta环境下会出现类加载冲突。 - 确保Jar被正确引入:WAR包中要放到
WEB-INF/lib,Spring Boot项目依赖范围设为compile或runtime,不要用provided。
5. 排查Tomcat与JSF版本冲突
Tomcat 10.x自带的JSF实现(MyFaces或Mojarra)要和项目依赖的JSF 3版本一致:
- 如果用Mojarra,直接引入兼容依赖:
<dependency> <groupId>org.glassfish</groupId> <artifactId>jakarta.faces</artifactId> <version>3.0.10</version> </dependency>
- 检查
web.xml中FacesServlet的类路径是否改为Jakarta版本:
<servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping>
6. 类加载日志排查
开启Tomcat类加载日志,确认Jar内的配置文件是否被扫描:
在conf/logging.properties中添加:
org.apache.catalina.loader.WebappClassLoader.level = FINE org.apache.catalina.loader.WebappClassLoader.useParentHandlers = false
启动后查看日志,验证faces-config.xml、taglib.xml是否被JSF容器识别。
内容的提问来源于stack exchange,提问作者iljkr
相关产品推荐
相关产品推荐

