文档章节

Liferay 6.1开发学习(十六):FriendlyURL的使用

攻城狮不是猫
 攻城狮不是猫
发布于 2015/07/03 09:26
字数 3632
阅读 35
收藏 0

站点的FriendlyURL

Liferay的页面URL一般为/web/xxx/xxx,其中web后面的即为站点的名称,如默认的为guest。站点的FriendlyURL可以在管理-->站点设置-->基本信息-->站点URL-->友好URL里面修改。

使用FriendlyURL好处是可以更清晰的表达语义,默认的是一个数字串,我们可以使用拼音或者英文字母表达这个站点的含义,比如可以使用公司名称等。

站点URL的获取,可以在代码中使用如下的方法:group.getFriendlyURL();

页面的FriendlyURL

页面的FriendlyURL和站点的FriendlyURL的作用差不多。可以通过如下方法进行修改。

管理-->页面-->友好URL,可以在这里输入相应的名称作为FriendlyURL。如下图。

页面URL的获取在代码中可以使用:layout.getFriendlyURL();

使用页面的FriendlyURL的好处个人感觉有两点:

1、如站点FriendlyURL一样,可以清晰的表达语义。

2、可以帮助我们固定页面,在默认中页面的FreindlyURL是一个数字,这个数字的生成是按照页面的添加顺序来的,在实际开发中,有一些页面的地址可能需要写在代码中, 但是在添加页面的时候,由于某些原因可能并不能保证每一个站点的的页面的添加顺序就是一样的,如在A站点中添加的新闻查看的页面可能是1,但是在b站点中页面的地址可能是12,但是他们都是新闻查看,这个时候就可以为这两个页面都将FriendlyURL设置为newsview,通过FreindlyURL来保持地址的一致性。

Portlet的FriendlyURL

portlet的FriendlyURL并不能通过简单的配置来实现,需要编写一些代码来完成。如Liferay的官方网站,有这样的一个地址,http://www.liferay.com/marketplace/-/mp/category/11232560,则这就是一个portletFriendlyURL,这个里面的-后面的即为portletFriendlyURL

Portlet的FriendlyURL可以帮助我们屏蔽一些不必要的URL信息,普通的portlet的信息,则是如下面这样的一个大长串:http://localhost:8080/web/hqw/2?p_auth=b9fBsvH4&p_p_id=cmslinkmanager_WAR_cmsportlet&p_p_lifecycle=1&p_p_state=normal&p_p_mode=view&p_p_col_id=column-1&p_p_col_count=1&_cmslinkmanager_WAR_cmsportlet_jspPage=%2Fhtml%2FCmsLinkManager%2Fview.jsp&_cmslinkmanager_WAR_cmsportlet_javax.portlet.action=viewLink

这样的一长串地址,显然对用户是不太友好的,对于普通的Portlet应用,不关心也无所谓。但在一些特殊的Portlet中,我们需要在在其他地方引用时就不太方便,可以使用FriendlyURL来简化portletURL信息。

首先确定要对哪一个portletURLFreindlyURL,如现在我们有一个新闻的RSS输出的Portlet,需要对不同的新闻栏目进行RSS的输出,我们希望URL的信息尽可能的简短,方便用户订阅。实现的目标如下:

http://xxx/web/hqw/rss/-/rss/ 这个地址为订阅全部栏目的新闻

http://xxx/web/hqw/rss/-/rss/123 这个地址为订阅栏目ID123的新闻,则实现方法如下:

一、首先在Liferay-portlt.xml里面找到此RSS输出的Portlet,在此portlet的配置里面添加如下信息:

<friendly-url-mapper-class>com.liferay.portal.kernel.portlet.DefaultFriendlyURLMapper</friendly-url-mapper-class>
 <friendly-url-mapping>rss</friendly-url-mapping>
 <friendly-url-routes>xx/xx/portlet/cmsarticlerss/cmsrss-friendly-url-routes.xml</friendly-url-routes>

friendly-url-mapper-class:此配置参考上面的即可,不需要自定义。

