portlet示例

In the presented introduction about Apache Pluto, we’ve mainly discussed the most simple Portlet application that you may have. The business scenarios are more complicated then normal and they require a full knowledge about the Portlet, Portlet Life cycle and how could provide a compliant enhanced Portlet that complying with the latest standards presented at the Portlet field.

在有关Apache Pluto的介绍中,我们主要讨论了您可能拥有的最简单的Portlet应用程序。 业务场景比正常情况更为复杂,并且它们需要有关Portlet,Portlet生命周期以及如何提供符合Portlet领域最新标准的兼容增强Portlet的全面知识。

Portlet教程 (Portlet Tutorial)

This tutorial will help you getting this practice applied, while it should take you through the following subjects:

本教程将帮助您应用此实践,同时应带您完成以下主题:

  • Little Bit More about GenericPortlet

    有关GenericPortlet的更多信息
  • Little Bit More about PortletRequest & PortletResponse

    关于PortletRequest和PortletResponse的更多信息
  • Enhancing Portlet

    增强Portlet
  • Change The Portlet Title

    更改Portlet标题
  • Portlet URLs

    Portlet URL
  • doEdit & doHelp

    doEdit和doHelp
  • Summary

    摘要

有关GenericPortlet的更多信息 (Little Bit More About GenericPortlet)

As we’ve stated in the proposed introduction, our developed Portlet was extended a GenericPortlet class as it’s abstract class. According to Portlet Javadoc, GenericPortlet class provides the default implementation for the Portlet interface (Which will be discussed later on here). It provides an abstract class to be sub-classed to create Portlets.

正如我们在建议的引言中所述,我们开发的Portlet被扩展了GenericPortlet类,因为它是抽象类。 根据Portlet Javadoc,GenericPortlet类为Portlet接口提供了默认的实现(稍后将在此处进行讨论)。 它提供了一个抽象类,可以将其抽象化以创建Portlet。

A subclass of GenericPortlet should either use one of the following annotations: @ProcessAction, @ProcessEvent and @RenderMode or override at least one method of the following:

GenericPortlet的子类应使用以下注释之一: @ProcessAction@ProcessEvent@RenderMode或重写以下至少一种方法:

  • processAction: to handle action requests (will be discussed later on in this tutorial).

    processAction :处理动作请求(将在本教程后面讨论)。
  • doView: to handle render requests when the Portlet is in the View mode.

    doView :在Portlet处于查看模式时处理渲染请求。
  • doEdit: to handle render requests when the Portlet is in the Edit mode.

    doEdit :在Portlet处于“编辑”模式时处理渲染请求。
  • doHelp: to handle render requests when the Portlet is in the Help mode.

    doHelp :当Portlet处于帮助模式时,处理渲染请求。
  • init and destroy: to manage resources that are held for the life of the Servlet.

    initdestroy :管理在Servlet生命周期内保留的资源。

Normally, no need to override the render or the doDispatch methods, as the render method handles render requests, setting the title of the Portlet in the response and invoking the doDispatch.

通常,不需要重写renderdoDispatch方法,因为render方法处理渲染请求,在响应中设置Portlet的标题并调用doDispatch

In turn of the doDispatch method, the request is dispatched to one of the doView, doEdit or doHelp method depending on the Portlet mode indicated in the request. The major issue that you might find it so important, is that the Portlet is running in a multi threaded manner, so be careful when it comes to handle shared resources. Shared resources may take different forms; it’s include in-memory data such as instance or class variables, external resources like a files, database connections and network connections.

依次使用doDispatch方法,根据请求中指示的Portlet模式,将请求分派到doView,doEdit或doHelp方法之一。 您可能会发现它如此重要的主要问题是Portlet以多线程方式运行,因此在处理共享资源时要小心。 共享资源可以采取不同的形式; 它包括内存中的数据(例如实例或类变量),外部资源(例如文件),数据库连接和网络连接。

In the proposed sample that you’ve looked for at the introduction, we’ve overridden the doView method for getting message displayed. We do, some modifications against the sample itself, so you should notice the following:

在介绍中寻找的建议样本中,我们重写了doView方法来显示消息。 我们对样本本身做了一些修改,因此您应该注意以下几点:

  • We’ve eliminated the overriding of doView method, as we used @RenderMode annotation to annotate a new method called inspectRenderMode.

    我们已经消除了doView方法的重载,因为我们使用了@ RenderMode批注来注释一个名为inspectRenderMode的新方法。
  • We’ve updated the pom.xml file, so no need to get your generated WAR every time and copy it into your Tomcat’s webapp deployment folder. That’s done by using an integration-test phase that asks Ant to make that in behind of you.

    我们已经更新了pom.xml文件,因此无需每次获取生成的WAR并将其复制到Tomcat的webapp部署文件夹中。 这是通过使用一个integration-test阶段来完成的,该阶段要求Ant将其放在您的后面。
package com.journaldev.portlet;

import java.io.IOException;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.RenderMode;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class HelloWorldPortlet extends GenericPortlet {
	@RenderMode(name="View")
	public void inspectRenderMode(RenderRequest request, RenderResponse response)
			throws PortletException, IOException {
		response.getWriter().print(
				"Jounral Dev Provides you Hello World Portlet Using Annotations !");
	}

    public void init( PortletConfig config ) throws PortletException {
        super.init( config );
    }
}
<project xmlns="https://maven.apache/POM/4.0.0" xmlns:xsi="https://www.w3/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache/POM/4.0.0 https://maven.apache/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev</groupId>
	<artifactId>HelloWorldPortlet</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>HelloWorldPortlet Maven Webapp</name>
	<url>https://maven.apache</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>
	</dependencies>
	<build>
		<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>
						<phase>integration-test</phase>
						<configuration>
							<tasks>
								<!-- Use this to build and deploy the testsuite war. PORTLET_DEPLOY_DIR
									is an environmental variable pointing to the hot-deploy directory of your
									portal. You can also use -Ddeploy.dir=<path to deployment dir> on the command
									line when invoking maven: mvn -Ddeploy.dir=/pluto-1.1.4/webapps integration-test -->
								<property environment="env" />
								<property name="deploy.dir" value="${env.PORTLET_DEPLOY_DIR}" />
								<copy file="target/${pom.build.finalName}.war" tofile="${deployFolder}/${pom.build.finalName}.war" />
							</tasks>
						</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.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Here’s detailed explanation for the code listed above:

这是上面列出的代码的详细说明:

  • JSR-286 has introduced the using of annotations for controlling things were controlled normally through overriding GenericPortlet methods. We’ve used @renderMode instead of overriding doView method done like before.

    JSR-286引入了使用注释来控制通过覆盖GenericPortlet方法正常控制的事物的方法。 我们使用@renderMode而不是像以前一样重写doView方法。
  • We’ve added antrun plugin to replace the old way of deploying that we were used. Now, what’s really you want to do is to execute mvn clean integration-test package to get your WAR copied and deployed directly underneath of your Tomcat’s webapp folder. This procedure will be used henceforward.

    我们添加了antrun插件来替代以前使用的旧部署方式。 现在,您真正想要做的是执行mvn clean integration-test package以将WAR复制并直接部署在Tomcat的webapp文件夹下。 此后将使用此过程。

Finally, if you have a special kind of business that you would like to provide such a type of integration, you may make a subclass of GenericPortlet and let your developers extend it.

最后,如果您想提供这种类型的集成的特殊业务,则可以创建GenericPortlet的子类,并让您的开发人员扩展它。

关于PortletRequest和PortletResponse的更多信息 (Little Bit More About PortletRequest & PortletResponse)

The PortletRequest interface in the Portlet API represents the common functionality in an ActionRequest and RenderRequest, where both of them are actually subclass of PortletRequest.

Portlet API中的PortletRequest接口表示ActionRequest和RenderRequest中的通用功能,它们实际上都是PortletRequest的子类。

The PortletRequest provides all needed information about the user’s request (e.g request’s parameters), user’s session, Portal, Portlet application and different information about the Portlet itself.

PortletRequest提供有关用户请求的所有必需信息(例如,请求的参数),用户会话,门户网站,Portlet应用程序以及有关Portlet本身的其他信息。

The Portlet container passes all Portlet request and response objects to the Portlet whenever the Portlet get requested.

每当请求Portlet时,Portlet容器会将所有Portlet请求和响应对象传递给Portlet。

In the other side, the Portlet sends a response object back to the Portal after every request. Usually, the response object contains the content fragment of the Portlet, any requested Portlet modes or window states and several other pieces of information that get discussed later.

另一方面,Portlet在每个请求之后将响应对象发送回Portal。 通常,响应对象包含Portlet的内容片段,任何请求的Portlet模式或窗口状态以及稍后讨​​论的其他几条信息。

Actually, the Portlet developers haven’t worked with actual instances of PortletRequest and PortletResponse. However, the developers will work with RenderRequest, ActionRequest, RenderResponse and ActionResponse.

实际上,Portlet开发人员并未使用PortletRequest和PortletResponse实际实例。 但是,开发人员将使用RenderRequest,ActionRequest,RenderResponse和ActionResponse。

You may be asking about the difference between RenderRequest, RenderResponse and ActionRequest, ActionResponse and why they are categorized like that. Following figure shows you the main differences shortly before getting all detailed clarifications in the next coming sections.

您可能会询问RenderRequest,RenderResponse和ActionRequest,ActionResponse之间的区别,以及为什么要这样分类。 下图向您展示了主要的区别,不久将在接下来的各节中进行所有详细的说明。

TypeDescriptionWho’s Created It
RenderRequestThe RenderRequest represents the request sent to the Portlet to handle a render.The Portlet container creates a RenderRequest object and passes it as argument to the Portlet’s render() method.
RenderResponseThe RenderResponse defines an object to assist a Portlet in sending a response to the Portal.The Portlet container creates a RenderResponse object and passes it as argument to the Portlet’s render() method.
ActionRequestThe ActionRequest represents the request sent to the Portlet to handle an action.The Portlet container creates an ActionRequest object and passes it as argument to the Portlet’s processAction() method.
ActionResponseThe ActionResponse represents the response for the response to an action request.The Portlet container creates an ActionResponse object and passes it as argument to the Portlet’s processAction() method.
类型 描述 谁创造的
渲染请求 RenderRequest代表发送到Portlet以处理渲染的请求。 Portlet容器创建一个RenderRequest对象,并将其作为参数传递给Portlet的render()方法。
渲染响应 RenderResponse定义一个对象,以协助Portlet向门户发送响应。 Portlet容器创建一个RenderResponse对象,并将其作为参数传递给Portlet的render()方法。
动作请求 ActionRequest代表发送给Portlet来处理操作的请求。 Portlet容器创建一个ActionRequest对象,并将其作为参数传递给Portlet的processAction()方法。
动作响应 ActionResponse表示对操作请求的响应的响应。 Portlet容器创建一个ActionResponse对象,并将其作为参数传递给Portlet的processAction()方法。

As you’ve noticed in the figure shown, Portlet specification defines two different types of request/response, render’s request/response and action’s request/response are mainly the only objects you may revolve around at each time you got into a Portlet development mission.

正如您在图中所注意到的那样,Portlet规范定义了两种不同的请求/响应类型,呈现器的请求/响应和操作的请求/响应主要是您每次进入Portlet开发任务时可以围绕的唯一对象。

Such that distinction is very helpful when it comes to deal with the Portlet business, as a Portlet may be rendered at every time the contained Portal page is refreshed, while the action is getting executed at a certain specific time the user has asked for.  To make clear, following sample shows you the difference in between calling render() and processAction().

这种区别在处理Portlet业务时非常有帮助,因为Portlet可以在每次刷新所包含的Portal页面时呈现,而在用户要求的特定时间执行操作时,Portlet会在每次刷新时呈现。 为了清楚起见,下面的示例向您展示了调用render()processAction()之间的区别。

package com.journaldev.portlet;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class HelloWorldPortlet extends GenericPortlet {
	private static int renderCount = 0;
	private static int actionCount = 0;

	public void doView(RenderRequest request, RenderResponse response)
			throws PortletException, IOException {

		synchronized(this){
			renderCount++;
		}

		response.getWriter().print("<form action="+response.createActionURL()+">"
				+ "<p>Render has executed "+renderCount+"</p>"
				+ "<p>Render has executed "+actionCount+"</p>"
				+ "<input type='submit'/>"
				+ "</form>");
	}

	public void processAction(ActionRequest actionRequest, ActionResponse actionResponse){
		synchronized(this){
			actionCount++;
		}
	}

    public void init( PortletConfig config ) throws PortletException {
        super.init( config );
    }
}

