liferay有自己的struts和spring扩展,有兴趣的朋友可以看一下它对spring的扩展和使用。这里说一下使用liferay的对struts框架的支持下的开发;我用的是struts1.*,liferay现在也有对struts2.*的支持桥,暂不讨论,以后用到的时候再说。
对于用惯了SSH开发的人来说,刚开始在liferay中使用struts还是有些不适应的,我的不适应来自于请求的发送。由于我使用的是集成了liferay环境的tomcat:liferay-portal-tomcat-5.5-5.1.2,所以有很多jar文件的冲突;
struts配置介绍:
先说一下配置文件的构造。在你自己的portlet下的WEB-INF中需要有这几个配置文件:liferay-display.xml,liferay-portlet.xml,portlet.xml,tiles-defs.xml,struts-config.xml,web.xml;我们一个一个的看看,哈!
web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>PortletActionServlet</servlet-name> <servlet-class> com.liferay.portal.struts.PortletActionServlet </servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>PortletActionServlet</servlet-name> <url-pattern>/portlet_action/*</url-pattern> </servlet-mapping> </web-app>
这里把对struts的action的请求都通过portlet用桥接做了处理后再交由struts自己的action进行处理;
再看struts-config.xml,这个和我们一般用的也没啥区别:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"> <struts-config> <action-mappings> <action path="/library/view" type="exam.ssha.webapp.action.GoodAction"> <forward name="library.view" path="library.view" /> </action> <action path="/library/edit_entry" type="exam.ssha.webapp.action.GoodAction"> <forward name="library.edit_entry" path="library.edit_entry" /> <forward name="library.view" path="library.view" /> </action> </action-mappings> <message-resources parameter="content.Language" /> <plug-in className="org.apache.struts.tiles.TilesPlugin"> <set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" /> <set-property property="moduleAware" value="true" /> <set-property property="definitions-parser-validate" value="true" /> </plug-in> </struts-config>
处理后的跳转映射是在tiles-defs.xml中定义的:
<?xml version="1.0"?> <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd"> <tiles-definitions> <definition name="library.view" path="/library/view.jsp" /> <definition name="library.edit_entry" path="/library/edit_entry.jsp" /> </tiles-definitions>
这是portlet.xml:
<?xml version="1.0" encoding="UTF-8"?> <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"> <portlet> <portlet-name>myExam</portlet-name> <display-name>MyExam</display-name> <portlet-class>com.liferay.portlet.StrutsPortlet</portlet-class> <init-param> <name>view-action</name> <value>/library/view</value> </init-param> <expiration-cache>0</expiration-cache> <supports> <mime-type>text/html</mime-type> </supports> <resource-bundle>content.Language</resource-bundle> <portlet-info> <title>MyExam</title> <short-title>MyExam</short-title> <keywords>myExam</keywords> </portlet-info> <security-role-ref> <role-name>user</role-name> </security-role-ref> </portlet> </portlet-app>
如果你看了前面关于portletl的介绍,这个也能很容易看懂,这个只是在启动参数上有区别,不用struts的时候是jsp页面,现在是struts的请求映射;
接下来是liferay-portlet.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 4.4.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_4_4_0.dtd"> <liferay-portlet-app> <portlet> <portlet-name>myExam</portlet-name> <struts-path>library</struts-path> <restore-current-view>false</restore-current-view> <header-portlet-css>/html/library/css.jsp</header-portlet-css> <header-portlet-javascript>/html/js/util.js</header-portlet-javascript> <css-class-wrapper>portlet-library</css-class-wrapper> </portlet> <role-mapper> <role-name>user</role-name> <role-link>User</role-link> </role-mapper> </liferay-portlet-app>
liferay-display.xml:
<?xml version="1.0"?> <!DOCTYPE display PUBLIC "-//Liferay//DTD Display 4.0.0//EN" "http://www.liferay.com/dtd/liferay-display_4_0_0.dtd"> <display> <category name="category.exam"> <portlet id="myExam" /> </category> </display>
注意id的对应就好了。
Spring配置:
我的spring配置文件放到了Classes_HOME/META-INF/下,有两个文件:init.properties和jdbcContext.xml;
用过spring的人一看都知道的,一个是数据源方面的属性配置文件,一个是数据源加载和各种bean的配置文件。
这是加载spring的配置文件的代码:
this.appContext = new ClassPathXmlApplicationContext(
"/META-INF/jdbcContext.xml");
jar文件冲突
liferay本身的开发和运行环境提供了对struts和spring的支持,在集成了liferay的环境的tomcat中运行测试时难免会有jar文件的冲突;在你自己的项目lib目录中struts相关的jar文件是不能有的,还有就是liferay对spring做扩展了的一些jar也不能引入,有spring-core.jar spring-bean.jar;还有liferay本身就扩展了log4j的一些东西,你的lib中也不能有log4j的jar。当然这不是绝对的,这只是我测试多次以后发现的,根据不同的应用jar文件的引用应该根据具体需要来定,哈!这是我应用中的一个jar文件清单:
Struts中action
在使用liferay对struts扩展之后,action需要继承com.liferay.portal.struts.PortletAction类,这时Action中主要有两个方法:
public void processAction(ActionMapping mapping, ActionForm form,
PortletConfig config, ActionRequest request, ActionResponse response)
public ActionForward render(ActionMapping mapping, ActionForm form,
PortletConfig config, RenderRequest request, RenderResponse response)
processAction方法只有当页面中是form的POST请求时才会调用,而render方法是所有请求都会调用,也就是说当时form的POST请求时是先调用processAction方法,之后调用render方法的。在processAction方法中用setForward(request, "url");方法设定跳转,在render方法中会生效的。
页面中的注意事项
开始时我在页面中使用jstl总是不起作用,还以为是liferay对jstl标签有什么限制,其实不然;页面中没有什么特别的,和一般我们的页面开发没有多少区别;不能使用jstl的原因是因为我做例子的时候是基于一个别人的例子做的,结果例子中web.xml配置的servlet是2.3版本,而我本身的jsp环境是2.0,使得在页面中无法应用表达式语言,把web.xml中的配置改为2.4就都OK了。还有一点是,portlet的页面不是一个完整的页面,所以html代码用到什么就写啥。
struts请求的发送,简便的方式还是只用标签,如:
<portlet:renderURL><portlet:param name="struts_action" value="/library/edit_entry"/></portlet:renderURL>
这里的参数名称struts_action就是标识着映射名称,如果你想在这个请求后面用js动态添加参数,直接<portlet:namespace />参数名=参数值 这样添加到这个请求后面就可以了。页面form中的每一项属性都需要用<portlet:namespace />区分,因为每一个portlet都是一个独立的web应用。
Ajax的使用
我试过用ajax向liferay的struts的action类发送请求,但是在action中不能正确返回xml数据,查了不少资料:一种说是,portlet中的数据返回只能是txt/html格式的,这个已经在配置文件中写死了,不能返回 txt/xml格式的数据;还有一种说是和liferay本身或者是portal本身的页面加载机制有关系。在com.liferay.portlet.documentlibrary.action下有一个GetFileAction类,这是一个文件下载的处理类,我试过里面的ServletResponseUtil中的几个方法,在客户端还是得不到xml数据;试了几种方式,返回的都是整个页面的html代码。最后我采用了不少人的建议,就是不使用action处理ajax请求,改用jsp或者servlet处理,这样发送请求的时候需要加上应用目录名称,指明具体的请求地址;或者使用单独的struts action处理,不使用portlet action。
如有疏漏或问题,欢迎回复交流,例子代码请发邮件索取。