friendly-url-mapping:为此portlet定义的FriendlyURL,如这里定义为rss,即是http://xxx/web/hqw/rss/-/rss/这里面-后面的rss

friendly-url-routes:portlet的定义规则的xm的路径,这里是包名。

二、编辑第一步中定义的cmsrss-friendly-url-routes.xml文件,xml文件的参考配置信息如下:

<?xml version="1.0"?>
<!DOCTYPE routes PUBLIC "-//Liferay//DTD Friendly URL Routes 6.0.0//EN" "http://www.liferay.com/dtd/liferay-friendly-url-routes_6_0_0.dtd">
<routes>
 <route>
 <pattern></pattern>
 <implicit-parameter name="p_p_id">cmsarticlerssfeed_WAR_Cms_Eipportlet</implicit-parameter>
 <implicit-parameter name="p_p_lifecycle">2</implicit-parameter>
 <implicit-parameter name="p_p_state">normal</implicit-parameter>
 <implicit-parameter name="p_p_mode">view</implicit-parameter>
 <implicit-parameter name="p_p_resource_id">rss</implicit-parameter>
 </route>
 <route>
 <pattern>/{columnId}</pattern>
 <implicit-parameter name="p_p_id">cmsarticlerssfeed_WAR_Cms_Eipportlet</implicit-parameter>
 <implicit-parameter name="p_p_lifecycle">2</implicit-parameter>
 <implicit-parameter name="p_p_state">normal</implicit-parameter>
 <implicit-parameter name="p_p_mode">view</implicit-parameter>
 <implicit-parameter name="p_p_resource_id">rss</implicit-parameter>
 </route>
</routes>

pattern:为主路径,是类似restfull的格式形式,为空的则表示是http://xxx/web/hqw/rss/-/rss/此路径。

implicit-parameter:这个里面的信息是一些固定的参数信息可以看作为静态参数,表示请求此路径的时候在后台默认附带的参数。

/{columnId}:这个表示的动态参数,也就是需要根据此参数的不同的来到后台根据此参数来显示不同的内容。columnId表示这个参数的名称为columnId。当在浏览器请求的URL为:http://xxx/web/hqw/rss/-/rss/123这样的形式的时候,则表示请求的内容为columnId=123

实例Demo

Liferay中左右布局的示例

在博客中的留言中有朋友问在Liferay中怎么实现,左边是导航,右边是具体的portlet内容,点击左边的导航右边的内容变化怎么实现,我理了一下大概有以下几种情况和不同的实现方式。

§ 使用iframe,右边刷新的内容为portlet页面

§ 使用iframe,右边刷新的为普通的JSP页面,而非portlet页面

这两种的实现方式是一样的,无论是portlet页面或者是JSP页面,都是将iframesrc的属性使用JS动态的设置为待刷新的页页的URL

如果为portlet时,portlet页面URL可以如下定义示例:

<portlet:actionURL var="config" name="save" windowState="<%=LiferayWindowState.POP_UP.toString()%>">
 <portlet:param name="jspPage" value="/html/NewsGatherManager/configGather.jsp"/>
</portlet:actionURL>

则设置iframeURL的方法如下(使用JQuery):$('#iframeid').attr('src',url);,其中的urlconfig

如果是IFrame的为普通的jsp页面,则url=${basepath}/html/NewsGatherManager/configGather.jsp,其中的basepath=request.getContextPath();

§ 使用ajax,右边刷新的为普通的JSP页面或html片断

使用ajax的时候,为点击左边导航的时候触发相应的Ajax请求,将返回值的内容填充到相应的元素中。

§ 左右两边为两个不同的portlet,左边为导航,右边为具体的显示内容,通过在URL中传递参数来为右边的portlet刷新不同的内容。

点击左边的导航的时候,重新载入本页面,并动态的修改URL的参数内容。

示例代码下载:点击此处

Liferay中通过URL传参数

Liferay中会常遇到类似文章查看、内容详情等类似的情况。在传统的web开发中我们一般使用类似这样的URL形式/viewarticle?id=232等这样的形式,在Liferay中其实也可以使用这样的形式,最终的效果是这样的:/web/hqw/viewarticle?articleId=322

