자바 SSE 서버 푸 시 WEB 페이지 수신 데이터
, web app, , , , , : -- , , 、 , , Web , ,Web , , , 。 , 。
, :
1.
2. ,
:
、Ajax
Ajax , Ajax , ajax , 。
, , , 。
JSONP , , , 。
。
, , , , , 。
、Comet
Comet, HTTP " " , , , :
1. AJAX (long-polling)
Ajax JavaScript XMLHttpRequest HTTP ,JavaScript HTML 。 AJAX " " AJAX :
。
JavaScript , , 。
、 , ; , 。
" "(poll), " "(pull)。 AJAX, : ; ;IE、Mozilla FireFox AJAX。
(long polling) , HTTP XHR :
(1). HTTP JSONP
script 。 , , script , 。
(2).XHR
。
AJAX ; , , 。 JavaScript , , ; 。
CROS , HTTP JSONP , XHR 。
, Ajax 。
。 , , 。
>> , : Ajax , 。 : 。 : , 。 : 。 : Ajax , hold , , 。 : 。 : hold 。 :WebQQ、Hi 、Facebook IM。 , socket : : iframe, iframe src , 。 : , 。 : 。 :Gmail Flash Socket: Socket Flash JavaScript Flash Socket Socket ,JavaScript 。 : , 。 : Flash ; HTTP , 。 : 。
2. Iframe htmlfile (streaming)
iframe HTML , HTML , SRC , 。
Comet
: ( ); ( )
: , 。
Comet
1. Dojo CometD —— http://cometdproject.dojotoolkit.org/
2. DWR —— http://directwebremoting.org/dwr/index.html
3. ICEfaces —— http://www.icefaces.org/main/home/
4. GlassFish Grizzly —— https://grizzly.dev.java.net/
CometD Comet , DWR 。 ICEfaces , 。 Grizzly GlassFish , 。CometD, DWR 。
Comet
HTTP
IE , Web , 。 , 。 HTTP 1.1 , HTTP , 。 IE 。
HTTP 1.1 , Web : IE Web , IE HTTP 。
, frame , frame HTTP , HTTP , frame 。
Web , Comet, 。 , ; 。
, 。HTTP 1.1 1.0 :1.0 Get/Post ; 1.1 , , 。 Java 1.4 IO java.nio 。 , , ; , 。 、 。
AJAX , Comet , , 。Jetty 6 Web AJAX、Comet 。
HTTP
, : , , 。 , , 。
, HTTP , 。
, iframe , iframe, , , , ; , 。 AJAX , XMLHttpRequest , 。
“ ”
: , 。 , , 。 。 :
, , 。 , , 。
AJAX ; 、 , , , 、 。
, , 、 。
,websocket
WebSocket HTML5 TCP 。WebSocket 2011 IETF RFC 6455,WebSocketAPI W3C 。 WebSocket API , , , 。 。
websocket , websocket , 。
, 。
sse java
//
package com.xy.inuyasha.web.controller;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
/**
* Created by Administrator on 2017/3/15.
*/
@WebServlet(urlPatterns = { "/role_echo" }, asyncSupported = true)
public class SseTest extends HttpServlet {
private static final long serialVersionUID = 1L;
private final static int DEFAULT_TIME_OUT = 10 * 60 * 1000;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
resp.setContentType("text/event-stream");
resp.setCharacterEncoding("UTF-8");
req.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);//
AsyncContext actx = req.startAsync(req, resp);
actx.setTimeout(DEFAULT_TIME_OUT);
actx.addListener(new AsyncListener() {
@Override
public void onComplete(AsyncEvent arg0) throws IOException {
// TODO Auto-generated method stub
System.out.println("[echo]event complete:" + arg0.getSuppliedRequest().getRemoteAddr());
}
@Override
public void onError(AsyncEvent arg0) throws IOException {
// TODO Auto-generated method stub
System.out.println("[echo]event has error");
}
@Override
public void onStartAsync(AsyncEvent arg0) throws IOException {
// TODO Auto-generated method stub
System.out.println("[echo]event start:" + arg0.getSuppliedRequest().getRemoteAddr());
}
@Override
public void onTimeout(AsyncEvent arg0) throws IOException {
// TODO Auto-generated method stub
System.out.println("[echo]event time lost");
}
});
new Thread(new AsyncWebService(actx)).start();
}
}
class AsyncWebService implements Runnable {
AsyncContext ctx;
public AsyncWebService(AsyncContext ctx) {
this.ctx = ctx;
}
public void run() {
try {
// ,
Thread.sleep(10000);
PrintWriter out = ctx.getResponse().getWriter();
out.println("data: " + new Date() + "\r
"); //js EventSource :data: + "\r
"
out.flush();
ctx.complete();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//jsp js
if (!!window.EventSource) { //EventSource SSE . EventSource
var source = new EventSource('/role_echo');//
s = '';
source.addEventListener('message', function(e) {
s += e.data + "
";
$("#msgFromPush").html(s);
},false);//
source.addEventListener('open', function(e) {
console.log(" ");
}, false);
source.addEventListener('error',function(e){
if(e.currentTarget.readyState==EventSource.CLOSED){
console.log(" ");
}else{
console.log(e.currentTarget.readyState);
}
});
}else{
console.log(" SSE");
}
!!
웹 소켓
인터넷 이 발전 함 에 따라 전통 적 인 HTTP 프로 토 콜 은 웹 응용 이 날로 복잡 해 지 는 수 요 를 만족 시 키 기 어렵다.최근 몇 년 동안 HTML 5 가 탄생 하면 서 웹 소켓 프로 토 콜 은 브 라 우 저 와 서버 의 모든 양 방향 통신 을 실현 하고 브 라 우 저 와 서버 의 통신 기능 을 확대 하여 서버 도 자발적으로 클 라 이언 트 에 데 이 터 를 보 낼 수 있 도록 했다.
우 리 는 전통 적 인 HTTP 프로 토 콜 이 무상 태 라 는 것 을 알 고 있 습 니 다. 매번 요청 (request) 은 클 라 이언 트 (예 를 들 어 브 라 우 저) 가 주동 적 으로 시작 해 야 합 니 다. 서버 가 처리 한 후에 response 결 과 를 되 돌려 주 고 서버 는 클 라 이언 트 에 데 이 터 를 주동 적 으로 보 내기 어렵 습 니 다.이러한 클 라 이언 트 는 주동 적 인 측 이 고 서비스 측은 수 동적 인 측의 전통 적 인 웹 모델 로 정보 변화 가 빈번 하지 않 은 웹 응용 에 있어 발생 하 는 번 거 로 움 이 비교적 적 으 며 실시 간 정보 와 관련 된 웹 응용 에 큰 불편 을 가 져 왔 다. 예 를 들 어 실시 간 통신, 실시 간 데이터, 구독 푸 시 등 기능 을 가 진 응용 이다.웹 소켓 규범 이 제기 되 기 전에 개발 자 들 은 이러한 실시 간 으로 비교적 강 한 기능 을 실현 하려 면 절충 적 인 해결 방법 인 폴 링 (polling) 과 Comet 기술 을 자주 사용한다.사실 후 자 는 본질 적 으로 도 일종 의 폴 링 으로 개선 되 었 을 뿐이다.
폴 링 은 실시 간 웹 응용 을 실현 하 는 가장 원시 적 인 해결 방안 이다.폴 링 기술 은 클 라 이언 트 가 설정 한 시간 간격 으로 주기 적 으로 서버 에 요청 을 보 내 고 새로운 데이터 변경 여 부 를 자주 조회 하도록 요구한다.이런 방법 은 불필요 한 요청 을 너무 많이 하고 데이터 와 서버 자원 을 낭비 하 는 것 이 분명 하 다.
Comet 기술 은 긴 폴 링 과 스 트림 기술 로 나 눌 수 있다.긴 폴 링 은 상술 한 폴 링 기술 을 개선 하여 쓸모없는 요 구 를 줄 였 다.일부 데이터 에 만 료 시간 을 설정 하고 데이터 가 만 료 된 후에 야 서버 에 요청 을 보 낼 수 있 습 니 다.이런 메커니즘 은 데이터 의 변경 에 적합 하 다. 특별히 빈번 한 상황 은 아니다.스 트림 기술 은 클 라 이언 트 가 숨겨 진 창 을 사용 하여 서버 와 HTTP 긴 연결 을 만 드 는 것 을 말 합 니 다. 서버 는 연결 상 태 를 계속 업데이트 하여 HTTP 긴 연결 을 유지 합 니 다.이렇게 하면 서버 는 이 긴 연결 을 통 해 자발적으로 데 이 터 를 클 라 이언 트 에 보 낼 수 있다.스 트림 기술 은 병발 환경 에서 서버 의 성능 을 시험 할 수 있다.
이 두 가지 기술 은 모두 요청 - 응답 모델 을 바탕 으로 하 는 것 으로 진정한 의미 의 실시 간 기술 이 아니다.그들의 모든 요청, 응답 은 똑 같은 머리 정보 에 일정한 데 이 터 를 낭비 하고 개발 의 복잡 도 도 비교적 크다.
HTML 5 가 출시 한 웹 소켓 과 함께 웹 의 실시 간 통신 을 진정 으로 실현 하여 B / S 모드 가 C / S 모드 의 실시 간 통신 능력 을 갖 추 게 되 었 다.웹 소켓 의 작업 절 차 는 다음 과 같 습 니 다. 브 라 우 저 는 자바 스 크 립 트 를 통 해 서버 에 웹 소켓 연결 을 요청 합 니 다. 웹 소켓 연결 이 성공 하면 클 라 이언 트 와 서버 는 TCP 연결 을 통 해 데 이 터 를 전송 할 수 있 습 니 다.웹 소켓 연결 은 본질 적 으로 TCP 연결 이기 때문에 전송 할 때마다 반복 되 는 머리 데 이 터 를 가 져 올 필요 가 없 기 때문에 폴 링 과 Comet 기술 보다 데이터 전 송 량 이 훨씬 적다.본 고 는 웹 소켓 규범 을 상세 하 게 소개 하지 않 고 주로 웹 소켓 이 자바 웹 에서 의 실현 을 소개 한다.
자바 EE 7 에서 JSR - 356: 자바 API for WebSocket 규범 이 나 왔 습 니 다.Tomcat, Nginx, Jetty 등 많은 웹 용기 들 이 웹 소켓 을 지원 한다.톰 캣 은 7.0.27 부터 웹 소켓 을 지원 하고 7.0.47 부터 JSR - 356 을 지원 하 며, 아래 데모 코드 역시 톰 캣 7.0.47 이상 에 배 치 된 버 전이 있어 야 실행 할 수 있다.
2. WebSocket 예제
2.1. 새 자바 웹 테스트 항목
pom. xml 에 Jar 패키지 의존 추가
javax
javaee-api
7.0
provided
클 라 이언 트 (웹 홈 페이지) 코드:
html>
Java WebSocket Tomcat Welcome
var websocket = null; // WebSocket if ('WebSocket' in window) { websocket = new WebSocket("ws://localhost:8080/websocket"); } else { alert(' Not support websocket') } // websocket.onerror = function () { setMessageInnerHTML("WebSocket "); }; // websocket.onopen = function () { setMessageInnerHTML("WebSocket "); } // websocket.onmessage = function (event) { setMessageInnerHTML(event.data); } // websocket.onclose = function () { setMessageInnerHTML("WebSocket "); } // , , websocket , ,server 。 window.onbeforeunload = function () { closeWebSocket(); } // function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML += innerHTML + '<br/>'; } // WebSocket function closeWebSocket() { websocket.close(); } // function send() { var message = document.getElementById('text').value; websocket.send(message); }
Java Web后端代码
package me.gacl.websocket;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
/**
* @ServerEndpoint , websocket ,
* URL , URL WebSocket
*/
@ServerEndpoint("/websocket")
public class WebSocketTest {
// , 。 。
private static int onlineCount = 0;
//concurrent Set, MyWebSocket 。 , Map , Key
private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet();
// ,
private Session session;
/**
*
* @param session 。session ,
*/
@OnOpen
public void onOpen(Session session){
this.session = session;
webSocketSet.add(this); // set
addOnlineCount(); // 1
System.out.println(" ! " + getOnlineCount());
}
/**
*
*/
@OnClose
public void onClose(){
webSocketSet.remove(this); // set
subOnlineCount(); // 1
System.out.println(" ! " + getOnlineCount());
}
/**
*
* @param message
* @param session
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println(" :" + message);
//
for(WebSocketTest item: webSocketSet){
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
/**
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
System.out.println(" ");
error.printStackTrace();
}
/**
* 。 , 。
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException{
this.session.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketTest.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketTest.onlineCount--;
}
}
1.2. 실행 효과
Google 브 라 우 저 와 불 여우 브 라 우 저 를 동시에 열 어 다 중 클 라 이언 트 시 뮬 레이 션 을 진행 합 니 다. 실행 효 과 는 다음 과 같 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.