liferay7.0开发的二三坑

摘要:
参考资源:https://blog.csdn.net/u012551585/article/details/62261352?locationNum=7&fps=1liferay7.0的官方文档不稳定,已更新和改进。例如,当Liferay 7.0通过JPM安装BladeCli时,官方网站上的[ZipFile.open]errorinopingzipfile文章已经更新。没有这样的问题。我希望新版本能尽快稳定

参考:https://blog.csdn.net/u012551585/article/details/62261352?locationNum=7&fps=1

liferay7.0的官方文档并不稳定,一直在更新完善,比如Liferay7.0 通过JPM安装Blade Cli 时[ZipFile.open] error in opening zip file 这篇,现在官网已经更新,没有这个问题了,希望新版本早日稳定,以下是我开发时遇到的一些问题:

 

问题一:Portlet页面中使用AJAX请求Portlet控制类中serveResource时,resourceRequest得到的AJAX请求参数为NULL ?

问题二:Liferay不同页面拥有不同theme时,切换页面时,上一个页面的theme会Cache下来

问题三:Liferay自定义字段操作

问题四:Liferay自定义JSON服务接口

问题五:在Liferay API基础上自定义 数据库查询

问题六:Liferay用户具有哪些状态,比如停用、激活等

问题七:Liferay添加用户时,用户screenname不允许为全数字

问题八: Liferay自定义登录

问题九:Liferay自定义ERROR404页面

问题十:Blade安装问题,官网提供的blade依赖的Java Package Manager 地址无法访问(截止2017.4.20日)

问题十一:Liferay 自动登录

问题十二:MVCPortlet中得到所在页面的请求参数

问题十三:Liferay7.0中任务调度定时任务

问题十四:Liferay7.0中上下文提供者

 

问题一:Portlet页面中使用AJAX请求Portlet控制类中serveResource时,resourceRequest得到的AJAX请求参数为NULL ?

       这个问题主要是LIferay默认情况下要求为参数加上namespace才行,这个有点坑,表单那块如果使用aui是没有这个问题的,如果使用原生表单项的话,也会遇到相同的问题,后台接收不到传的参数;所以只需为我们的请求项加上namespace就行了:

  1.  
    $.post('<%=resourceURL%>',
  2.  
    {"<portlet:namespace />action":"role",
  3.  
    "<portlet:namespace />plid":plidPageId,
  4.  
    "<portlet:namespace />roleId":roleId
  5.  
    },
  6.  
    function(data){
  7.  
    });

问题二:Liferay不同页面拥有不同theme时,切换页面时,上一个页面的theme会Cache下来

         这个问题主要它的缓存机制有关,liferay提供了相关的Cache禁用配置,在portal-ext.properties添加以下配置:

  1.  
    #禁止缓存
  2.  
    theme.css.fast.load=false
  3.  
    theme.css.fast.load.check.request.parameter=true
  4.  
    theme.images.fast.load=false
  5.  
    theme.images.fast.load.check.request.parameter=true
  6.  
     
  7.  
    javascript.fast.load=false
  8.  
    javascript.log.enabled=false
  9.  
     
  10.  
    layout.template.cache.enabled=false
  11.  
     
  12.  
    browser.launcher.url=
  13.  
     
  14.  
    combo.check.timestamp=true
  15.  
     
  16.  
    freemarker.engine.cache.storage=soft:1
  17.  
    freemarker.engine.resource.modification.check.interval=0
  18.  
     
  19.  
    minifier.enabled=false
  20.  
     
  21.  
    openoffice.cache.enabled=false
  22.  
     
  23.  
    velocity.engine.resource.modification.check.interval=0
  24.  
     
  25.  
    com.liferay.portal.servlet.filters.cache.CacheFilter=false
  26.  
    com.liferay.portal.servlet.filters.etag.ETagFilter=false
  27.  
    com.liferay.portal.servlet.filters.header.HeaderFilter=false

     

         portal-ext.properties配置相关的属性值,在https://docs.liferay.com/ce/portal/7.0-latest/propertiesdoc/portal.properties.html可以查看全部的配置信息