Here’s detailed clarifications for code listed above:

以下是上面列出的代码的详细说明:

  • You may notice that the render counter will be incremented by one at every time you’ve got the Portal page rendered. GenericPortlet render method has delegated the control into doView that’s overrode at the HelloWorldPortlet.

    您可能会注意到,每次渲染门户页面时,渲染计数器都会增加一。 GenericPortlet呈现方法已将控件委托给在HelloWorldPortlet覆盖的doView中。
  • Action counter won’t be incremented until you’ve clicked on the submit action. GenericPortlet processAction method has delegated the control into processAction method that’s overrode at the HelloWorldPortlet.

    在您单击提交动作之前,动作计数器不会增加。 GenericPortlet processAction方法已将控件委托给在HelloWorldPortlet覆盖的processAction方法。
  • We’ve implemented both of render and action using the Portlet specification 1.0 as no annotation has been used.

    我们已经使用Portlet规范1.0实现了渲染和动作,因为未使用任何注释。
  • As being render method had called at every time you’ve got your Portal page refreshed, it’s very clear that’s why render isn’t the proper location to put any business logic you may require. If we’ve assumed that we have a business logic like mail sending putting there, so the mail would be sending at every time the Portal page getting refreshed.

    由于每次刷新门户网站页面时都会调用render方法,因此很明显,这就是为什么render不是放置您可能需要的任何业务逻辑的适当位置。 如果我们假设有诸如发送邮件的业务逻辑,那么每次刷新门户网站页面时都会发送邮件。

增强Portlet (Enhancing Portlet)

Portlet capabilities aren’t stopped here as we’re going to make some improvements to demonstrate other sides of these capabilities. Usually, the Portlet doesn’t render a plain HTML, it’s contained other resources like JavaScript, images and StyleSheets.

Portlet功能不会在这里停止,因为我们将进行一些改进以展示这些功能的其他方面。 通常,Portlet不会呈现纯HTML,而是包含其他资源,例如JavaScript,图像和StyleSheets。

Also, the view mode isn’t the only mode that you lets the end user contact with, EDIT and HELP modes are also supported by the Portlets. Mainly, you may provide an EDIT mode for a kind of configuration, meanwhile, the HELP mode is a good place to provide a helpful information about the Portlet itself.

而且,查看模式不是让最终用户联系的唯一模式,Portlet还支持EDIT和HELP模式。 主要是,您可以为一种配置提供EDIT模式,同时,HELP模式是提供有关Portlet本身的有用信息的好地方。

Beside that, providing Portlet Title isn’t so complex mission, as you can provide the default value using the portlet-info XML tag, you can also change the Title programmatically.

除此之外,提供Portlet标题并不是那么复杂的任务,因为您可以使用portlet-info XML标记提供默认值,所以还可以以编程方式更改标题。

更改Portlet标题 (Change The Portlet Title)

Generally, Portlet specification has introduced the portlet-info XML tag to allow developers specifying these information related to the Portlet’s title, short-title and keywords that may be used for categorization purpose.

通常,Portlet规范引入了portlet-info XML标记,以允许开发人员指定与可用于分类目的的Portlet标题,简称和关键字相关的这些信息。

You have three different scenarios that can you have to let the Portlet get its title, you may be using the most simplest way; define the title at the portlet.xml file within portlet-info or using a resource bundle for getting internationalization descriptive title or providing the title programmatically. Following example shows you how can you leverage two additional scenarios to make sure the desired title is set as we’ve had the first scenario previously.

您可能需要使用三种最简单的方法来使Portlet获得其标题,这是三种不同的方案。 在portlet-info内的portlet.xml文件中定义标题,或使用资源包获取国际化描述性标题或以编程方式提供标题。 下面的示例向您展示了如何利用两个其他方案来确保设置所需的标题,就像我们之前第一个方案一样。

package com.journaldev.portlet;

