锁定老帖子 主题:后台向前台消息推送求解决方案
精华帖 (0) :: 良好帖 (0) :: 新手帖 (19) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2011-10-20
叫我Fox 写道 walldr2161 写道 说说想法不一定能实现:监听数据库,其实也就是AOP监听insert、delete、update等,
帖子一个 希望有所帮助 http://www.open-china.net/blog/8940.html 正解 使用数据库调用外部程序或者数据库向某个url发送请求来告知数据库本身数据的变化,这个跟楼主的要求不沾边儿,下面是我写的一个平常的存储过程,作用是访问外部url,告知数据库本身的变化: -- Author: George <gblog.iteye.com> CREATE OR REPLACE PROCEDURE OracleMessagePushTool(p_message IN VARCHAR2,p_returnValue OUT VARCHAR2) as v_text varchar2(100) := '这里是向url传递的参数值';--不能有空白 req utl_http.req; resp utl_http.resp; value VARCHAR2(2048); -- 访问url后,url的返回值 BEGIN -- Author: George <gblog.iteye.com> v_text := replace(p_message,'%','%25'); v_text := replace(utl_encode.text_encode(v_text), '=', '%'); req := utl_http.begin_request('http://192.168.2.109:9090/george-app/GlobalServerPush.gaction?doType=pushMessageFromDb&message=' || v_text); utl_http.set_header(req, 'Content-Type', 'text/html; charset=UTF-8'); resp := utl_http.get_response(req); LOOP utl_http.read_line(resp, value, TRUE); p_returnValue := p_returnValue || value; -- dbms_output.put_line(value); END LOOP; utl_http.end_response(resp); EXCEPTION WHEN utl_http.end_of_body THEN utl_http.end_response(resp); END OracleMessagePushTool; 这种技术在Oracle中是很平常和常用的场景,和楼主的要求风马牛不相及。 楼主的需求是从server端通知消息到client端浏览器,可以是广播到所有的浏览器,可以是单独对某个浏览器进行主动推送消息。 我一般是使用Pushlet来实现,这里是官方demo 但是Pushlet也不能很好地解决这类应用所面临的问题,最大的问题是效率问题。 楼主如果有足够的时间,可以研究一下gmail中的gtalk的消息推送实现。 |
|
返回顶楼 | |
发表时间:2011-10-20
websocket
给你个例子 server用python写的, 你可以改成mina实现 import asyncore import struct import hashlib import socket class WebSocketConnection(asyncore.dispatcher_with_send): def __init__(self, conn, server): asyncore.dispatcher_with_send.__init__(self, conn) self.server = server self.server.sessions.append(self) self.readystate = 'connection' self.buffer = '' def handle_read(self): data = self.recv(1024) self.buffer += data if self.readystate == 'connection': self.parse_connection() elif self.readystate == 'open': self.parse_frametype() def handle_close(self): self.server.sessions.remove(self) self.close() def parse_connection(self): header_end = self.buffer.find('\r\n\r\n') if header_end == -1: return else: header = self.buffer[:header_end] # ------------------------------------- print header # ------------------------------------- self.buffer = self.buffer[header_end + 4:] header_lines = header.split('\r\n') headers = {} method, path, protocol = header_lines[0].split(' ') if method != 'GET' or protocol != 'HTTP/1.1' or path[0] != '/': self.terminate() return for line in header_lines[1:]: key, value = line.split(': ') headers[key] = value headers['Location'] = 'ws://' + headers['Host'] + path self.readystate = 'open' self.handler = self.server.handlers.get(path, None)(self) if 'Sec-WebSocket-Key1' in headers.keys(): self.send_server_handshake_76(headers) else: return def terminate(self): self.readystate = 'closed' self.close() def send_server_handshake_76(self, headers): key1 = headers['Sec-WebSocket-Key1'] key2 = headers['Sec-WebSocket-Key2'] key3, self.buffer = self.buffer[:8], self.buffer[8:] response_token = self.calculate_key(key1, key2, key3) self.send_bytes('HTTP:/1.1 101 Web Socket Protocol Handshake\r\n') self.send_bytes('Upgrade: WebSocket\r\n') self.send_bytes('Connection: Upgrade\r\n') self.send_bytes('Sec-WebSocket-Origin: %s\r\n' % headers['Origin']) self.send_bytes('Sec-WebSocket-Location: %s\r\n' % headers['Location']) if 'Sec-WebSocket-Protocol' in headers: protocol = headers['Sec-WebSocket-Protocol'] self.send_bytes('Sec-WebSocket-Protocol: %s\r\n' % protocol) self.send_bytes('\r\n') self.send_bytes(response_token) def calculate_key(self, key1, key2, key3): num1 = int(''.join([digit for digit in list(key1) if digit.isdigit()])) spaces1 = len([char for char in list(key1) if char == ' ']) num2 = int(''.join([digit for digit in list(key2) if digit.isdigit()])) spaces2 = len([char for char in list(key2) if char == ' ']) combined = struct.pack('>II', num1 / spaces1, num2 / spaces2) + key3 md5 = hashlib.new('md5') md5.update(combined) return md5.digest() def parse_frametype(self): while len(self.buffer): type_byte = self.buffer[0] if type_byte == '\x00': if not self.parse_textframe(): return def parse_textframe(self): terminator_index = self.buffer.find('\xFF') if terminator_index != -1: frame = self.buffer[1:terminator_index] self.buffer = self.buffer[terminator_index + 1:] s = frame.decode('utf-8') self.handler.dispatch(s) return True else: return False def send(self, s): if self.readystate == 'open' : self.send_bytes('\x00') self.send_bytes(s.encode('utf-8')) self.send_bytes('\xFF') def send_bytes(self, bytes): asyncore.dispatcher_with_send.send(self, bytes) class EchoHandler(object): def __init__(self, conn): self.conn = conn def dispatch(self, data): self.conn.send('echo: ' + data) class BroadcastHandler(object): def __init__(self, conn): self.conn = conn def dispatch(self, data): for session in self.conn.server.sessions: session.send(data) class WebSocketServer(asyncore.dispatcher): def __init__(self, port=2000, handlers=None): asyncore.dispatcher.__init__(self) self.handlers = handlers self.sessions = [] self.port = port self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind(('', port)) self.listen(5) def handle_accept(self): conn, addr = self.accept() session = WebSocketConnection(conn, self) if __name__ == '__main__': print 'Start WebSocket Server' WebSocketServer(handlers={'/broadcast':BroadcastHandler}) asyncore.loop() client 就是html的, 记住,需要html5 支持, chrome ,ff 4+ 都可以运行 ip 地址自己改一下。 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script> var url = 'ws://10.45.28.100:2000/broadcast'; var w = new WebSocket(url) w.onmessage = function(e) { document.getElementById("output").innerHTML += (e.data + '\n'); } window.onload = function() { document.getElementById("sendButton").onclick = function() { var b = w.send(document.getElementById("inputMessage").value); if (!b) { alert('network error!'); } } } </script> </head> <body> <input type="text" id="inputMessage" , value="Hello Websocket!"> <button id="sendButton">Send</button> <pre id="output"></pre> </body> </html> |
|
返回顶楼 | |
发表时间:2011-10-20
dwr推技术
|
|
返回顶楼 | |
发表时间:2011-10-20
推荐这个,
http://cometd.org/ 我也在研究这个 |
|
返回顶楼 | |
发表时间:2011-10-20
最后修改:2011-10-20
zp840566233 写道 dwr推技术
理由?demo? 经常看到一些人这样回答问题: 引用 甲问:如何同时兼顾 url.xxx?param=value 格式的url和 url/param/value这样的RESTful URL的参数映射到controller method?
乙答:google 丙答:百度 丁答:必应 戊答:这样做很麻烦 己答:这样很容易实现啊 庚答:这样的系统太多了 辛答:我做过类似的系统 壬答:很好实现,使用xxx 癸答:这样的问题也来提问,先搜索历史帖子 这样的回答其实是相当于没有回答啊。 还有我那个Struts2标签的帖子,我使用代码举例Struts2标签模块的类之间的环环相扣的缠联,下面几个“高手”异口同声地说:“不麻烦啊”、“不是环环相扣啊”、“只关心Component就可以了啊”诸如此类…… 其实我怀疑他们有没有真正动手试过?没有自己动手就凭主观臆断在那里下结论,这种回帖有意义么? |
|
返回顶楼 | |
发表时间:2011-10-20
comet
|
|
返回顶楼 | |
发表时间:2011-10-20
george_space 写道 叫我Fox 写道 walldr2161 写道 说说想法不一定能实现:监听数据库,其实也就是AOP监听insert、delete、update等,
帖子一个 希望有所帮助 http://www.open-china.net/blog/8940.html 正解 使用数据库调用外部程序或者数据库向某个url发送请求来告知数据库本身数据的变化,这个跟楼主的要求不沾边儿,下面是我写的一个平常的存储过程,作用是访问外部url,告知数据库本身的变化: -- Author: George <gblog.iteye.com> CREATE OR REPLACE PROCEDURE OracleMessagePushTool(p_message IN VARCHAR2,p_returnValue OUT VARCHAR2) as v_text varchar2(100) := '这里是向url传递的参数值';--不能有空白 req utl_http.req; resp utl_http.resp; value VARCHAR2(2048); -- 访问url后,url的返回值 BEGIN -- Author: George <gblog.iteye.com> v_text := replace(p_message,'%','%25'); v_text := replace(utl_encode.text_encode(v_text), '=', '%'); req := utl_http.begin_request('http://192.168.2.109:9090/george-app/GlobalServerPush.gaction?doType=pushMessageFromDb&message=' || v_text); utl_http.set_header(req, 'Content-Type', 'text/html; charset=UTF-8'); resp := utl_http.get_response(req); LOOP utl_http.read_line(resp, value, TRUE); p_returnValue := p_returnValue || value; -- dbms_output.put_line(value); END LOOP; utl_http.end_response(resp); EXCEPTION WHEN utl_http.end_of_body THEN utl_http.end_response(resp); END OracleMessagePushTool; 这种技术在Oracle中是很平常和常用的场景,和楼主的要求风马牛不相及。 楼主的需求是从server端通知消息到client端浏览器,可以是广播到所有的浏览器,可以是单独对某个浏览器进行主动推送消息。 我一般是使用Pushlet来实现,这里是官方demo 但是Pushlet也不能很好地解决这类应用所面临的问题,最大的问题是效率问题。 楼主如果有足够的时间,可以研究一下gmail中的gtalk的消息推送实现。 你说的这个Oracle的DEMO也就是监听数据库的变化,确实和LZ所提的需求风马牛不相及,内部请求意易不大。。不过触发器的效率还是蛮高的。至于Pushlet,去看看去。谢谢分享。。 |
|
返回顶楼 | |
发表时间:2011-10-20
最后修改:2011-10-20
Jclick 写道 george_space 写道 叫我Fox 写道 walldr2161 写道 说说想法不一定能实现:监听数据库,其实也就是AOP监听insert、delete、update等,
帖子一个 希望有所帮助 http://www.open-china.net/blog/8940.html 正解 使用数据库调用外部程序或者数据库向某个url发送请求来告知数据库本身数据的变化,这个跟楼主的要求不沾边儿,下面是我写的一个平常的存储过程,作用是访问外部url,告知数据库本身的变化: -- Author: George <gblog.iteye.com> CREATE OR REPLACE PROCEDURE OracleMessagePushTool(p_message IN VARCHAR2,p_returnValue OUT VARCHAR2) as v_text varchar2(100) := '这里是向url传递的参数值';--不能有空白 req utl_http.req; resp utl_http.resp; value VARCHAR2(2048); -- 访问url后,url的返回值 BEGIN -- Author: George <gblog.iteye.com> v_text := replace(p_message,'%','%25'); v_text := replace(utl_encode.text_encode(v_text), '=', '%'); req := utl_http.begin_request('http://192.168.2.109:9090/george-app/GlobalServerPush.gaction?doType=pushMessageFromDb&message=' || v_text); utl_http.set_header(req, 'Content-Type', 'text/html; charset=UTF-8'); resp := utl_http.get_response(req); LOOP utl_http.read_line(resp, value, TRUE); p_returnValue := p_returnValue || value; -- dbms_output.put_line(value); END LOOP; utl_http.end_response(resp); EXCEPTION WHEN utl_http.end_of_body THEN utl_http.end_response(resp); END OracleMessagePushTool; 这种技术在Oracle中是很平常和常用的场景,和楼主的要求风马牛不相及。 楼主的需求是从server端通知消息到client端浏览器,可以是广播到所有的浏览器,可以是单独对某个浏览器进行主动推送消息。 我一般是使用Pushlet来实现,这里是官方demo 但是Pushlet也不能很好地解决这类应用所面临的问题,最大的问题是效率问题。 楼主如果有足够的时间,可以研究一下gmail中的gtalk的消息推送实现。 你说的这个Oracle的DEMO也就是监听数据库的变化,确实和LZ所提的需求风马牛不相及,内部请求意易不大。。不过触发器的效率还是蛮高的。至于Pushlet,去看看去。谢谢分享。。 我举得那个存储过程的例子,本来就是和楼主的需求风马牛不相及,我帖子中举它做例子,就是为了说明这种数据库与外部程序交互的应用在Oracle中很常见,但是跟楼主要求的server push message to client风马牛不相及。 |
|
返回顶楼 | |
发表时间:2011-10-20
QiuQiu0034 写道 freegaga 写道 要求:当数据库中的数据发生变化时,需要主动将状态通知到前端,不希望使用定时异步刷新,请问各位高手有什么解决方案没有
pushlet,现在已经比较成熟了 不还是频繁请求的么?我还以为有什么特别的呢。原来是封装好的JS。。。 |
|
返回顶楼 | |
发表时间:2011-10-20
george_space 写道 Jclick 写道 george_space 写道 叫我Fox 写道 walldr2161 写道 说说想法不一定能实现:监听数据库,其实也就是AOP监听insert、delete、update等,
帖子一个 希望有所帮助 http://www.open-china.net/blog/8940.html 正解 使用数据库调用外部程序或者数据库向某个url发送请求来告知数据库本身数据的变化,这个跟楼主的要求不沾边儿,下面是我写的一个平常的存储过程,作用是访问外部url,告知数据库本身的变化: -- Author: George <gblog.iteye.com> CREATE OR REPLACE PROCEDURE OracleMessagePushTool(p_message IN VARCHAR2,p_returnValue OUT VARCHAR2) as v_text varchar2(100) := '这里是向url传递的参数值';--不能有空白 req utl_http.req; resp utl_http.resp; value VARCHAR2(2048); -- 访问url后,url的返回值 BEGIN -- Author: George <gblog.iteye.com> v_text := replace(p_message,'%','%25'); v_text := replace(utl_encode.text_encode(v_text), '=', '%'); req := utl_http.begin_request('http://192.168.2.109:9090/george-app/GlobalServerPush.gaction?doType=pushMessageFromDb&message=' || v_text); utl_http.set_header(req, 'Content-Type', 'text/html; charset=UTF-8'); resp := utl_http.get_response(req); LOOP utl_http.read_line(resp, value, TRUE); p_returnValue := p_returnValue || value; -- dbms_output.put_line(value); END LOOP; utl_http.end_response(resp); EXCEPTION WHEN utl_http.end_of_body THEN utl_http.end_response(resp); END OracleMessagePushTool; 这种技术在Oracle中是很平常和常用的场景,和楼主的要求风马牛不相及。 楼主的需求是从server端通知消息到client端浏览器,可以是广播到所有的浏览器,可以是单独对某个浏览器进行主动推送消息。 我一般是使用Pushlet来实现,这里是官方demo 但是Pushlet也不能很好地解决这类应用所面临的问题,最大的问题是效率问题。 楼主如果有足够的时间,可以研究一下gmail中的gtalk的消息推送实现。 你说的这个Oracle的DEMO也就是监听数据库的变化,确实和LZ所提的需求风马牛不相及,内部请求意易不大。。不过触发器的效率还是蛮高的。至于Pushlet,去看看去。谢谢分享。。 我举得那个存储过程的例子,本来就是和楼主的需求风马牛不相及,你没看懂我的帖子内容吧? 是你没看懂我的回复吧?“确实和LZ所提的需求风马牛不相及” 确实不懂什么意思? |
|
返回顶楼 | |