上一篇日誌利用推送源週期性地向訂閱了某一事件的全部網頁端推送信息,但怎麼實現向特定的某一個用戶推送信息呢,想象一個網絡聊天室,怎麼向單獨的一個好友私聊呢。問題的關鍵就是那個SessionID,Pushlet默認是用java.rmi.server.UID參數的隨機字符串做爲會話標誌,這就形成咱們無法跟一個特色的用戶對應上,也就是說客戶必須在joinListen的時候提供一個他的ID,就像登錄qq時,輸入用戶名同樣。javascript
好了,這裏就列出怎麼修改相關代碼,實現上述功能。html
一樣,首先用MyEclipse新建一個web工程,我這裏命名爲PushletTest2。不一樣的是,咱們不引用pushlet.jar包了,由於咱們要更改源碼,在下載pushlet的時候裏面就包含源代碼了,最外層是nl包,加入個人工程的src裏。好了,加進去以後會報錯,將log4j.jar加入引用就行了。。以後,一樣別忘了把pushlet.properties和sources.properties加入WebRoot/WEN-INF下。工程結構以下:前端
FirPush.java是本身寫的一個觸發推送動做的類,它是一個servlet,請求該servlet就觸發向特定的用戶推送信息的動做(固然,怎麼觸發推送動做還有不少種形式)。java
web.xml代碼以下:web
- <span style="font-size: x-small;"><?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <servlet>
- <servlet-name>pushlet</servlet-name>
- <servlet-class>nl.justobjects.pushlet.servlet.Pushlet</servlet-class>
- <load-on-startup>3</load-on-startup>
- </servlet>
- <servlet>
- <servlet-name>FirePush</servlet-name>
- <servlet-class>com.mysrc.FirePush</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>pushlet</servlet-name>
- <url-pattern>/pushlet.srv</url-pattern>
- </servlet-mapping>
- <servlet-mapping>
- <servlet-name>FirePush</servlet-name>
- <url-pattern>/FirePush</url-pattern>
- </servlet-mapping>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- </web-app></span>
Ok,接下來就是要進行修改了,首先打開ajax-pushlet-client.js。PL對象,在它的最開始添加一個屬性userId:'', ,由於分析ajax-pushlet-client.js以後會發現,全部的請求都是get方式,也就是說是將請求參數添加到url裏的,咱們要作的是在進行join請求的時候將userId加到url上。找到PL的_doRequest,它是一個函數,全部的請求都是經過調用它發出的,找到var url = PL.pushletURL + '?p_event=' + anEvent;這一行,這兒就是在構造請求參數,在它的後面加入代碼:ajax
- if (anEvent == 'join' || anEvent == 'join-listen') { url = url + '&userId=' + PL.userId;
- }
好了,ajax-pushlet-client.js的修改就完成了。網絡
接下來是test.html:session
- <html>
- <head>
- <script type="text/javascript" src="ajax-pushlet-client.js"></script>
- <script type="text/javascript">
- PL.userId='piero';
- PL._init();
- PL.joinListen('myevent1');
- function onData(event) {
- alert(event.get("key1"));
- }
- </script>
- </head>
- <body>
- This is pushlet test page....<br>
- </body>
- </html>
而後就是修改pushlet的java源代碼,找到nl.justobjects.pushlet.core包下的SessionManager類,將它的createSession方法改爲:app
- public Session createSession(Event anEvent) throws PushletException {
- // Trivial
- //return Session.create(createSessionId());
- return Session.create(anEvent.getField("userId", "visitor"));
- }
這兒就使得創建的session的id是發送過來的userId,而不是一個隨機字符串。getField的第二個參數是當得不到請求參數userId的值的時候設定的默認值。jsp
好了,全部的準備工做都完成了,接下來就是經過userId給特色的用戶推送信息了。
FirePush.java代碼以下:
- package com.mysrc;
-
- import java.io.IOException;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- import nl.justobjects.pushlet.core.Dispatcher;
- import nl.justobjects.pushlet.core.Event;
- import nl.justobjects.pushlet.core.SessionManager;
-
- public class FirePush extends HttpServlet {
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- myUnicast();
- //myMulticast();
- //myBroadcast();
- }
- private void myUnicast()
- {
- if(SessionManager.getInstance().hasSession("piero")){
- Event event = Event.createDataEvent("myevent1");
- event.setField("key1", "houhou_yesttttt....");
- Dispatcher.getInstance().unicast(event,"piero"); //向ID爲piero的用戶推送
-
- System.out.println("success....");
- }
- else {
- System.out.println("piero do not login....%%%%%%%%%%%%");
- }
- }
- private void myMulticast()
- {
- Event event = Event.createDataEvent("myevent1");
- event.setField("key1", "houhou....");
- Dispatcher.getInstance().multicast(event); //向全部和myevent1名稱匹配的事件推送
-
- System.out.println("wa success....");
- }
- private void myBroadcast()
- {
- Event event = Event.createDataEvent("myevent1"); //向全部的事件推送,不要求和這兒的myevent1名稱匹配
- event.setField("key1", "dig hole....");
- Dispatcher.getInstance().broadcast(event);
-
- System.out.println("asw success....");
- }
- }
這兒主要利用了dispatcher的unicat/multicat/broadcast方法。
好了,值得一提的是在ajax-pushlet-client.js有publish方法,也就是上面提到的觸發信息推送動做,其實徹底能夠在前端調用這個js的publish函數向訂閱了某事件的全部網頁推送信息。test2.html代碼以下:
- <html>
- <head>
- <script type="text/javascript" src="ajax-pushlet-client.js"></script>
- <script type="text/javascript">
- PL.userId='juvenh';
- PL._init();
-
- PL.joinListen('event223');
- function onData(event) {
- alert(event.get("eventVal"));
- }
-
- function sendnews(){
- //PL.publish("myevent1","key1=dlut&ba=ls");
- p_publish('myevent1', 'key1', 'dlut', 'ba', 'ls');
- }
- </script>
- </head>
-
- <body>
- This is my JSP page. <br>
- <input type = "button" value="發消息" onclick="sendnews()"/>
- </body>
- </html>
上面代碼中的PL.publish和p_publish徹底等效,查看p_publish的代碼,其實也是構造請求url。這兒的publish方法只能向訂閱某一事件的全部網頁推送消息,也即等同於multicast方法,沒法向某一個特定的用戶推送,解決方法仍是向上面那樣修改pushlet的java源代碼,在nl.justobjects.pushlet.core包下的Controller.java中的protected void doPublish(Command aCommand);函數,看一下就會發現,這兒就是調用了dispacher的multicast函數,這兒改爲unicast,前提是上面的js的publish裏提供了userId。