import java.util.Locale;
import java.util.ResourceBundle;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class TitleChangedPortlet extends GenericPortlet{
	public void doView(RenderRequest request, RenderResponse response) throws PortletException, java.io.IOException {
		response.getWriter().println("My Name Is:"+this.getPortletName());
	}

	public java.lang.String getTitle(RenderRequest request) {
		// Check whether the name of the portlet is programmaticTitleChangePortlet
		if(this.getPortletName().equals("ProgrammaticTitleChangePortlet")){
			// If it's like that, just get the defined bundle
			ResourceBundle bundle = this.getPortletConfig().getResourceBundle(new Locale("en"));
			// Retrun the string that's corresponded for anyTitle property
			return (String)bundle.getObject("anyTitle");
		}
		// else return the default, either that's defined in the portlet.xml or that's defined in the bundle
		return super.getTitle(request);
	}
}
package com.journaldev.portlet;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class HelloWorldPortlet extends GenericPortlet {
	private static int renderCount = 0;
	private static int actionCount = 0;

	public void doView(RenderRequest request, RenderResponse response)
			throws PortletException, IOException {

		synchronized(this){
			renderCount++;
		}

		response.getWriter().print("<form action="+response.createActionURL()+">"
				+ "<p>Render has executed "+renderCount+"</p>"
				+ "<p>Action has executed "+actionCount+"</p>"
				+ "<input type='submit'/>"
				+ "</form>");
	}

	public void processAction(ActionRequest actionRequest, ActionResponse actionResponse){
		synchronized(this){
			actionCount++;
		}
	}

    public void init( PortletConfig config ) throws PortletException {
        super.init( config );
    }
}

portlet.xml

portlet.xml

<?xml version="1.0" encoding="UTF-8"?>

<portlet-app xmlns="https://java.sun/xml/ns/portlet/portlet-app_1_0.xsd"
	version="1.0" xmlns:xsi="https://www.w3/2001/XMLSchema-instance"
	xsi:schemaLocation="https://java.sun/xml/ns/portlet/portlet-app_1_0.xsd
                        https://java.sun/xml/ns/portlet/portlet-app_1_0.xsd">

	<portlet>
		<description>Write here a short description about your portlet.</description>
		<portlet-name>HelloWorldPortlet</portlet-name>
		<display-name>HelloWorldPortlet Portlet</display-name>

		<portlet-class>com.journaldev.portlet.HelloWorldPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
		</supports>

		<portlet-info>
			<title>Title Is Set Using Simplest Way Portlet-Info XML Tag</title>
			<short-title>Hello World</short-title>
			<keywords>Hello,pluto</keywords>
		</portlet-info>

	</portlet>

	<portlet>
		<description>It's a Portlet that's setting title using Resource Bundle</description>
		<portlet-name>ResourceBundleTitleChangePortlet</portlet-name>
		<display-name>ResourceBundleTitleChangePortlet</display-name>

		<portlet-class>com.journaldev.portlet.TitleChangedPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
		</supports>

		<supported-locale>en</supported-locale>

		<resource-bundle>message</resource-bundle>

	</portlet>

	<portlet>
		<description>It's a Portlet that's setting title programmatically</description>
		<portlet-name>ProgrammaticTitleChangePortlet</portlet-name>
		<display-name>ProgrammaticTitleChangePortlet</display-name>

		<portlet-class>com.journaldev.portlet.TitleChangedPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
		</supports>

		<supported-locale>en</supported-locale>

		<resource-bundle>message</resource-bundle>		

	</portlet>	

</portlet-app>

message.properties

message.properties

javax.portlet.title=Title Is Set By Resource Bundle
anyTitle=Title Is Set Programmatically

Here’s detailed explanation for code shown above:

这是上面显示的代码的详细说明:

  • It’s possible to use the same Portlet with different names. We’ve used TitleChangedPortlet twice; once under ResourceBundleTitleChangePortlet name and second with ProgrammaticTitleChangePortlet.

    可以将同一Portlet使用不同的名称。 我们已经两次使用TitleChangedPortlet了; 一次在ResourceBundleTitleChangePortlet名称下,第二次在ProgrammaticTitleChangePortlet
  • HelloWorldPortlet uses the title that’s defined within the portlet.xml file.

    HelloWorldPortlet使用在portlet.xml文件中定义的标题。
  • ResourceBundleTitleChangePortlet uses the title that’s defined inside resource bundle. As you’ve noticed you must use the well-known constants as they must be compliant with Portlet specification to be considered. Following below the constants for the Portlet level resource bundle:

    ResourceBundleTitleChangePortlet使用在资源束中定义的标题。 正如您已经注意到的那样,必须使用众所周知的常量,因为它们必须符合Portlet规范才能被考虑。 以下是Portlet级别资源束的常量:
