Apache Pluto&Perl集成教程示例
Perl是一门高级语言家族,由于使用了基于文本的处理,因此很容易适应Web。
为了实现这种集成,我们使用Portlet Perl桥进行了一些修改,这些修改已经在Apache SVN为该桥提供的源代码上完成。
与Perl集成并不是一件容易的事,因为一旦使用了默认的Apache Perl Bridge库,您可能会遇到很多问题。
不经任何修改直接使用Perl桥会引发ClassCastException,因为桥希望传递的RenderResponse实例为HttpServletResponseWrapper类型,但实际上不是。
在Portlet容器规范1.0中使用它时,效果似乎很好。
无论如何,我们现在在这里; Portlet容器规范2.0,我们必须为您提供一个执行此操作的库。
但是,您将无法进行Bridge修改,因为已经对其进行了修改并可以使用。
相反,您可以在此处下载最新的JAR,并将其安装到Maven存储库中,就像从Pom文件中引用任何库一样。
本教程旨在为您提供与我们之前提供的许多教程中已经介绍的相同的员工注册示例。
由于Perl的集成是一项复杂的任务,因此我们将专注于完成任务的方式,而不是专注于有效使用Perl的方式。
项目目录结构
员工表
由于我们建议的业务模式只是员工注册的过程,因此很容易知道我们有一个名为employee的表,如下所示:
您可以使用以下SQL语句将该表创建到数据库中:
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=2 DEFAULT CHARSET=utf8;
员工模式
根据MVC设计模式,应提供的数据必须位于数据模型中。
对于员工注册过程,员工数据模型应如下所示:
Employee.java
package com.theitroad.data; public class Employee { //Employee Identification private int id; //Employee Name private String name; //Employee Job private String job; //Employee Salary 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; } }
下载Apache Perl Bridge
为安装Apache Perl桥库引入了多种选择。
您可以直接从Maven存储库中引用它,从Apache源代码控件中获取源代码或者直接下载theitroad版本。
我们建议您下载theitroad版本,因为它已被修改,以防止您遇到上述异常。
从Maven存储库引用Apache Perl库应该使它可用于本地存储库,因此不需要进一步执行Maven命令。
如果您选择从源代码控制中获取Apache Perl,则需要执行mvn clean install以获取位于获取的文件夹上的pom.xml文件的就绪JAR。
但是,如果要下载在线发行版本,则必须遵循以下步骤,以确保能够从项目的maven文件中引用库:
将下载的ZIP文件保存到本地目录中。
将文件扩展名从ZIP更改为JAR。
通过使用命令行导航到下载JAR位置并执行
mvn install:install-file -DgroupId = org.apache.portals.bridges -DartifactId = portals-bridges-perl -Dversion = 1.0.4 -Dpackaging = jar -Dfile = {PATH-TO-FILE}
。确保您已成功完成Maven安装。
Maven构建文件
完成以前的库安装后,让我们看一下所需的maven构建文件:
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>PerlBridge</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>PerlBridge</name> <url>https://maven.apache.org</url> <properties> <deployFolder>D:/ApachePluto/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>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.7.0</version> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.1</version> </dependency> <dependency> <groupId>commons-digester</groupId> <artifactId>commons-digester</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>commons-digester</groupId> <artifactId>commons-digester</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.5</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-tools</artifactId> <version>2.0</version> </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.apache.portals.bridges</groupId> <artifactId>portals-bridges-perl</artifactId> <version>1.0.4</version> <exclusions> <exclusion> <groupId>org.apache.portals.jetspeed-2:</groupId> <artifactId>jetspeed-rewriter</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.portals.jetspeed-2</groupId> <artifactId>jetspeed-rewriter</artifactId> <version>2.1.4</version> <exclusions> <exclusion> <groupId>castor</groupId> <artifactId>castor</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>castor</groupId> <artifactId>castor</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>org.apache.portals.bridges</groupId> <artifactId>portals-bridges-common</artifactId> <version>2.0</version> </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>
您可能会注意到,下载的Apache Perl网桥已经在Maven文件中列出,因为它现在位于本地存储库中。
Perl Portlet和Portlet部署描述符
就像任何其他类型的Portlet一样,您的Perl Portlet必须如下所示:
PerlPortlet.java
package com.theitroad.portlet; import java.io.IOException; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.PortletException; import javax.portlet.PortletRequestDispatcher; import javax.portlet.PortletSession; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import org.apache.portals.bridges.perl.PerlParameters; public class PerlPortlet extends org.apache.portals.bridges.perl.PerlPortlet{ public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException{ if(request.getParameter("status") != null && request.getParameter("status").equals("success")){ PerlParameters perlParam = (PerlParameters)request.getPortletSession().getAttribute(PerlParameters.PERL_PA内存ETER, PortletSession.APPLICATION_SCOPE); if(perlParam == null){ perlParam = new PerlParameters(); perlParam.setScriptName("success.cgi"); perlParam.setApplicationName("PerlPortlet"); request.getPortletSession().setAttribute(PerlParameters.PERL_PA内存ETER,perlParam, PortletSession.APPLICATION_SCOPE); } super.doView(request, response); } else if(request.getParameter("status") != null && request.getParameter("status").equals("failure")){ PerlParameters perlParam = (PerlParameters)request.getPortletSession().getAttribute(PerlParameters.PERL_PA内存ETER, PortletSession.APPLICATION_SCOPE); if(perlParam == null){ perlParam = new PerlParameters(); perlParam.setScriptName("failure.cgi"); perlParam.setApplicationName("PerlPortlet"); request.getPortletSession().setAttribute(PerlParameters.PERL_PA内存ETER,perlParam, PortletSession.APPLICATION_SCOPE); } super.doView(request, response); } else if(request.getParameter("status") != null && request.getParameter("status").equals("initial")){ PerlParameters perlParam = (PerlParameters)request.getPortletSession().getAttribute(PerlParameters.PERL_PA内存ETER, PortletSession.APPLICATION_SCOPE); if(perlParam == null){ perlParam = new PerlParameters(); perlParam.setScriptName("register.cgi"); perlParam.setApplicationName("PerlPortlet"); request.getPortletSession().setAttribute(PerlParameters.PERL_PA内存ETER,perlParam, PortletSession.APPLICATION_SCOPE); } super.doView(request, response); } else { super.doView(request, response); } } public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException{ //Create request dispatcher PortletRequestDispatcher dispatcher = this.getPortletContext().getNamedDispatcher("RegisterEmployeeServlet"); try { if(request.getMethod().equals("POST")){ //Include dispatcher.include(request, response); //Set render parameter response.setRenderParameter("status", "success"); } else { response.setRenderParameter("status", "initial"); } } catch(Exception ex){ //Set render parameter response.setRenderParameter("status", "failure"); response.setRenderParameter("exception", ex.getMessage()); } } }
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> <display-name>PerlPortlet</display-name> <portlet-name>PerlPortlet</portlet-name> <portlet-class>com.theitroad.portlet.PerlPortlet</portlet-class> <description>Per Portlet</description> <init-param> <name>PerlScript</name> <value>register.cgi</value> </init-param> <init-param> <name>ScriptPath</name> <value>cgi-bin</value> </init-param> <init-param> <name>Application</name> <value>PerlPortlet</value> </init-param> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports> <portlet-info> <title>Perl Portlet</title> <keywords>Perl,Portlet</keywords> <short-title>Perl Portlet</short-title> </portlet-info> </portlet> </portlet-app>
以下是上面列出的代码的详细说明:
您的Perl Portlet的类型应为org.apache.portals.bridges.perl.PerlPortlet。
您可以通过扩展PerPortlet或者在Portlet部署描述符中直接提及Perl Portlet来定义Perl Portlet,而无需扩展现有的类。
每次渲染Portlet时都会调用doView,因此,它将读取状态参数,该参数确定应委派哪个Perl视图。
要更改Perl视图,您应该使用提供了scriptName和applicationName的PerlParameters对象。
调用super.doView()将确保应该显示和呈现新选择的Perl脚本。
确保您设置了相同的applicationName,就像在Portlet.xml中定义的名称一样。
doView方法已定义默认情况,对于该情况默认为不传递状态参数或者不传递初始值。
默认视图将通过调用super.doView()进行处理,而无需其他PerlParamater。
为此,主要应该在Portlet.xml内提供PerlScript和ScriptPath。ProcessAction已定义了用于注册Employee的所有必需代码。
您应该注意,由于Perl Portlet的种类,我们已经在ProcessAction方法中区分了POST请求和GET请求。
Perl Portlet将所有相关URL转换为Portlet操作,因此它们将调用ProcessAction。您可以通过扩展对在ProcessAction中设置的渲染参数的使用来扩展此工作,以在Perl脚本中使用。
Perl视图
我们假设我们有三种不同的Perl脚本,它们是:
register.cgi
#!D:\Strawberry\perl\bin\perl - print qq( <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Register Employee</title> </head> <body> <form action="/dummyAction" 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.cgi
#!D:\Strawberry\perl\bin\perl - print qq( Register Employee <table width="100%"> <tbody> <tr> <td>Registration has done successfully!</td> <td><a href="/pluto/portal/theitroad">Register Another</a></td> </tr> </tbody> </table> );
failure.cgi
#!D:\Strawberry\perl\bin\perl - print qq( Register Employee <table width="100%"> <tbody> <tr> <td>Registration hasn't done successfully!</td> <td><a href="/pluto/portal/theitroad">Register Another</a></td> </tr> </tbody> </table> );
以下是上面列出的代码的详细说明:
我们引用了已经安装到您的计算机中的perl。
您可以通过从此处下载Perl软件将Perl安装到计算机中。通常,您使用的是#!在Perl中可以从Perl脚本中引用本地驱动器。
我们使用了打印功能来打印HTML内容。
RegisterEmployeeServlet –业务委托
我们将员工注册业务留在了名为RegisterEmployeeServlet的单独的Servlet中。
如下图所示:
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); } } }
数据库实用程序
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; } }
员工注册演示
在开始演示如何使用Perl脚本进行员工注册之前,让我们回到Apache Pluto简介中,这将帮助您显示准备好的theitroad门户页面。
现在,将您的Perl Portlet设置到您的theitroad门户页面,然后开始进行员工注册过程:
而且,如果您尝试使用相同的ID注册同一名员工,则可能会收到以下回复。