问题三:Liferay自定义字段操作

         某些情况下,Liferay自定义的数据库字段并不能满足要求,Liferay允许在已有字段的基础上添加自定义字段,Liferay后台提供了添加自定义字段的界面操作(控制面板>配置>自定义字段),自定义字段的数据存储结构和wordpress自定义的存储字段一样,并没有在修改原有表,而是都存储在expando开头的数据表中,https://docs.liferay.com/portal/7.0/javadocs/portal-kernel/com/liferay/expando/kernel/service/package-frame.html提供了相关的API,下面是一个取自定义值得例子:

  1.  
    long companyId=PortalUtil.getCompanyId(renderRequest);
  2.  
    try {
  3.  
    long testUserId=UserLocalServiceUtil.getUserByScreenName(companyId, "test").getPrimaryKey();
  4.  
    System.out.println(testUserId);
  5.  
    String testvalue=ExpandoValueLocalServiceUtil.getData(companyId, User.class.getName(),
  6.  
    "CUSTOM_FIELDS", "customword",
  7.  
    testUserId, "test");
  8.  
    System.out.println(testvalue);
  9.  
    renderRequest.setAttribute("customword", testvalue);
  10.  
    } catch (PortalException e) {
  11.  
    // TODO Auto-generated catch block
  12.  
    e.printStackTrace();
  13.  
    }

问题四:Liferay自定义JSON服务接口

        Liferay提供了两种工具新建Service模块,Eclipse 和Blade 方式创建,需要注意的就是创建以后远程的调用路径问题,可以参考官网给出的实例

   liferay7.0开发的二三坑第1张    

    另外,Liferay支持修改官网提供的接口,通过http://localhost:8080/api/jsons查看Liferay提供的原有接口,可参照官网https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/customizing-liferay-services-service-wrappers覆盖原有借口,但要注意此模块只能覆盖原接口,不能新建接口,新建接口还需要使用上述方法。

问题五:在Liferay API基础上自定义 数据库查询

             Liferay API提供了大量的操作,但某些情况下它提供的不是太灵活,需要我们自定义,API提供了这方面的支持,例如:

 

  1.  
    DynamicQuery guestbookQuery = DynamicQueryFactoryUtil.forClass(Guestbook.class)
  2.  
    .add(RestrictionsFactoryUtil.eq("name", guestbookName))
  3.  
    .setProjection(ProjectionFactoryUtil.property("guestbookId"));
  4.  
     
  5.  
    Order order = OrderFactoryUtil.desc("modifiedDate");
  6.  
     
  7.  
    DynamicQuery entryQuery = DynamicQueryFactoryUtil.forClass(Entry.class)
  8.  
    .add(RestrictionsFactoryUtil.eq("name", entryName))
  9.  
    .add(PropertyFactoryUtil.forName("guestbookId").in(guestbookQuery))
  10.  
    .addOrder(order);
  11.  
     
  12.  
    List<Event> entries = EventLocalServiceUtil.dynamicQuery(entryQuery);

问题六:Liferay用户具有哪些状态,比如停用、激活等

           

  1.  
    public static final int STATUS_ANY = -1;
  2.  
    public static final int STATUS_APPROVED = 0;
  3.  
    public static final int STATUS_DENIED = 4;
  4.  
    public static final int STATUS_DRAFT = 2;
  5.  
    public static final int STATUS_DRAFT_FROM_APPROVED = 9;
  6.  
    public static final int STATUS_EXPIRED = 3;
  7.  
    public static final int STATUS_INACTIVE = 5;
  8.  
    public static final int STATUS_INCOMPLETE = 6;
  9.  
    public static final int STATUS_PENDING = 1;
  10.  
    public static final int STATUS_SCHEDULED = 7;

          可以去http://note.youdao.com/noteshare?id=0018de9bef6459ea3aab2c6f8f07d4ec查看用户所用状态。

问题七:Liferay添加用户时,用户screenname不允许为全数字

         当我们自定义注册时,会发现liferay默认情况下screenname字段不允许为全数字:

 

  1.  
    //添加用户
  2.  
    try {
  3.  
    User u=UserLocalServiceUtil.addUserWithWorkflow(currentuserId, companyId, false, password, password,
  4.  
    false, screenname, email, 0L,
  5.  
    phone, new Locale("zh_CN"), username, username,
  6.  
    username, 0L, 0L, "男".equals(sex)?true:false,
  7.  
    month, day, year, message,
  8.  
    null, null, roles, null,
  9.  
    false, ServiceContextFactory.getInstance(resourceRequest));
  10.  
    UserLocalServiceUtil.updateStatus(u.getUserId(), WorkflowConstants.STATUS_INACTIVE,ServiceContextFactory.getInstance(resourceRequest));
  11.  
    } catch (PortalException e) {
  12.  
     
  13.  
    e.printStackTrace();
  14.  
    }


        查看数据库可知该字段为varchar,应该支持全数字,查看配置文件,果然是可配置项:

 

  1.  
    users.screen.name.allow.numeric=true
  2.  
     

问题八: Liferay自定义登录

          Liferay默认提供了三种登录方式:

 

  1.  
    public static final String AUTH_TYPE_EA = "emailAddress";
  2.  
     
  3.  
    public static final String AUTH_TYPE_ID = "userId";
  4.  
     
  5.  
    public static final String AUTH_TYPE_SN = "screenName";

       

        自定义登录代码示例http://download.csdn.net/detail/u012551585/9825444

        自定义好登录页面后怎样替换默认的登录页面呢,需要在添加配置项:

 

  1.  
    #登录页面
  2.  
    auth.login.url=/zh_CN/web/guest/customlogin
  3.  
     

问题九:Liferay自定义ERROR404页面

       Liferay在报错或者找不到路径时,全部跳转到原有的error页面 bundles/tomcat-8.0.32/webapps/ROOT/errors/code.jsp。项目中需要自定404页面:

      首先,在bundles/tomcat-8.0.32/webapps/ROOT/errors/ 文件夹中创建自定义的404.jsp页面(如果想在该页面中显示一些系统信息,可以参照code.jsp的写法);然后在配置文件中配置该404页面:

 

  1.  
    layout.show.http.status=true
  2.  
    layout.friendly.url.page.not.found=/errors/404.jsp
  3.  
     


问题十:Blade安装问题,官网提供的blade依赖的Java Package Manager 地址无法访问(截止2017.4.20日),这个估计官网后续会更新,下面给出一个解决方案:

         Linux下直接运行下面命令:

  1.  
    curl -sL https://github.com/jpm4j/jpm4j.installers/raw/master/dist/biz.aQute.jpm.run.jar > tmp.jar &&
  2.  
    JPM_BIN_DIR=`java -jar tmp.jar -g init | grep -e "Bin[ ]*dir" | awk '{print $3}'` &&
  3.  
    rm -f tmp.jar &&
  4.  
    ${JPM_BIN_DIR}/jpm install -f https://releases.liferay.com/tools/blade-cli/latest/blade.jar &&
  5.  
    echo "blade installed successfully into ${JPM_BIN_DIR}/blade"
  6.  
     

        Windows下:

      https://github.com/jpm4j/jpm4j.installers/blob/master/dist/jpm-setup.exe

问题十一:Liferay 自动登录

         某些访问写略下,我们可能会要求liferay自动登录,官方教程:https://dev.liferay.com/zh/develop/tutorials/-/knowledge_base/7-0/auto-login

         首先,在任意一个module project中新建一个class继承AutoLogin,最主要的就是实现它的login方法的返回值,要求是一个String数组,数组的第一个值为你要登录的用户ID,第二个值为密码,第三个值为密码是否加密("true"或"false"),代码示例如下:

 

  1.  
    package com.zonebase.liferaylogin.portlet;
  2.  
     
  3.  
    import javax.servlet.http.HttpServletRequest;
  4.  
    import javax.servlet.http.HttpServletResponse;
  5.  
     
  6.  
    import org.osgi.service.component.annotations.Component;
  7.  
     
  8.  
    import com.liferay.portal.kernel.model.User;
  9.  
    import com.liferay.portal.kernel.security.auto.login.AutoLogin;
  10.  
    import com.liferay.portal.kernel.security.auto.login.AutoLoginException;
  11.  
    import com.liferay.portal.kernel.service.UserLocalServiceUtil;
  12.  
     
  13.  
    @Component(immediate = true)
  14.  
    public class CustomAutoLogin implements AutoLogin{
  15.  
    //该方法可以不管返回null
  16.  
    @Override
  17.  
    public String[] handleException(HttpServletRequest request, HttpServletResponse response, Exception e)
  18.  
    throws AutoLoginException {
  19.  
    // TODO Auto-generated method stub
  20.  
    return null;
  21.  
    }
  22.  
    //主要是该方法的返回值
  23.  
    @Override
  24.  
    public String[] login(HttpServletRequest request, HttpServletResponse response) throws AutoLoginException {
  25.  
    //默认登录之后跳转到主页面,也可以通过该属性进行设置
  26.  
    request.setAttribute("AutoLogin.AUTO_LOGIN_REDIRECT", "/show1");
  27.  
     
  28.  
    String userId=request.getParameter("userId");
  29.  
    if(userId!=null&&userId!=""){
  30.  
    User user=UserLocalServiceUtil.fetchUser(Long.parseLong(userId));
  31.  
    return new String[] { userId,user.getPassword(),String.valueOf(user.getPasswordEncrypted())};
  32.  
    }
  33.  
    return null;
  34.  
    }
  35.  
    }


            接下来,重要的是在配置文件中配置该自动登录的地址:

 

  1.  
    auto.login.hooks=com.zonebase.liferaylogin.portlet.CustomAutoLogin
  2.  
     