ConstantDescription
javax.portlet.titleThe,title that should be displayed in the titlebar of,this portlet. Only one title per locale is allowed. Note,that this title may be overrided by the portal or,programmatically by the portlet.
javax.portlet.short-titleA short,version of the title that may be used for,devices with limited display,capabilities. Only one,short title per locale is allowed.
javax.portlet.keywordsKeywords,describing the functionality of the portlet.,Portals that allow users to search for portlets based,on keywords may use these keywords. Multiple,keywords per locale are allowed, but must be,separated by commas ‘,’.
javax.portlet.descriptionDescription,of the portlet.
javax.portlet.display-nameName,under which this portlet is displayed at,deployment time or to tools. The display name need,not be unique.
javax.portlet.app.custom-portletmode.<,name>.decoration-nameDecoration,name for the portlet managed custom,portlet mode .
不变 描述
javax.portlet.title 该portlet的标题栏中应显示的标题。 每个语言环境仅允许一个标题。 注意,此标题可能会被门户网站覆盖,或者被portlet编程覆盖。
javax.portlet.short-title 可能用于显示能力有限的设备的标题的简短版本。 每个区域仅允许一个简短的标题。
javax.portlet.keywords 关键字,描述portlet的功能。允许用户基于关键字搜索portlet的portals可以使用这些关键字。 每个区域允许使用多个关键字,但必须用逗号“,”分隔。
javax.portlet.description Portlet的描述。
javax.portlet.display-name 部署时或工具上显示此portlet的名称。 显示名称不必唯一。
javax.portlet.app.custom-portletmode。<,名称>。装饰名称 装饰,portlet管理的定制的名称,portlet模式。
  • Typically, you should define your resources within the same package as your Portlet to make sure every Portlet has used its relevant messages.

    通常,您应该在与Portlet相同的包中定义资源,以确保每个Portlet都使用了其相关消息。
  • ProgrammaticTitleChangePortlet uses the title that’s changed programmatically. Even that we can provide a static text, but we’ve provide another use of bundle messages.

    ProgrammaticTitleChangePortlet使用以编程方式更改的标题。 即使我们可以提供静态文本,也可以提供捆绑消息的另一种用法。
  • In case you need to provide the title programmatically, you must do override for the getTitle() method that’s already inherited from the GenericPortlet.

    如果需要以编程方式提供标题,则必须对已经从GenericPortlet继承的getTitle()方法进行重写。
  • If you’re used resource bundle for getting Portlet’s accompanies text defined, you must make sure that you have your resource files (e.g message.properties) located into your class path as you’ve defined it in the portlet.xml.

    如果使用资源包来定义Portlet的伴随文本,则必须确保已在portlet.xml定义资源文件(例如message.properties)到类路径中。
  • Another way to change the title programmatically, you can invoke setTitle() against renderResponse object inside any delegated method (i.e doView, doEdit and doHelp).

    以编程方式更改标题的另一种方法是,您可以在任何委托的方法(即doView,doEdit和doHelp)内针对renderResponse对象调用setTitle() )。

Portlet URL (Portlet URLs)

