Portlet事件也是JSR-286(Portlet 2.0新添加的一种Portlet之间交互的方式),比起Public Render参数的交互方式,它可以传递大对象而不只局限于字符串或者字符串数组,而且可以启用cache.比起PortletSession,它又支持跨Portlet应用的Portlet交互.
(我惊叹:果然事件驱动的思想深入人心并且无处不在啊,已经在无数地方看到了事件驱动的强大能力了)
步骤1:先定义一个Event类,它必须实现Serializable接口, 因为有可能要被远程的Portlet容器里面的Portlet所接受,所以要在网络传输因此要被序列化,序列化的方式就是用JAXB将其转为XML文档然后在网络上传输。
这个@XmlRootElement表示这个事件将以xml的形式被Portlet容器发布出去
- import chapter11.code.listing.domain.Book;
- import javax.xml.bind.annotation.XmlRootElement;
- @XmlRootElement
- public class BookAddedEvent implements Serializable
- private static final long serialVersionUID = ...
- private String name;
- private String author;
- private Long isbnNumber;
- private String category;
- public BookAddedEvent() {
- //-- do nothing
- }
- public BookAddedEvent(Book book) {
- this.name = book.getName();
- this.author = book.getAuthor();
- this.category = book.getCategory();
- this.isbnNumber = book.getIsbnNumber();
- }
- ...
- }
然后这个Book添加的事件就会转为如下的XML序列化的文档并且在网络上传输:
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <bookAddedEvent>
- <author>Ramnivas Laddad</author>
- <category>Java</category>
- <isbnNumber>1933988053</isbnNumber>
- <name>AspectJ in Action, Second Edition</name>
- </bookAddedEvent>
步骤2:在发送者Portlet的方法中添加这个事件对象:
- public class BookCatalogPortlet extends GenericPortlet {
- @ProcessAction(name = "addBookAction")
- public void addBook(...)... {
- ...
- Book book = new Book(category, name, author, Long
- .valueOf(isbnNumber));
- //调用bookService的addBook方法来添加这本书
- bookService.addBook(book);
- //同时,创建一个QualifiedName来代表事件的唯一名称(有了某个名字空间)
- QName eventName = new QName(
- "http://www.mynamespace.com", "bookAddedEvent"
- );
- //在response对象中,将Event的内容和Event的QName进行绑定
- response.setEvent(eventName, new BookAddedEvent(book);
- ...
- }
步骤3:在portlet.xml的<portlet>中声明这个portlet所支持的发布事件,并且在portlet应用级别显式的定义它所发布的事件<supported-publishing-event>(事件的qname关联到具体的事件类类型)
- <portlet-app...>
- <portlet>
- <portlet-name>bookCatalog</portlet-name>
- <portlet-class>
- chapter11.code.listing.base.BookCatalogPortlet
- </portlet-class>
- ...
- <supported-publishing-event>
- <qname xmlns:n="http://www.mynamespace.com">
- n:bookAddedEvent</qname>
- </supported-publishing-event>
- </portlet>
- <event-definition>
- <qname xmlns:n="http://www.mynamespace.com">
- n:bookAddedEvent</qname>
- <value-type>chapter11.code.listing.base.
- BookAddedEvent</value-type>
- </event-definition>
- ...
- </portlet-app>
步骤4;在接收者Portlet中,用代码显示的从事件中获取所需要的内容并且处理:
- public class RecentlyAddedBookPortlet extends GenericPortlet ...
- @ProcessEvent(qname=
- "{http://www.mynamespace.com}bookAddedEvent")
- public void processAddedBookEvent(EventRequest
- request, EventResponse eventResponse) throws...{
- Event event = request.getEvent();
- BookAddedEvent bookAddedEvent =
- (BookAddedEvent)event.getValue();
- eventResponse.setRenderParameter("category",
- bookAddedEvent.getCategory());
- eventResponse.setRenderParameter("name",
- bookAddedEvent.getName());
- eventResponse.setRenderParameter("author",
- bookAddedEvent.getAuthor());
- eventResponse.setRenderParameter("isbnNumber",
- String.valueOf(bookAddedEvent.getIsbnNumber()));
- }
- }
- <portlet-app...>
- <portlet>
- <portlet-name>recentBook</portlet-name>
- <portlet-class>
- chapter11.code.listing.base.RecentlyAddedBookPortlet
- </portlet-class>
- ...
- <supported-processing-event>
- <qname xmlns:n="http://www.mynamespace.com">
- n:bookAddedEvent</qname>
- </supported-processing-event>
- </portlet>
- <event-definition>
- <qname xmlns:n="http://www.mynamespace.com">
- n:bookAddedEvent</qname>
- <value-type>chapter11.code.listing.base.
- BookAddedEvent</value-type>
- </event-definition>
- ...
- </portlet-app>