要实现这样的效果一般是有两个Portlet,一个是内容的列表,一个是内容的查看。(示例说明前提如下:)

1、首先将这两个portlet添加到不同的页面中。

2、将新闻详情查看的portlet所在页面的friendlyUR设置为viewarticle(根据自己的情况修改调整)

3、将内容列表的标题部分的a标签的href属性设置为:/web/hqw/viewarticle?articleId=XXX(这里替换为实际的文章ID)

4、点击上面的文章列表的时候浏览器会将地址跳转到http://xxx/web/hqw/viewarticle?articleId=XXX的页面。这个时候会执行文章详细的portlet中的doView方法。

关键点在这里,在这里只要取到URL中的articleId这个参数,就可以根据这个文章id获取到文章的具体内容,将文章的相关信息放到request里面,再在页面中显示。

取这个URL的参数可以使用如下的两行代码:

HttpServletRequest request = PortalUtil.getHttpServletRequest(renderRequest);
 String articleId = PortalUtil.getOriginalServletRequest(request).getParameter("articleId");

分享一段JS格式化JSON的代码

项目中需要在页面中格式化JSON代码,看到百度上有一个这样的应用,地址:http://app.baidu.com/editjson?keyword=json%E7%BC%96%E8%BE%91%E5%99%A8

里面的格式化JSON代码的功能比较好用,就将里面的关键代码提取了出来,稍作修改,方便在其他地方引用,代码如下:

使用方法,format(json)这样为格式化代码。

format(json,true)为开启压缩模式。

1.     function format(txt,compress/*是否为压缩模式*/){/* 格式化JSON源码(对象转换为JSON文本) */  

2.             var indentChar = '    ';   

3.             if(/^\s*$/.test(txt)){   

4.                 alert('数据为空,无法格式化! ');   

5.                 return;   

6.             }   

7.             try{var data=eval('('+txt+')');}   

8.             catch(e){   

9.                 alert('数据源语法错误,格式化失败错误信息: '+e.description,'err');   

10.              return;   

11.          };   

12.          var draw=[],last=false,This=this,line=compress?'':'\n',nodeCount=0,maxDepth=0;   

13.             

14.          var notify=function(name,value,isLast,indent/*缩进*/,formObj){   

15.              nodeCount++;/*节点计数*/  

16.              for (var i=0,tab='';i<indent;i++ )tab+=indentChar;/* 缩进HTML */  

17.              tab=compress?'':tab;/*压缩模式忽略缩进*/  

18.              maxDepth=++indent;/*缩进递增并记录*/  

19.              if(value&&value.constructor==Array){/*处理数组*/  

20.                  draw.push(tab+(formObj?('"'+name+'":'):'')+'['+line);/*缩进'[' 然后换行*/  

21.                  for (var i=0;i<value.length;i++)   

22.                      notify(i,value[i],i==value.length-1,indent,false);   

23.                  draw.push(tab+']'+(isLast?line:(','+line)));/*缩进']'换行,若非尾元素则添加逗号*/  

24.              }else   if(value&&typeof value=='object'){/*处理对象*/  

25.                      draw.push(tab+(formObj?('"'+name+'":'):'')+'{'+line);/*缩进'{' 然后换行*/  

26.                      var len=0,i=0;   

27.                      for(var key in value)len++;   

28.                      for(var key in value)notify(key,value[key],++i==len,indent,true);   

29.                      draw.push(tab+'}'+(isLast?line:(','+line)));/*缩进'}'换行,若非尾元素则添加逗号*/  

30.                  }else{   

31.                          if(typeof value=='string')value='"'+value+'"';   

32.                          draw.push(tab+(formObj?('"'+name+'":'):'')+value+(isLast?'':',')+line);   

33.                  };   

34.          };   

35.          var isLast=true,indent=0;   

36.          notify('',data,isLast,indent,false);   

37.          return draw.join('');   

38.      }  

文档在线阅读的实现(类百度文库)

Office文档的在线阅读,现在的一般实现思路如下:

