Liferay 6.1开发学习(十八):Liferay开发过程中的一些常见问题
记录一些个人在Liferay的开发中遇到的一些常见问题与处理技巧,持续更新ing
Build namespace xx build number xxx which is newer than xx
此错误常出现在部署工程的时候,错误的意思是说当前工程的build number比服务器上已经部署的小。那这个有什么影响呢?我们做ServiceBuilder的时候,知道Liferay会自动的更新服务端的数据库信息等,Liferay判断需要不需要更新就是通过这个build number来进行判断的。如果我们要修复很明显有两种方法,一种是修改插件工程,一种是修改Liferay的数据库。
方法一:修改插件工程中的build number
在插件工程的src下面找到service.properties,打开找到里面的build.number,将之修改的比服务端上的build number大,然后重新部署即可。
方法二:修改Liferay的数据库。
打开数据库里面的servicecomponent表,在里面找到相应的build numer,将之修改的比插件工程里面的小。修改完数据库要保证修改的数据库有效,需要我们在控制面板--服务器管理 执行一下清除数据库缓存。然后重新部署工程。
如何避免此问题出现
此问题的出现,一般是有多人参与的项目里面,使用版本控制工具来维护代码,有人提交了,有人没有提交,要想保持一致,让大家都及时的提交service.properties文件,并且如果有冲突的话就选择build number最大的为准。
No Liferay Plugin SDK configured on project xxx
一般此问题出现在将工程导入到Eclipse中时,问题的原因是SDK的位置不正确,有可能有两个原因:
可能1:在eclipse里面没有配置SDK
可能2:工程不是在SDK的相应目录下面,比如xxx-portlet,要将此工程放到SDK/portlets目录下面,xxx-theme放到SDK/theme目录下面,就是不同的工程放到对应的目录下面
怎么获取HttpServletRequest
在一些特殊情况下,我们希望在portlet中使用原生的httpServletRequest,可以使用下面的代码获取,下面分别是renderRequest和actionRequest,可以将renderRequest和actionRequest转换为HttpServletRequest
HttpServletRequest request = PortalUtil.getHttpServletRequest(renderRequest);
HttpServletRequest request = PortalUtil.getHttpServletRequest(actionRequest);
怎么获取UserId,groupId,companyId
Liferay中的二级开发,在设计表的时候强烈建议为每一个表添加groupId和companyId,这样我们的系统就可以在不同的站点、company下面独立使用。获取这些参数的代码如下:
Long companyId = PortalUtil.getCompanyId(renderRequest);
Long groupId = PortalUtil.getScopeGroupId(renderRequest);
long userId = PortalUtil.getUserId(request);
如果是获取User可以直接使用下面的:
User user = PortalUtil.getUser(request);
通过这个方法可以获取到用户信息,得到user之后就可以获取用户的其他信息,如用户名称、emailaddress、性别等等
Liferay中怎么获取当前页面/导航的名称
Liferay中的导航其实就是一个个的页面,这个页面对应于Liferay中的Layout这个实体,其实要获取页面/导航的信息,只需要获取到Layout即可。
layout在Jsp中通过下面的两种方法获取
Layout layout = (Layout) request.getAttribute(WebKeys.LAYOUT);
或者是添加以下的标签:
<%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %>
<liferay-theme:defineObjects />
有了上面的这两个标签,即可直接使用layout
layout.getName就是页面/导航的名称,通过这个还可以获取父页面的信息,子页面的信息等。
表单提交参数的获取
Liferay对于从Request里面获取提交参数进行了一个简单的封装,提供了不少便利。
ParamUtil是对参数获取的一个封装,可以方便的对获取到的参数赋予默认值,类型转换等。Request支持servletRequest和PortletRequest、ActionRequest。下面是一些常用的方法,其他还有一些date了使用方法类型
获取字符串
String title = ParamUtil.getString(request, "title","liferay");
这个代码等同于
String title = request.getParameter("title"); if(title==null){ title = "liferay"; }
第三个参数如果为空,则当title为空的时候赋予“”,也就是一个空的字符串。
对于long,date,int等还提供了内置的转换。
获取数字
ParamUtil.getInteger(ServletRequest req,String param)
ParamUtil.getInteger(ServletRequest req,String param,int defaultVlue)
如果没有指定默认值,则默认值为“0”。
ParamUtil.getDouble(ServletRequest req,String param)
ParamUtil.getDouble(ServletRequest req,String param,double defaultVlue)
如果没有指定默认值,则默认值为0.0。
getFloat、getShort、getLong类似。
获取boolean
ParamUtil.getBoolean(servlet req,String param)
ParamUtil.getBoolean(servlet req,String param,Boolean default)
这个方法对于参数为:“true”,“t”,“y”,“on”,“1”时会转化为true,默认为false;如果是其他的情况不要使用。
Liferay中的类型转换
在开发中常遇到类型的强制转换,比如将String id = "123"中的id,由String类型,转换成long类型,我们通常使用下面的代码。
long idl = Long.valueOf(id);
但这样会有一个问题,会出现一个异常,当转换失败的时候我们需要处理这个异常,或者我们希望转换失败的时候可以赋予一个默认值,这样写起来就会有一点复杂,Liferay封装了一个类型转换类GetterUtil。上面的代码如果使用这个类方法为:
long idl = GetterUtil.getLong(id,1);
这个的意思是说当转换失败的时候,为这个idl赋予默认值 1,如果第二个参数不加,则默认值为0。
GetterUtil里面还有其他常见类型的转换方法,具体的可以自行查阅API
Liferay中的StringUtil工具类
Liferay中的StringUtil类是我最常使用LiferayAPI,他提供了一些常用方法的封装。
如将一个字符串中的数字提取出来:StringUtil.extractDigits(String s)
如将一个集合(List、数组)转换成一个字符串,并使用一定的分割符切分:
方法为:merge(Collection<?> col) 和merge(Collection<?> col, String delimiter)
如果不加第二个参数,默认是以英文逗号切分等。
此类比较简单,看一下API就可以了解具体的使用。
Liferay中的验证工具类
非空检查、判断一个字符串是不是数字、是不是邮件地址、是不是IP地址、是不是URL地址等,都可以使用此工具类Validator。具体的使用方法看API,比较简单,不详述。
Liferay中如何判断当前运行环境的类型
在一些特殊的情况下,我们需要判断当前环境的类型,如是运行在tomcat中还是在weblogic或者是其他的中间件,因为中间件的差异,有些特殊的代码,希望为不同的中间件编写特殊的内容。Liferay封装了一个下面的方法,如果不是在Liferay中使用,有这样需求的,也可以参考一下Liferay的ServerDetector代码。
我们可以使用下面的代码判断。
if(ServerDetector.isTomcat()){//tomcat server …… }else if(ServerDetector.isWebLogic()){//weblogic server …… }
在Portlet的类中LanguageUtil.get(Local,key)取不到
会发现在Portlet的控制类,MVC类中使用LanguageUtil.get(local,key)等获取不到相对应的国际化配置信息,而这样的写法在JSP页面中是可以取到对应的国际化信息的,那么在Portlet类中应该如何取的,可以使用下面的代码:
- PortletConfig portletConfig =(PortletConfig)renderRequest.getAttribute(JavaConstants.JAVAX_PORTLET_CONFIG);
- ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(WebKeys.THEME_DISPLAY);
- System.out.println(LanguageUtil.get(portletConfig,themeDisplay.getLocale(), "key"));
使用这样的代码即可达到在Portlet类中访问国际化信息。
请问专家,如果不使用Spring框架,直接继承Liferay的Portlet类。这种情况如何写这些Portlet实现类的Unit Test呢 ❓
谢谢!
javax.servlet.jsp.JspException: com.liferay.portal.kernel.template.TemplateException: Unable to process template newliferays-theme_SERVLET_CONTEXT_/templates/portal_normal.ftl
最近出现了这么一个问题不知道怎么解决
这个一般是在主题正在部署的时候,访问了页面,重启或稍后访问即可
>javax.servlet.jsp.JspException: com.liferay.portal.kernel.template.TemplateException: Unable to process template newliferays-theme_SERVLET_CONTEXT_/templates/portal_normal.ftl
我也发生了上面的问题。
我只修改了portal_normal.ftl,删除了footer的内容
重启后还是发生同样的问题。
胡神:
我们现在使用的GA5和GA4版本,但是在执行build service的时候,build.auto.upgrade 的值会自动变成true,我们觉得这样很危险,但是耗费了很长时间没有找到解决的办法.
还请胡神点播一下.
新建一个service-ext.properties文件,在这个文件中改为false就可以了
https://dev.liferay.com/zh/develop/tutorials/-/knowledge_base/6-2/configuring-service-properties
按照官网方法也就是service-ext.properties
build.auto.upgrade=false
并不能解决这个问题
这个方法肯定可以的