问题十二:MVCPortlet中得到所在页面的请求参数

        某些情况下,在portlet中可能要得到该请求页面的请求参数,只需获得HttpServletRequest,代码如下:

 

  1.  
    public class HomepagePortlet extends MVCPortlet {
  2.  
    @Override
  3.  
    public void doView(RenderRequest renderRequest, RenderResponse renderResponse)
  4.  
    throws IOException, PortletException {
  5.  
    HttpServletRequest request = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(renderRequest));
  6.  
    HttpServletResponse response=PortalUtil.getHttpServletResponse(renderResponse);
  7.  
    String test=request.getParameter("test");
  8.  
    .....
  9.  
    .....
  10.  
    }
  11.  
    }
  12.  
     

问题十三:Liferay7.0中任务调度定时任务

  1.  
    package test.scheduler.portlet;
  2.  
    import org.osgi.service.component.annotations.Activate;
  3.  
    import org.osgi.service.component.annotations.Component;
  4.  
    import org.osgi.service.component.annotations.Deactivate;
  5.  
    import org.osgi.service.component.annotations.Modified;
  6.  
    import org.osgi.service.component.annotations.Reference;
  7.  
     
  8.  
    import com.liferay.portal.kernel.messaging.BaseSchedulerEntryMessageListener;
  9.  
    import com.liferay.portal.kernel.messaging.DestinationNames;
  10.  
    import com.liferay.portal.kernel.messaging.Message;
  11.  
    import com.liferay.portal.kernel.module.framework.ModuleServiceLifecycle;
  12.  
    import com.liferay.portal.kernel.scheduler.SchedulerEngineHelper;
  13.  
    import com.liferay.portal.kernel.scheduler.TimeUnit;
  14.  
    import com.liferay.portal.kernel.scheduler.TriggerFactory;
  15.  
    import com.liferay.portal.kernel.scheduler.TriggerFactoryUtil;
  16.  
    /**
  17.  
    * 任务调度DEMO
  18.  
    * @author zonebase@163.com
  19.  
    */
  20.  
    @Component(immediate = true, service = TestSchedulerEntryMessageListener.class)
  21.  
    public class TestSchedulerEntryMessageListener extends BaseSchedulerEntryMessageListener {
  22.  
    @Reference(target = ModuleServiceLifecycle.PORTAL_INITIALIZED, unbind = "-")
  23.  
    private volatile ModuleServiceLifecycle _moduleServiceLifecycle;
  24.  
    @Reference(unbind = "-")
  25.  
    private volatile SchedulerEngineHelper _schedulerEngineHelper;
  26.  
    @Reference(unbind = "-")
  27.  
    private volatile TriggerFactory _triggerFactory;
  28.  
    @Activate
  29.  
    @Modified
  30.  
    protected void activate() {
  31.  
    //触发器 定义
  32.  
    schedulerEntryImpl.setTrigger(
  33.  
    TriggerFactoryUtil.createTrigger(
  34.  
    getEventListenerClass(), getEventListenerClass(), 60,
  35.  
    TimeUnit.MINUTE));
  36.  
    _schedulerEngineHelper.register(
  37.  
    this, schedulerEntryImpl, DestinationNames.SCHEDULER_DISPATCH);
  38.  
    }
  39.  
     
  40.  
    @Deactivate
  41.  
    protected void deactivate() {
  42.  
    _schedulerEngineHelper.unregister(this);
  43.  
    }
  44.  
    @Override
  45.  
    protected void doReceive(Message message) throws Exception {
  46.  
    //任务
  47.  
    System.out.println("轮训执行。。。。。。。。。。。。");
  48.  
    }
  49.  
     
  50.  
    }
  51.  
     


