Liferay 7.0 Portlet重启后无法正常部署问题求助
从你描述的现象和报错信息来看,核心问题是Liferay重启自动部署后,两个Spring MVC Portlet的DispatcherPortlet找不到请求处理器(Handler),而热部署时正常。结合依赖差异和报错堆栈,我们可以从以下角度排查:
一、报错本质:Spring上下文未正确初始化或Handler未注册
你看到的NoHandlerFoundException是表象,真正的原因大概率是重启时Spring Portlet的应用上下文没有成功完成初始化——可能是类加载冲突、Bean创建失败,导致Controller等Handler组件没有被注册到DispatcherPortlet中。热部署时类加载器的优先级和重启时不同,暂时规避了冲突,但重启后容器类加载器优先加载,问题就暴露了。
二、重点怀疑的依赖问题
对比三个Portlet的依赖,失效的两个多引入了以下依赖,其中几个点需要重点关注:
1. com.liferay.util.taglib 使用 compile 范围
Liferay本身已经内置了这个标签库,如果你用compile范围,会把它打包到Portlet的WAR包中。重启时,容器类加载器和Portlet私有类加载器会加载同一类的不同版本,引发类加载冲突——可能导致Spring在扫描组件、创建Bean时抛出隐藏异常(你没在启动日志里看到,但会导致Handler无法注册)。
2. 其他provided范围依赖的版本匹配问题
javax.servlet.jsp-api、org.glassfish.web.jstl-impl:虽然是provided范围,但要确保你指定的版本和Liferay内置的版本一致。如果版本不匹配,可能导致Spring视图解析相关类加载失败,间接影响Handler映射的注册。oracle.ojdbc6:如果Liferay已经配置了全局的JDBC驱动,重复引入可能导致驱动类加载冲突,进而影响依赖该驱动的Bean创建。
3. 额外引入的hibernate-core、jackson-mapper-asl
这两个库如果是compile范围,会被打包到WAR中。如果Liferay内置了不同版本的Hibernate或Jackson,同样会引发类加载冲突,导致Spring上下文初始化失败。
三、具体排查与修复步骤
1. 调整依赖范围,避免类重复加载
- 将
com.liferay.util.taglib的scope改为provided,让Portlet直接使用Liferay内置的版本,不要打包到WAR中:<dependency> <groupId>com.liferay.portal</groupId> <artifactId>com.liferay.util.taglib</artifactId> <version>2.8.0</version> <scope>provided</scope> </dependency> - 检查
hibernate-core、jackson-mapper-asl是否必须由Portlet提供,如果Liferay已经内置兼容版本,也改为provided范围。
2. 查看启动时的隐藏异常
重启Liferay时,重点查看以下日志:
- Portlet部署时的Spring上下文初始化日志(搜索
ApplicationContext、BeanCreationException等关键词) - Liferay的OSGi容器日志(查看Portlet对应的Bundle是否成功激活,有没有启动失败的提示)
这些日志会告诉你Spring上下文初始化时是否有异常,这才是NoHandlerFoundException的根源。
3. 检查类加载冲突
- 使用Liferay的Gogo Shell执行
bundle:diag [你的Portlet Bundle ID],查看是否有类加载冲突的诊断信息。 - 解压失效Portlet的WAR包,检查
WEB-INF/lib目录,确保没有Liferay已经内置的JAR包(比如liferay-util-taglib.jar、jsp-api.jar等)。
4. 验证Spring配置的一致性
虽然你说配置文件一致,但仍需确认:
portlet-application-context.xml中的组件扫描路径是否正确(比如<context:component-scan base-package="xxx.controller"/>),有没有拼写错误。spring/application-context.xml中是否有Bean定义错误,导致容器初始化失败。
5. 检查OSGi Bundle配置
确保liferay-plugin-package.properties中的bundle-symbolic-name是唯一的,三个Portlet不能重复;同时检查required-deployment-contexts等配置是否正确,避免Bundle依赖缺失导致启动失败。
总结
最可能的原因是com.liferay.util.taglib的compile范围引发类加载冲突,导致Spring上下文初始化失败。先调整这个依赖的范围,再通过启动日志排查具体的异常,逐步解决问题。
内容的提问来源于stack exchange,提问作者Jamie

