本文使用spring集成hibernate完成一个liferay portlet的开发,做为plugin的方式部署到liferay容器当中。提供源代码下载。
版本约束:
Spring 3.0 及以上
Hiberante 3.5
Liferay 6.0及以上
构建基制:
Ant
Maven
知识点描述:
使用Hiberante+jndi的方式,否则使用Hiberante+jdbc的话,在liferay当中部署不成功,然后再集成Spring,最前端使用GenericPortlet。
开发配置:
web.xml
<?xml version="1.0"?> <web-app 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" version="2.4"> <display-name>AntBee Portlet</display-name> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/classes/log4j.properties</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
Spring的配置文件:applicationContext.xml,放在\WEB-INF\applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
">
<aop:aspectj-autoproxy />
<context:component-scan base-package="com.antbee.portlet" />
<jee:jndi-lookup jndi-name="java:comp/env/jdbc/myportalDB"
id="dataSource" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="annotatedClasses">
<list>
<value>com.antbee.portlet.domain.MonitorItem</value>
<value>com.antbee.portlet.domain.SearchResult4Db</value>
</list>
</property>
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="loggingAspect" class="com.antbee.portlet.base.LoggingAspect" />
</beans>
针对Liferay Portlet的几个配置文件:portlet.xml,放在目录:WEB-INF\portlet.xml
<?xml version="1.0" encoding="UTF-8"?> <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"> <portlet> <portlet-name>resultForNews</portlet-name> <portlet-class>com.antbee.portlet.base.SearchResultPortlet</portlet-class> <expiration-cache>1000</expiration-cache> <cache-scope>private</cache-scope> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> </supports> <resource-bundle>content.Language-ext</resource-bundle> <portlet-info> <title>安特比软件-Portlet演示</title> </portlet-info> </portlet> </portlet-app>
接上面,同样是portlet的配置文件:liferay-display.xml,放在目录WEB-INF\liferay-display.xml
<?xml version="1.0"?> <!DOCTYPE display PUBLIC "-//Liferay//DTD Display 6.0.0//EN" "http://www.liferay.com/dtd/liferay-display_6_0_0.dtd"> <display> <category name="antbee.portlet.function"> <portlet id="resultForNews" /> </category> </display>
接上面,同样是portlet的配置文件:liferay-portlet.xml,放在目录WEB-INF\liferay-portlet.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 6.0.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_0_0.dtd"> <liferay-portlet-app> <portlet> <portlet-name>resultForNews</portlet-name> <instanceable>true</instanceable> <remoteable>true</remoteable> <header-portlet-css>/css/bookCatalog.css</header-portlet-css> <header-portlet-javascript>/js/bookCatalog.js</header-portlet-javascript> </portlet> </liferay-portlet-app>
前端继承的GenericPortlet的SearchResultPortlet.java
package com.antbee.portlet.base;
import java.io.IOException;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import javax.portlet.GenericPortlet;
import javax.portlet.PortalContext;
import javax.portlet.PortletException;
import javax.portlet.PortletMode;
import javax.portlet.PortletRequest;
import javax.portlet.RenderMode;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.WindowState;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.web.portlet.context.PortletApplicationContextUtils;
import com.antbee.portlet.service.SearchResultService;
import com.antbee.portlet.utils.Constants;
/**
*
* @author Weiya
*
*/
public class SearchResultPortlet extends GenericPortlet {
private Logger logger = Logger.getLogger(SearchResultPortlet.class);
private static SearchResultService searchResultService;
public void init() {
searchResultService = getSearchResultService();
}
public SearchResultService getSearchResultService() {
ApplicationContext springCtx = PortletApplicationContextUtils.getWebApplicationContext(getPortletContext());
return (SearchResultService)springCtx.getBean("searchResultService");
}
@RenderMode(name = "VIEW")
public void showSearchResult(RenderRequest request, RenderResponse response)
throws IOException, PortletException {
logger.info("Inside showSearchResult method");
PortalContext context = request.getPortalContext();
printSupportedPortletModes(context);
printSupportedWindowStates(context);
Map userAttributeMap = (Map) request
.getAttribute(PortletRequest.USER_INFO);
String firstName = "";
String lastName = "";
if (userAttributeMap != null) {
firstName = (String) userAttributeMap.get("user.name.given");
lastName = (String) userAttributeMap.get("user.name.family");
// --set firstName and lastName in request so that JSP can pick
// --from the request
request.setAttribute("firstName", firstName);
request.setAttribute("lastName", lastName);
}
String jspPage = "home.jsp";
// Got Data
List results = searchResultService.getKeyWordByMonitorItem(3);
request.setAttribute("results", results);
getPortletContext().getRequestDispatcher(
response.encodeURL(Constants.PATH_TO_JSP_FUNCTION_PAGE + jspPage))
.include(request, response);
}
//-- Print supported portlet modes by the portal server
private void printSupportedPortletModes(PortalContext context) {
// -- supported portlet modes by the portal server
Enumeration<PortletMode> portletModes = context
.getSupportedPortletModes();
while (portletModes.hasMoreElements()) {
PortletMode mode = portletModes.nextElement();
logger.info("Support portlet mode " + mode.toString());
}
}
//-- prints support window states by the portal server
private void printSupportedWindowStates(PortalContext context) {
// -- supported window states by the portal server
Enumeration<WindowState> windowStates = context
.getSupportedWindowStates();
while (windowStates.hasMoreElements()) {
WindowState windowState = windowStates.nextElement();
logger.info("Support window state " + windowState.toString());
}
}
}
还有构建脚本:build.xml
<?xml version="1.0"?>
<!-- define the project -->
<project name="antbeePortlet" default="build" basedir=".">
<!-- define project properties -->
<property name="compiler" value="modern" />
<property name="fork" value="no" />
<property name="verbose" value="no" />
<property name="debug" value="on" />
<property name="optimize" value="on" />
<property name="deprecation" value="on" />
<property name="target" value="1.5" />
<property name="source" value="1.5" />
<property file="build.properties" />
<property environment="env" />
<!-- define properties to refer to directories in the project -->
<property name="webinf.dir" value="WEB-INF" />
<property name="webinf.lib.dir" value="WEB-INF/lib" />
<property name="lib.dir" value="lib" />
<property name="src.dir" value="src" />
<property name="test.dir" value="test" />
<property name="build.dir" value="build" />
<property name="webinf.classes.dir" value="${webinf.dir}/classes" />
<property name="webinf.classes.content.dir" value="${webinf.dir}/classes/content" />
<property name="web.xml" value="${webinf.dir}/web.xml" />
<fileset id="webapp.libs" dir="${webinf.lib.dir}">
<include name="*.jar" />
</fileset>
<fileset id="libs" dir="${lib.dir}">
<include name="*.jar" />
</fileset>
<path id="class.path">
<pathelement path="${webinf.classes.dir}" />
<fileset refid="webapp.libs" />
<fileset refid="libs" />
</path>
<pathconvert pathsep=":" property="class.path" refid="class.path" />
<fileset id="war.files" dir=".">
<include name="${webinf.dir}/**" />
<exclude name="${webinf.dir}/Language-ext*.properties" />
<exclude name="${webinf.dir}/ValidationMessages.properties" />
<include name="images/**" />
<include name="css/**" />
<include name="js/**" />
<exclude name="${web.xml}" />
</fileset>
<!-- compile target to compile the sources -->
<target name="compile">
<mkdir dir="${webinf.classes.dir}" />
<!-- Content directory contains Liferay resource bundle-->
<mkdir dir="${webinf.classes.content.dir}" />
<javac srcdir="${src.dir}:${test.dir}" destdir="${webinf.classes.dir}" fork="${fork}" verbose="${verbose}" deprecation="${deprecation}" debug="${debug}" optimize="${optimize}" compiler="${compiler}" target="${target}" source="${source}">
<classpath refid="class.path" />
</javac>
<copy todir="${webinf.classes.dir}" preservelastmodified="true">
<fileset dir="${src.dir}">
<include name="**/*.properties" />
<include name="**/*.xml" />
</fileset>
</copy>
<copy todir="${webinf.classes.content.dir}">
<fileset dir="${webinf.dir}">
<include name="Language-ext*.properties" />
</fileset>
</copy>
</target>
<!-- target to create the project WAR file -->
<target name="build" depends="clean,compile">
<mkdir dir="${build.dir}" />
<war destfile="${build.dir}/antbeePortlet.war" webxml="${web.xml}">
<fileset refid="war.files" />
</war>
<copy todir="${liferay.portal.home}/deploy">
<fileset dir="${build.dir}">
<include name="**/*.war" />
</fileset>
</copy>
</target>
<!-- target to clean up all files created by various tasks -->
<target name="clean">
<delete quiet="true" includeemptydirs="true">
<fileset dir="${webinf.classes.dir}" includes="**/*" />
<fileset dir="${build.dir}" />
<fileset dir="${work.dir}" />
</delete>
</target>
</project>
另外一个是SVN的构建脚本pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>antbee</groupId>
<artifactId>antbeePortlet</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<repositories>
<repository>
<id>JBoss Repository</id>
<url>http://repository.jboss.com/maven2</url>
</repository>
</repositories>
<build>
<sourceDirectory>${project.basedir}/src</sourceDirectory>
<outputDirectory>${project.basedir}/target/classes</outputDirectory>
<resources>
<resource>
<targetPath>content</targetPath>
<directory>WEB-INF</directory>
<includes>
<include>Language-ext.properties</include>
</includes>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-alpha-2</version>
<configuration>
<webResources>
<resource>
<directory>css</directory>
<targetPath>css</targetPath>
</resource>
<resource>
<directory>js</directory>
<targetPath>js</targetPath>
</resource>
<resource>
<directory>images</directory>
<targetPath>images</targetPath>
</resource>
<resource>
<directory>WEB-INF/jsp/</directory>
<targetPath>WEB-INF/jsp</targetPath>
</resource>
<resource>
<directory>WEB-INF</directory>
<targetPath>WEB-INF</targetPath>
<includes>
<include>**/*.xml</include>
</includes>
<excludes>
<exclude>Language-ext.properties</exclude>
</excludes>
</resource>
</webResources>
<webXml>${project.basedir}/WEB-INF/web.xml</webXml>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>javax.portlet</groupId>
<artifactId>portlet-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.5.0-Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.5.0-Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-asm</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc-portlet</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>3.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.0.0.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.9.0.GA</version>
</dependency>
</dependencies>
</project>
哈哈。如果完成项目后,可以通过:
ANT脚本: ant clean build
MAVEN脚本:mvn clean install构建项目
在部署到liferay时,要创建jndi的连接方式,如下是我的创建过程和脚本:(目标是TOMCAT服务器)
Add <Resource> element in server.xml, inside <GlobalNamingResources> element.
<GlobalNamingResources>
..
<Resource name="jdbc/myportalDB"
auth="Container"
type="javax.sql.DataSource"
username="root" password="root"
driverClassName="com.mysql.jdbc.Driver"
factory="org.apache.commons.dbcp.BasicDataSourceFactory"
url="jdbc:mysql://localhost/myportaldb?useUnicode=true&"
maxActive="5"
maxIdle="2"/>
..
</GlobalNamingResources>
Add <ResourceLink> element in context.xml file, inside <Context> element.
<Context>
....
<ResourceLink name="jdbc/myportalDB"
global="jdbc/myportalDB"
type="javax.sql.DataSource"/>
....
</Context>
重新启动,enjoy it!
不买关子,提供代码让大家下载,如果有什么不明白的,请留言。(eclipse项目,可以直接导入)
下载代码当中去掉了jar,如下是抓图: