如何在Liferay 7中重写SearchDisplayContext类并添加自定义方法
在Liferay 7 DXP中为portal-search-web的SearchDisplayContext添加自定义方法的解决方案
直接修改Liferay自带的SearchDisplayContext类肯定不可行——一来内部包的类不允许直接修改,二来升级Liferay时你的修改会被覆盖。我们可以通过OSGi组件替换/继承的方式来扩展这个类,下面是具体步骤:
1. 准备自定义模块
首先创建一个Liferay OSGi模块,在模块的构建配置中添加对portal-search-web的依赖:
- 如果用Gradle,在
build.gradle中加入:dependencies { compileOnly group: "com.liferay", name: "com.liferay.portal.search.web", version: "对应你的Liferay版本号" } - 在
bnd.bnd中确保导入所需的内部包:Import-Package: com.liferay.portal.search.web.internal.display.context,*
2. 创建自定义的SearchDisplayContext类
我们通过继承原类并注册为更高优先级的OSGi组件,来替换原有类。这样既可以重用原有逻辑,又能添加自定义方法:
import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.util.WebKeys; import com.liferay.portal.search.web.internal.display.context.SearchDisplayContext; import com.liferay.portal.search.web.portlet.preferences.SearchPortletPreferences; import com.liferay.portal.search.web.search.request.SearchRequestBuilder; import com.liferay.portal.search.web.search.response.SearchResponse; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; import org.osgi.service.component.annotations.Component; @Component( immediate = true, property = { "request.scoped=true", "service.ranking:Integer=100" // 设置更高优先级,确保优先加载我们的类 }, service = SearchDisplayContext.class ) public class CustomSearchDisplayContext extends SearchDisplayContext { // 注入父类构造函数所需的所有依赖 @Inject public CustomSearchDisplayContext( com.liferay.portal.kernel.portlet.Portal portal, ThemeDisplay themeDisplay, HttpServletRequest httpServletRequest, SearchPortletPreferences searchPortletPreferences, SearchRequestBuilder searchRequestBuilder, SearchResponse searchResponse, WebKeys webKeys) { super(portal, themeDisplay, httpServletRequest, searchPortletPreferences, searchRequestBuilder, searchResponse, webKeys); } // 这里添加你的自定义方法 public String getCustomSearchSummary() { // 可以直接调用父类的方法获取原有数据,比如搜索结果总数 long totalHits = getSearchResponse().getTotalHits(); return String.format("本次搜索共找到 %d 条结果", totalHits); } // 如果你需要修改原有方法的逻辑,也可以重写父类方法 @Override public boolean isShowEmptyResultsMessage() { // 比如自定义空结果时的显示逻辑 return super.isShowEmptyResultsMessage(); } }
3. 部署并测试
- 将模块打包成JAR文件,部署到Liferay的
osgi/modules目录下,Liferay会自动加载这个新的组件。 - 在搜索页面的JSP(比如
search_results.jsp)中调用自定义方法:<% CustomSearchDisplayContext searchDisplayContext = (CustomSearchDisplayContext)request.getAttribute(SearchDisplayContext.class.getName()); %> <div class="custom-search-summary"> <%= searchDisplayContext.getCustomSearchSummary() %> </div>
注意事项
- 由于原类属于
internal包,Liferay升级时可能会修改其构造函数或方法签名,升级后需要检查并同步你的自定义类。 - 如果你不想继承原类,也可以使用OSGi装饰器模式包装原有组件,但这种方式需要实现原类的所有方法,相对繁琐,适合不需要重用大量原有逻辑的场景。
内容的提问来源于stack exchange,提问作者Pankaj Sharma
相关产品推荐
相关产品推荐

