Apache Pluto和Groovy集成教程示例
Apache Pluto为您提供了大量集成类型,可用于处理Portlet开发任务。
我们之前已经向您介绍了不同类型的Portlet;标准Portlet(JSR286),JSP和Servlet,JSF 2.0,Struts 2.0,PHP 5,现在是Groovy类型的Portlet。
Groovy是一种Java虚拟语言(JVM),可以像您编写的任何Java类一样在JVM中无缝运行。
Apache Pluto为您提供了Groovy桥,使您可以将Groovy Portlet暴露到门户页面中,而无需其他外观。
本教程旨在为您提供完整的员工注册示例,其中将显示初始页面以收集员工的信息。
用户提交表单后,将开始员工注册,并且还将显示确认消息。
项目结构
下图可以帮助您识别放置Groovy类的最佳位置之一,并为您显示该项目的不同随附文件。
员工表
由于我们拥有注册员工表格,因此让我们看一下"员工表格"的表格及其相关列。
同样,您可以使用下面的SQL create语句将Employee Table创建到Schema中。
employee.sql
CREATE TABLE `employee` ( `EMP_ID` int(11) NOT NULL AUTO_INCREMENT, `EMP_NAME` varchar(45) DEFAULT NULL, `EMP_JOB` varchar(45) DEFAULT NULL, `EMP_SALARY` int(11) DEFAULT NULL, PRIMARY KEY (`EMP_ID`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
员工模式
在MVC设计模式中,并根据关注分离的概念,我们必须具有以下形式的Employee模型:
Employee.java
package com.theitroad.data;
public class Employee {
private int id;
private String name;
private String job;
private int salary;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
该模型将保存应用程序中定义的不同组件之间来回的数据。
将Groovy插件安装到Eclipse中
为了确保可以在Maven项目中获取Groovy源码,必须将Eclipse Groovy插件安装到Eclipse IDE中。
安装Eclipse插件不会花费很多时间,因为您可以使用Eclipse安装新软件工具来完成安装。
从帮助菜单中选择安装新软件。
将复制的链接粘贴到"使用输入"中,然后等待Eclipse向您显示插件包含的列出的假定更新。
选择Groovy-Eclipse(必需)并单击下一步。
继续进行操作,直到您的Eclipse安装了Groovy插件,然后重新启动Eclipse以确保已安装的插件生效。
现在,从您之前创建的Maven项目中,正常创建一个Groovy类。
RegisterEmployeePortlet Groovy Portlet
RegisterEmployeePortlet的构建将采用与我们介绍的JSP&Servlet示例相同的方式进行。
它与现在的Groovy类的主要区别在于,该类不需要包声明或者变量类型。
您可以编写类似于您在RegisterEmployeePortlet Java类中编写的代码的代码,但是为了区别起见,我们删除了Groovy不需要的那些可选结构。
RegisterEmployeePortlet.groovy
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
public class RegisterEmployeePortlet extends GenericPortlet{
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
if(request.getParameter("status") == null){
//Create a dispatcher
def dispatcher = this.getPortletContext().getRequestDispatcher("/register/registerEmployee.jsp");
dispatcher.include(request, response);
}
else if(request.getParameter("status") != null && request.getParameter("status").equals("initiate")){
//Create a dispatcher
def dispatcher = this.getPortletContext().getRequestDispatcher("/register/registerEmployee.jsp");
dispatcher.include(request, response);
}
else if(request.getParameter("status") != null && request.getParameter("status").equals("success")){
//Create a dispatcher
def dispatcher = this.getPortletContext().getRequestDispatcher("/register/success.jsp");
dispatcher.include(request, response);
}
else if(request.getParameter("status") != null && request.getParameter("status").equals("failed")){
//Create a dispatcher
def dispatcher = this.getPortletContext().getRequestDispatcher("/register/failure.jsp");
request.setAttribute("exception", request.getParameter("exception"));
dispatcher.include(request, response);
}
}
public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException{
//Create request dispatcher
def dispatcher = this.getPortletContext().getNamedDispatcher("RegisterEmployeeServlet");
try {
//Include
dispatcher.include(request, response);
//Set render parameter
response.setRenderParameter("status", "success");
}
catch(Exception ex){
//Set render parameter
response.setRenderParameter("status", "failed");
response.setRenderParameter("exception", ex.getMessage());
}
}
}
以下是上述代码的详细说明:
RegisterEmployeePortlet Groovy类未引用程序包,因为它包含在上述项目结构的资源中。
Groovy是一种动态语言,因此,它适用于您错过变量类型。
或者,您必须使用一个def关键字,Groovy引擎会从上下文中期望变量的类型。Groovy类还能够访问应用程序内部的任何已定义Servlet。
RegisterEmployeePortlet Groovy Portlet描述符
因为您已经使用Groovy类创建要由Apache Pluto使用的Portlet,所以您知道必须在Portlet部署描述符(Portlet.xml)中提及该Portlet。
Portlet描述符中的Groovy Portlet的定义稍有不同,因为它也包含了您必须了解的其他细节。
首先让我们看一下Portlet.xml,看看主要区别是什么。
portlet.xml
<?xml version="1.0" encoding="UTF-8"?> <portlet-app xmlns="https://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"> <portlet id="RegisterEmployee"> <display-name>Register Employee</display-name> <portlet-name>RegisterEmployee</portlet-name> <portlet-class>org.apache.portals.bridges.groovy.GroovyPortlet</portlet-class> <init-param> <name>script-source</name> <value>classpath:RegisterEmployeePortlet.groovy</value> </init-param> <init-param> <name>auto-refresh</name> <value>true</value> </init-param> <description>Employee Registration</description> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports> <portlet-info> <title>Employee Registration</title> <keywords>employee, registration</keywords> <short-title>Employee Registration</short-title> </portlet-info> </portlet> </portlet-app>
以下是上述代码的详细说明:
您的Groovy Portlet应该属于org.apache.portals.bridge.groovy.GroovyPortlet类。
您必须提供script-source,以后将用于指定负责处理启动的Portlet请求的Groovy类。
您可以提供一个可选的自动刷新参数来立即应用您的修改。
因此,只需进行修改并刷新Portlet即可直接执行它。脚本源参数接受不同类型的路径。
完整的物理文件,url,uri或者使用所示的保留关键字classpath。
应用程序部署描述符和Maven构建文件
Web部署描述符没有任何变化,使用的文件与" JSP&Servlet教程"中定义的文件相同。
web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "https://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Employee Registration</display-name> <servlet> <servlet-class>com.theitroad.servlet.RegisterEmployeeServlet</servlet-class> <servlet-name>RegisterEmployeeServlet</servlet-name> </servlet> <servlet-mapping> <servlet-name>RegisterEmployeeServlet</servlet-name> <url-pattern>/registerEmployeeServlet</url-pattern> </servlet-mapping> <taglib> <taglib-uri>https://java.sun.com/portlet</taglib-uri> <taglib-location>/WEB-INF/portlet.com</taglib-location> </taglib> </web-app>
只需注意,Apache Pluto组装插件将在构建使Portlet可访问的应用程序时向您的web.xml中添加一些片段。
另一方面,所有必需的依赖项都由Maven构建文件维护,请在下面查看所使用的pom.xml。
pom.xml
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.theitroad</groupId>
<artifactId>GroovyBridge</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>GroovyBridge</name>
<url>https://maven.apache.org</url>
<properties>
<deployFolder>D:/Apache Pluto/pluto-2.0.3/webapps</deployFolder>
</properties>
<dependencies>
<!-- Java Portlet Specification V2.0 -->
<dependency>
<groupId>org.apache.portals</groupId>
<artifactId>portlet-api_2.0_spec</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.pluto</groupId>
<artifactId>pluto-taglib</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>1.1-rc-2</version>
</dependency>
<dependency>
<groupId>antlr</groupId>
<artifactId>antlr</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.apache.portals.bridges</groupId>
<artifactId>portals-bridges-groovy</artifactId>
<version>1.0.4</version>
<exclusions>
<exclusion>
<groupId>org.apache.portals.jetspeed-2</groupId>
<artifactId>jetspeed-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- bind 'pluto2:assemble' goal to 'process-resources' lifecycle -->
<!-- This plugin will read your portlet.xml and web.xml and injects required
lines -->
<plugin>
<groupId>org.apache.portals.pluto</groupId>
<artifactId>maven-pluto-plugin</artifactId>
<version>2.1.0-M3</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>assemble</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- configure maven-war-plugin to use updated web.xml -->
<!-- This plugin will make sure your WAR will contain the updated web.xml -->
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<webXml>${project.build.directory}/pluto-resources/web.xml</webXml>
</configuration>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>integration-test</phase>
<configuration>
<tasks>
<copy file="target/${project.artifactId}.war" tofile="${deployFolder}/${project.artifactId}.war"
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>delete</id>
<phase>clean</phase>
<configuration>
<tasks>
<delete file="${deployFolder}/${project.artifactId}.war"
<delete dir="${deployFolder}/${project.artifactId}"
</tasks>
<detail>true</detail>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
EmployeeDAO和ConnectionUtility –数据库处理
EmployeeDAO.java
package com.theitroad.dao;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.theitroad.dao.utility.ConnectionUtility;
import com.theitroad.data.Employee;
public class EmployeeDAO {
public static EmployeeDAO employeeDAO = null;
private EmployeeDAO(){
}
public static EmployeeDAO getInstance(){
synchronized(EmployeeDAO.class){
if(employeeDAO == null){
employeeDAO = new EmployeeDAO();
}
}
return employeeDAO;
}
public Employee createEmployee(Employee employee) throws SQLException, IllegalAccessException, IOException, ClassNotFoundException{
//Get connection instance
Connection connection = ConnectionUtility.getInstance().getConnection();
//Create Prepared Statement
PreparedStatement query = connection.prepareStatement("INSERT INTO EMPLOYEE VALUES (?,?,?,?)");
//Set variables
query.setInt(1, employee.getId());
query.setString(2, employee.getName());
query.setString(3, employee.getJob());
query.setInt(4, employee.getSalary());
try {
//Execute
query.execute();
//Return employee instance
return employee;
}
catch(Exception e){
//Close statement
query.close();
//Close connection
connection.close();
//Throw another exception for notifying the Servlet
throw new SQLException(e);
}
}
public boolean deleteEmployee(Employee employee){
return false;
}
public boolean updateEmployee(Employee employee, int employeeId){
return false;
}
}
ConnectionUtility.java
package com.theitroad.dao.utility;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class ConnectionUtility {
private static ConnectionUtility connectionUtiliy = null;
private Connection connection = null;
private ConnectionUtility() {
}
public static ConnectionUtility getInstance() throws IOException, IllegalAccessException, SQLException, ClassNotFoundException{
//Synchronized against connectionUtility instance
synchronized(ConnectionUtility.class){
//Check whether the connectionUtility is null or not
if(connectionUtiliy == null){
//Create a properties instance
Properties properties = new Properties();
//Load properties from classpath
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("connection.properties"));
//Set connection with connectionUtility
connectionUtiliy = new ConnectionUtility();
//Load driver class
Class.forName("com.mysql.jdbc.Driver");
//Create connection
connectionUtiliy.setConnection(DriverManager.getConnection("jdbc:mysql://localhost:3306/theitroad", properties));
}
return connectionUtiliy;
}
}
public Connection getConnection() throws ClassNotFoundException, SQLException, IOException {
if(connection.isClosed()){
//Create a properties instance
Properties properties = new Properties();
//Load properties from classpath
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("connection.properties"));
//Load driver class
Class.forName("com.mysql.jdbc.Driver");
//Create connection
connectionUtiliy.setConnection(DriverManager.getConnection("jdbc:mysql://localhost:3306/theitroad", properties));
}
return connection;
}
public void setConnection(Connection connection) {
this.connection = connection;
}
}
RegisterEmployeeServlet –业务处理
相反,如果您注意到Groovy类没有提供与注册过程相关的任何代码,则它主要用于处理所需的业务委托,并且在我们的RegisterEmployeeServlet内部定义了员工注册的实际工作,该概念适用关注分离(Soc)。
看下面:
RegisterEmployeeServlet.java
package com.theitroad.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import com.theitroad.dao.EmployeeDAO;
import com.theitroad.data.Employee;
public class RegisterEmployeeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
Logger logger = Logger.getLogger(RegisterEmployeeServlet.class);
public RegisterEmployeeServlet() {
super();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Create employee
Employee employee = new Employee();
//Fill in required data from the request sent
employee.setId(Integer.parseInt(request.getParameter("employeeID")));
employee.setName(request.getParameter("employeeName"));
employee.setJob(request.getParameter("employeeJob"));
employee.setSalary(Integer.parseInt(request.getParameter("employeeSalary")));
try {
//Asking employeeDAO creating the employee against registered database
Employee createdEmployee = EmployeeDAO.getInstance().createEmployee(employee);
//Print out the created employee information
logger.info("Employee Created"+createdEmployee);
} catch (Exception e) {
//Log the exception
logger.error("Employee Creation Failed", e);
//Throw another exception for notifying the Portlet
throw new ServletException(e);
}
}
}
JSP视图
如上所述,您的Groovy Portlet已将控件委派给三个不同的JSP页面:
registerEmployee.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri='https://java.sun.com/portlet' prefix='portlet'%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Register Employee</title> </head> <body> <portlet:actionURL var="registerLink" <form action="<%=registerLink%>" method="POST"> <table width="100%"> <tr width="60%"> <td>Enter Employee ID:</td> <td><input name="employeeID" </td> </tr> <tr width="60%"> <td>Enter Employee Name:</td> <td><input name="employeeName" </td> </tr> <tr width="60%"> <td>Enter Employee Job:</td> <td><input name="employeeJob" </td> </tr> <tr width="60%"> <td>Enter Employee Salary:</td> <td><input name="employeeSalary" </td> </tr> <tr width="60%" align="center"> <td colspan="2"><input type="submit" value="Register" </td> </tr> </table> </form> </body> </html>
success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri='https://java.sun.com/portlet' prefix='portlet'%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Register Employee</title> </head> <portlet:renderURL var="registerAnother"> <portlet:param name="status" value="initiate" </portlet:renderURL> <img src="<%=request.getContextPath()%>/images/success.jpg" name="<portlet:namespaceSuccess" <body> Congratulations ! you've just add a new employee<br<a href="<%=registerAnother%>">Register Another</a> </body> </html>
failure.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri='https://java.sun.com/portlet' prefix='portlet'%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Register Employee</title>
</head>
<portlet:defineObjects
<portlet:renderURL var="registerAnother">
<portlet:param name="status" value="initiate"
</portlet:renderURL>
<body>
Unfortunately ! you Jan not be able of registering a new employee cause the reason below
<br
<br
<img src="<%=request.getContextPath()%>/images/failed.jpg" name="<portlet:namespaceFailed"
<span style="font-size:small ;font-style: italic;color: red;font-weight: bold;">
<%=renderRequest.getAttribute("exception")%>
<br
<br
<a href="<%=registerAnother%>">Try Again</a>
</body>
</html>
员工注册演示
在开始演示员工注册示例之前,您必须已安装Apache Pluto实例以及theitroad门户页面。
如果您以前没有创建过它,则需要返回到Apache Pluto简介以完成所有操作。
而且您应该能够看到新的Employee已保存到数据库中:
而且,如果您尝试使用相同的ID来注册用户,则应该能够看到一条消息,告诉您实际的错误原因。
总结
Groovy是一种动态JVM语言,它令人惊叹,因为您无需了解很多事情,而在使用Java语言时则必须知道这些事情。
如果希望Portlet为您提供最大的动态范围,请选择Groovy,因为您可以在JVM运行时更改类。