1、使用openofficeoffice文档转换成PDF

2、使用swftoolsPDF转换成swf

3、使用flexpaper播放swf文件

最终的效果如下图:

具体实现如下:

office文档转PDF

需要的软件及类库

§ 需要软件openoffice 3.4.1,可以从openoffice官网下载。

§ jodconverter类库,3.0beta4

mvenv的信息如下:其中openoffice.version=3.2.1(3.4.1的类库在maven仓库上没有,所以使用这个版本的)

1.     <dependency>  

2.         <groupId>com.artofsolving</groupId>  

3.         <artifactId>jodconverter-core</artifactId>  

4.         <version>3.0-beta-4</version>  

5.     </dependency>  

6.     <dependency>  

7.               <groupId>org.openoffice</groupId>  

8.               <artifactId>ridl</artifactId>  

9.               <version>${openoffice.version}</version>  

10.        </dependency>  

11.        <dependency>  

12.            <groupId>org.openoffice</groupId>  

13.            <artifactId>juh</artifactId>  

14.            <version>${openoffice.version}</version>  

15.        </dependency>  

16.        <dependency>  

17.            <groupId>org.openoffice</groupId>  

18.            <artifactId>jurt</artifactId>  

19.            <version>${openoffice.version}</version>  

20.        </dependency>  

21.        <dependency>  

22.            <groupId>org.openoffice</groupId>  

23.            <artifactId>unoil</artifactId>  

24.            <version>${openoffice.version}</version>  

25.        </dependency>       

第一步:安装openoffice到操作系统里面

第二步:复制相关的jar包到系统的依赖库里面。具体的jar包见上面的代码。

第三步:编写转换代码,核心代码如下:

1.     /**  

2.          * office文档转换成PDF文档  

3.          * @Date 2012-12-11上午10:01:59   

4.          * @Author huqiwen  

5.          * @param inputFile 文件在磁盘上的物理路径  

6.          * @param pdfFile 目标文件在磁盘上的物理路径  

7.          * @return   

8.          */  

9.         public static File convert2PDF(String inputFile, String pdfFile) {   

10.          if (StringUtils.isEmpty(inputFile)||StringUtils.isEmpty(pdfFile)) {   

11.              return null;   

12.          }   

13.          startService();   

14.          logger.info("进行文档转换转换:" + inputFile + " --> " + pdfFile);      

15.          OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);   

16.          File targerpdfFile = new File(pdfFile);   

17.          converter.convert(new File(inputFile), targerpdfFile);   

18.          stopService();   

19.          return targerpdfFile;   

20.      }   

21.    

22.      public static void startService() {   

23.          DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();   

24.          try {   

25.              configuration.setOfficeHome(openoffice_home);// 设置OpenOffice.org安装目录   

26.              configuration.setTaskExecutionTimeout(1000 * 60 * 5L);// 设置任务执行超时为5分钟   

27.              configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L);// 设置任务队列超时为24小时   

28.    

29.              officeManager = configuration.buildOfficeManager();   

30.              officeManager.start(); // 启动服务   

31.              logger.info("office转换服务启动成功……");   

32.          } catch (Exception ce) {   

33.              logger.info("office转换服务启动失败!详细信息");   

34.          }   

35.      }   

36.    

37.      public static void stopService() {   

38.          logger.info("关闭office转换服务....");   

39.          if (officeManager != null) {   

40.              officeManager.stop();   

41.          }   

42.          logger.info("关闭office转换成功!");   

43.      }  

PDF转SWF

上面的过程是完成了office文档到PDF的转换,要想在flexpaper里面播放,还需要将PDF转换成SWF格式的,SWFTOOS是一个工具可以将pdf、图片等格式的内容转换成SWF格式,这里我们主要使用的PDF转换功能。

swftools的官方网站:http://www.swftools.org/

核心内代码如下:

1.        /**  

2.         * PDF文件转换为SWF的格式,虽然SWFTOOS支持多种格式,但这里主要转换PDF文件  

3.         * @Date 2012-12-11上午11:07:14   

4.         * @Author huqiwen  

5.         * @param sourceFilePath  

6.         * @param swfFilePath  

7.         * @param fileType  

8.         * @return  

9.         * @throws IOException  

10.      */  

11.  public static boolean convertPDFToSwf(String sourceFilePath,String swfFilePath,String fileType){   

12.      if(!swfToolExist()){   

13.          logger.warn("未指定要进行swf转化工具的地址!!!");   

14.          return false;   

15.      }   

16.    

17.         //判读要转换的文件类型是否符合转换为pdf   

18.      if(!Constants.PDF_FILE.equalsIgnoreCase(fileType)){   

19.          logger.warn("当前文件不符合要转化为SWF的文件类型!!!");   

20.          return false;   

21.      }   

22.      File sourceFile=new File(sourceFilePath);   

23.      if(!sourceFile.exists()){   

24.          logger.warn("要进行转换文件不存在!!!");   

25.          return false;   

26.      }   

27.    

28.         //检查flash文件的目录是否存在,不存在则创建   

29.         File swfFile=new File(swfFilePath);   

30.         if (!FileUtil.mkdirs(swfFile)) {   

31.             logger.error("目录创建失败[" + swfFile.getPath() + "]");   

32.             return false;   

33.         }   

34.    

35.      try {   

36.          if(!swftoolsPath.endsWith(File.separator)){   

37.              swftoolsPath+=File.separator;   

38.          }   

39.             

40.          List<String> commandBuidler = new ArrayList<String>();    

41.          //加载系统的字体目录   

42.          String systemFontsDir = properties.getProperty("file.fonts.dir""C:\\WINDOWS\\Fonts");   

43.             

44.          if (StringUtils.isNotEmpty(systemFontsDir) && Constants.PDF_FILE.equals(fileType)) {   

45.              commandBuidler.add(swftoolsPath + fileType+"2swf.exe");   

46.              commandBuidler.add("-F");   

47.              commandBuidler.add(systemFontsDir);   

48.              commandBuidler.add("-f");   

49.              commandBuidler.add(sourceFilePath);   

50.              commandBuidler.add("-o");   

51.              commandBuidler.add(swfFilePath);   

52.              commandBuidler.add("-T 9 ");   

53.              if (sourceFile.length() > 1024*1024*10) { //大于10M加上以下命令   

54.                  commandBuidler.add(" -s poly2bitmap ");   

55.              }   

56.          } else {   

57.              logger.warn("只提供PDF文档的格式转换");   

58.              return false;   

59.          }   

60.          ProcessBuilder processBuilder = new  ProcessBuilder();       

61.          processBuilder.command(commandBuidler);       

62.          Process process = processBuilder.start();          

63.             

64.          AbsInputStreamWathThread inputWathThread = new  InputStreamWathThread(process);       

65.          inputWathThread.start();       

66.          AbsInputStreamWathThread errorInputWathThread = new  ErrorInputStreamWathThread(process);       

67.          errorInputWathThread.start();       

68.                 

69.          process.waitFor();// 等待子进程的结束,子进程就是系统调用文件转换这个新进程   

70.          inputWathThread.setOver(true); // 转换完,停止流的处理   

71.          errorInputWathThread.setOver(true);   

72.      } catch (IOException e) {   

73.          e.printStackTrace();   

74.      } catch (InterruptedException e) {   

75.          e.printStackTrace();   

76.      }   

77.         

78.      return true;   

79.  }  

使用flexpaper播放

flexpaper的官方网站:http://flexpaper.devaldi.com/

从网站上下载免费版本即可,http://flexpaper.devaldi.com/download/

1、在页面中加载flexpaper.jsflexpaper_handlers.js两个JS文件

2、在页面中要显示flexpaper的地方使用以下JS

下面的jsDirectory的目录虽然叫js目录,但这个目录的目的主要是定位FlexPaperViewer.swf的位置的,比如现在jsDirectory : "${basepath}/resources/js/",   ,则将  FlexPaperViewer.swf放在${basepath}/resources/下面

1.     $('#nodeId').FlexPaperViewer(   

2.                     { config:{   

3.                         SWFFile : swfurl,   

4.                         jsDirectory : "${basepath}/resources/js/",   

5.                         Scale : 0.9,   

6.                         ZoomTransition : 'easeOut',   

7.                         ZoomTime : 0.5,   

8.                         FitPageOnLoad : true//加载后适合高度   

9.                         FitWidthOnLoad : true,//加载后适合宽度   

10.                      FullScreenAsMaxWindow : false//是否支持全屏   

11.                      ProgressiveLoading : false,  //是否支持延迟加载   

12.         

13.                      ViewModeToolsVisible : true,   

14.                      ZoomToolsVisible : true,   

15.                      NavToolsVisible : true,   

16.                      CursorToolsVisible : true,   

17.                      SearchToolsVisible : true,   

18.                      localeChain: 'zh_CN'   

19.                  }}   

20.          );  

© 著作权归作者所有

攻城狮不是猫
粉丝 3
博文 57
码字总数 86313
作品 0
杭州
程序员
私信 提问
Liferay Portal 6.1 CE 发布

Liferay 的新版本旗舰软件产品 Liferay Portal 6.1 CE 今天发布![下载][快速开始] Liferay 的产品团队和开发团队与我们优秀的社区协调一致,历时数月致力于 6.1 的发布,现在终于大功告成。...

红薯
2012/02/24
1K
4
liferay整理(留着备用)

Liferay 6.1开发学习(二十):Dynamic Query高级查询 在上一篇的博客《Liferay 6.1开发学习(十九):Liferay ServiceBuilder之自定义查询》之中介绍了一部分简单的Dynamic Query方法,可以...

IT小香猪
2014/07/17
0
5
初学liferay,怎么用liferay整合第三方应用程序,请高手给点建议?

本人大学实习生,刚进公司实习,刚接触liferay,请教高手们怎么用liferay去整合第三方应用程序,给点学习建议,谢谢。目前我用的是liferay版本是6.1的,是在win7系统上安装部署测试的,目的是...

jobbiss
2013/03/23
1K
2
在Tomcat 6.0.33上安装Liferay 6.1.0 CE的步骤

一、准备工作 下载tomcat 6.0.33, liferay 6.1.0 CE的war文件包、源码包、SQL脚本包以及附加依赖包。本例子采用Mysql数据库作为存储引擎,故请安装Mysql数据库并确保mysql服务已经启动。由于...

mj4738
2012/05/27
0
0
Liferay6.1学习笔记(四)--整合CAS实现单点登录

转载:http://www.ibm.com/developerworks/cn/opensource/os-cn-liferay-cas/index.html Liferay 门户介绍 Liferay 是一个基于 J2EE 架构的完整的门户解决方案,使用了 EJB、JMS 等技术, 前...

Michaelyn
2014/01/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

js动态设置元素高度

this.$refs.xxx.style.height= this.contentHeight; 元素需要绑定

Carbenson
49分钟前
2
0
今天的学习

今天学到了ci框架中的查询语句的where条件语句: 1、$this->db->select('')->from('')->where('id = ??')->get()->result_array();2、$this->db->select('')->from('')->where('id', '??'......

墨冥
59分钟前
2
0
MySQL在高并发下的订单撮合、系统使用、共享锁与排他锁保证数据一致性

前序 距离上次择文发表,两月余久。2018年也即将要结束了,目前的工作依然是与区块链应用相关的,也很荣幸在9月初受邀签约出版暂名为《区块链以太坊DApp实战开发》一书,预计在明年年初出版。...

我最喜欢三大框架
今天
2
0
深入理解Flutter多线程

该文章属于<简书 — 刘小壮>原创,转载请注明: <简书 — 刘小壮> https://www.jianshu.com/p/54da18ed1a9e Flutter默认是单线程任务处理的,如果不开启新的线程,任务默认在主线程中处理。 ...

刘小壮
今天
3
0
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

//有点投机啦 import java.util.ArrayList; public class Solution { public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) { ArrayList <Integer> s=new ArrayLi......

南桥北木
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部