问题十四:上下文提供者

       某些情况下,我们需要自定义一些像themeDisplay 的上下文对象来储存信息,相关的文档请看https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/context-contributors

   示例如下:

  1.  
    package com.zonebase.testcontext.context.contributor;
  2.  
     
  3.  
    import com.liferay.portal.kernel.template.TemplateContextContributor;
  4.  
     
  5.  
    import java.util.Map;
  6.  
     
  7.  
    import javax.servlet.http.HttpServletRequest;
  8.  
     
  9.  
    import org.osgi.service.component.annotations.Component;
  10.  
     
  11.  
    /**
  12.  
    * 上下文提供者DEMO
  13.  
    * @author zonebase@163.com
  14.  
    */
  15.  
    @Component(
  16.  
    immediate = true,
  17.  
    property = {"type=" + TemplateContextContributor.TYPE_THEME},
  18.  
    service = TemplateContextContributor.class
  19.  
    )
  20.  
    public class TestContextContributorTemplateContextContributor
  21.  
    implements TemplateContextContributor {
  22.  
     
  23.  
    @Override
  24.  
    public void prepare(
  25.  
    Map<String, Object> contextObjects, HttpServletRequest request) {
  26.  
    contextObjects.put("customObject", "Hello World.");
  27.  
    }
  28.  
     
  29.  
    }

文末彩蛋:Liferay7.0官方实例库https://github.com/liferay/liferay-blade-samples/tree/master/maven

免责声明:文章转载自《liferay7.0开发的二三坑》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇laravel框架——验证码(第一种方法)使用js的webrtc进行sip协议连接,实现webrtc与电话网打通下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

前端http请求和常见的几个请求技术做具体的讲解

对于前端来说,请求是前端日常工作必备的,通过请求才能与后端进行数据交互,尤其在现在前后端分离的开发模式下,请求显得就更加重要。因此,对于前端开发者来说,掌握请求就很重要。下面将从http请求和常见的几个请求技术做具体的讲解 一、XMLHttpRequest         XMLHttpRequest一开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效...

Ajax跨域CORS

在Ajax2.0中多了CORS允许我们跨域,但是其中有着几种的限制:Origin、Methods、Headers、Credentials 1.Origin 当浏览器用Ajax跨域请求的时候,会带上一个请求头“Origin: 协议://页面域名”,而服务器需要返回一个响应头“Access-Control-Allow-Origin: 协议://对应域名“,如果...

window.open()打开的新窗口被拦截的原因分析和解决方案

1、原因: 浏览器检测到非用户操作产生的新弹出窗口,则会对其进行阻止。因为浏览器认为这可能是一个广告。 window.open()放在ajax的回调函数中执行会导致被拦截 2、解决方案: 先打开一个页面,在ajax回调函数中把当前页重定向到目标页面 // 打开一个页面 var newWin = window.open('about:blank'); /...

文件上传的几种方式_django

一、form组件形式上传文件 缺点:页面会刷新 后台: 前端:   二、ajax形式上传 能够实现页面不刷新上传 1、原生ajax上传,使用XMLHttpRequest对象来进行上传   流程:     生成XMLHttpRequest对象     对象编写数据open()     开始发送send()     编写对象的回调函数xhr.onreadys...

H5 FormData对象的使用——进行Ajax请求并上传文件

XMLHttpRequest Level2 添加了一个新的接口——FormData。【 主要用于发送表单数据,但也可以独立使用于传输键控数据。与普通的Ajax相比,它能异步上传二进制文件 】 利用FormData对象,可通过js用一些键值对来模拟一系列表单控件,还可以使用XMLHttpRequest的send()方法异步提交表单。 首先,在之前的“前后台交...

ajax和json

一、json 1、 json是什么 它是js提供的一种数据交换格式! 2、json的语法 {}:是对象! 属性名必须使用双引号括起来!单引不行!!! 属性值: null、数值、字符串、 数组:使用[]括起来、boolean值:true和false eg: var person = {"name":"zhangSan", "age":18, "sex":"m...