As we knew, the Portlet isn’t a standalone resource like Servlet that can be accessed through a well defined URL (i.e https://servername:port/web-context/servlet-mapping). The Portlet can be accessed only via using a Portal page, as it’s reside there.

众所周知,Portlet不是像Servlet这样的独立资源,可以通过定义良好的URL(即https:// servername:port / web-context / servlet-mapping)进行访问。 Portlet只能通过位于其上的Portal页面进行访问。

However, a Portlet can create a URL that targets itself in the Portlet container (i.e by clicking a link or submitting a form) the result is a new client request to the Portal targeted to the Portlet as we already did when submitting HelloWorldPortlet above.

但是,Portlet可以在Portlet容器中创建一个以自身为目标的URL(即,通过单击链接或提交表单),结果是向目标门户网站的Portal发送了新的客户端请求,就像我们在上面提交HelloWorldPortlet时所做的那样。

Anyway, these URL’s are called portlet URLs. In that, a Portlet URL will reference the instance of the portlet in the Portal page (In case you have two different Portlets referenced the same Portlet class, they will have different Portlet URLs).

无论如何,这些URL被称为portlet URL。 这样,Portlet URL将在门户页面中引用该Portlet的实例(如果您有两个不同的Portlet引用了相同的Portlet类,则它们将具有不同的Portlet URL)。

Creation of these URLs is a Portlet container responsibility as it’s also parsed the Portlet URL into parameters for the Portlet request. The Portlet creates PortletURL objects that represent Portlet URLs. The Portlet itself can use one of two methods on the RenderResponse class to create these PortletURL objects:

这些URL的创建是Portlet容器的职责,因为它还将Portlet URL解析为Portlet请求的参数。 Portlet将创建代表Portlet URL的PortletURL对象。 Portlet本身可以使用RenderResponse类上的两个方法之一来创建这些PortletURL对象:

  • createActionURL(): Is used to make action URLs for HTML forms or links. These actions URLs are useful for processing actions (i.e Portlet’s state modifications) on the Portlet (i.e calling of processAction() overrode method against your Portlet).

    createActionURL() :用于为HTML表单或链接创建操作URL。 这些操作URL对于处理Portlet上的操作(即,对Portlet调用processAction()覆盖方法processAction()非常有用。
  • createRenderURL(): Is used to make render URLs for any tasks that doesn’t contain Portlet’s state modifications.

    createRenderURL() :用于为不包含Portlet状态修改的任何任务创建渲染URL。

Even that you can add Portlet URLs into your content with no parameters, but you can also set your parameters on a Portlet URLs by invoking setParameter(name, value) against your PortletURL object that’s returned once you invoked createActionURL() or createRenderURL().

即使您可以不带任何参数将Portlet URL添加到您的内容中,但是您也可以通过调用一次调用createActionURL()createRenderURL()返回的PortletURL对象的setParameter(name, value)在Portlet URL上设置参数。

More clarifications and samples would be delivered in the next coming tutorial that’s aimed to cover all technical specifics for accompanies render’s request/response and action’s request/response and how’s the parameter can be set and consumed after then.

在下一个教程中将提供更多的说明和示例,该教程旨在涵盖渲染器的请求/响应和操作的请求/响应的所有技术细节,以及如何在此之后设置和使用该参数。

doEdit和doHelp方法 (doEdit & doHelp Methods)

Practically, we’ve not used doEdit method for any type of normal rendition, it’s mainly used for specifying the Portlet’s states for controlling Portlte’s behavior at normal rendition invocation that’s done using doView.

实际上,我们没有将doEdit方法用于任何类型的普通表示形式,它主要用于指定Portlet的状态,以控制使用doView完成的普通表示形式调用时Portlte的行为。

At the same time, some Portlets have provided so complicated business, the user may need some sort of help to get the Portlet working properly and for that purpose the doHelp is given.

同时,一些Portlet提供了如此复杂的业务,用户可能需要某种帮助才能使Portlet正常工作,并为此提供了doHelp

Defining the Portlet’s modes isn’t so complex mission, all what you need for is to use portlet-mode within supports Tag for specifying which modes the Portlet has supported. Following example shows you the way that in which you are able of seeing Edit & Help modes.

定义Portlet的模式并不是那么复杂的任务,您所需要做的就是在support标签中使用portlet-mode来指定Portlet支持的模式。 以下示例向您展示了查看“编辑和帮助”模式的方式。

package com.journaldev.portlet;

import java.util.Locale;
import java.util.ResourceBundle;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class TitleChangedPortlet extends GenericPortlet{

	public void doView(RenderRequest request, RenderResponse response) throws PortletException, java.io.IOException {
		response.getWriter().println("My Name Is:"+this.getPortletName());
	}

	public void doEdit(RenderRequest request, RenderResponse response) throws PortletException, java.io.IOException {
		response.getWriter().println("Edit Mode On Portlet Name :"+this.getPortletName());
	}

	public void doHelp(RenderRequest request, RenderResponse response) throws PortletException, java.io.IOException {
		response.getWriter().println("Help Mode On Portlet Name :"+this.getPortletName());
	}

	public java.lang.String getTitle(RenderRequest request) {
		// Check whether the name of the portlet is programmaticTitleChangePortlet
		if(this.getPortletName().equals("ProgrammaticTitleChangePortlet")){
			// If it's like that, just get the defined bundle
			ResourceBundle bundle = this.getPortletConfig().getResourceBundle(new Locale("en"));
			// Retrun the string that's corresponded for anyTitle property
			return (String)bundle.getObject("anyTitle");
		}
		// else return the default, either that's defined in the portlet.xml or that's defined in the bundle
		return super.getTitle(request);
	}
}

portlet.xml

portlet.xml

<?xml version="1.0" encoding="UTF-8"?>

<portlet-app xmlns="https://java.sun/xml/ns/portlet/portlet-app_1_0.xsd"
	version="1.0" xmlns:xsi="https://www.w3/2001/XMLSchema-instance"
	xsi:schemaLocation="https://java.sun/xml/ns/portlet/portlet-app_1_0.xsd
                        https://java.sun/xml/ns/portlet/portlet-app_1_0.xsd">

	<portlet>
		<description>Write here a short description about your portlet.</description>
		<portlet-name>HelloWorldPortlet</portlet-name>
		<display-name>HelloWorldPortlet Portlet</display-name>

		<portlet-class>com.journaldev.portlet.HelloWorldPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
		</supports>

		<portlet-info>
			<title>Title Is Set Using Simplest Way Portlet-Info XML Tag</title>
			<short-title>Hello World</short-title>
			<keywords>Hello,pluto</keywords>
		</portlet-info>

	</portlet>

	<portlet>
		<description>It's a Portlet that's setting title using Resource Bundle</description>
		<portlet-name>ResourceBundleTitleChangePortlet</portlet-name>
		<display-name>ResourceBundleTitleChangePortlet</display-name>

		<portlet-class>com.journaldev.portlet.TitleChangedPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
			<portlet-mode>EDIT</portlet-mode>
			<portlet-mode>HELP</portlet-mode>
		</supports>

		<supported-locale>en</supported-locale>

		<resource-bundle>message</resource-bundle>

	</portlet>

	<portlet>
		<description>It's a Portlet that's setting title programmatically</description>
		<portlet-name>ProgrammaticTitleChangePortlet</portlet-name>
		<display-name>ProgrammaticTitleChangePortlet</display-name>

		<portlet-class>com.journaldev.portlet.TitleChangedPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
			<portlet-mode>EDIT</portlet-mode>
			<portlet-mode>HELP</portlet-mode>
		</supports>

		<supported-locale>en</supported-locale>

		<resource-bundle>message</resource-bundle>		

	</portlet>	

</portlet-app>

Here’s detailed explanation for code listed above:

这是上面列出的代码的详细说明:

  • You must define the modes that you want to make your Portlet support for.

    您必须定义支持Portlet的方式。
  • HelloWorldPortlet does support View mode as it’s Portlet with no Edit or Help.

    HelloWorldPortlet确实支持查看模式,因为它是Portlet,没有“编辑”或“帮助”。
  • Other two Portlets have defined all of modes are available.

    另外两个Portlet定义了所有可用模式。
  • Portal provides you the mode user interface for toggling between modes that are supported by the Portlet.

    Portal提供了模式用户界面,用于在Portlet支持的模式之间切换。

摘要 (Summary)

Portlet specification provide vast amount of APIs that you have to learn to be Portlet developer. This tutorial aimed to provide you additional details about GenericPortlet, PortletRequest, PortletResponse and others. Contribute us by commenting below and find downloaded source code.

Portlet规范提供了成为Portlet开发人员必须学习的大量API。 本教程旨在为您提供有关GenericPortlet,PortletRequest,PortletResponse等的更多详细信息。 通过在下面评论来贡献我们,并找到下载的源代码。

Download Portlet Basics and Enhancements Project 下载Portlet基础和增强项目

翻译自: https://www.journaldev/4663/java-portlet-example-tutorial

portlet示例

更多推荐

portlet示例_Java Portlet示例教程