下面列出了javax.websocket.OnError#javax.websocket.PongMessage 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void onPongMessage(final PongWebSocketFrame frame) {
if (session.isSessionClosed()) {
//to bad, the channel has already been closed
//we just ignore messages that are received after we have closed, as the endpoint is no longer in a valid state to deal with them
//this this should only happen if a message was on the wire when we called close()
return;
}
final HandlerWrapper handler = getHandler(FrameType.PONG);
if (handler != null) {
final PongMessage message = DefaultPongMessage.create(Unpooled.copiedBuffer(frame.content()).nioBuffer());
session.getContainer().invokeEndpointMethod(executor, new Runnable() {
@Override
public void run() {
try {
((MessageHandler.Whole) handler.getHandler()).onMessage(message);
} catch (Exception e) {
invokeOnError(e);
}
}
});
}
}
@Override
public void onMessage(PongMessage message) {
getMessages().add(message);
if (getLatch() != null) {
getLatch().countDown();
}
}
/**
* Create a {@link PongMessage} from the given {@link ByteBuffer}.
*/
public static PongMessage create(ByteBuffer data) {
if (data == null || data.hasRemaining()) {
return new DefaultPongMessage(data);
}
return EMPTY;
}
/**
* Return the {@link FrameType} for the given {@link Class}.
* <p>
* Note that multiple wrappers can be returned if both text and binary frames can be decoded to the given type
*/
protected List<HandlerWrapper> createHandlerWrappers(Class<?> type, MessageHandler handler, boolean partialHandler) {
//check the encodings first
Encoding encoding = session.getEncoding();
List<HandlerWrapper> ret = new ArrayList<>(2);
if (encoding.canDecodeText(type)) {
ret.add(new HandlerWrapper(FrameType.TEXT, handler, type, true, false));
}
if (encoding.canDecodeBinary(type)) {
ret.add(new HandlerWrapper(FrameType.BYTE, handler, type, true, false));
}
if (!ret.isEmpty()) {
return ret;
}
if (partialHandler) {
// Partial message handler supports only String, byte[] and ByteBuffer.
// See JavaDocs of the MessageHandler.Partial interface.
if (type == String.class) {
return Collections.singletonList(new HandlerWrapper(FrameType.TEXT, handler, type, false, true));
}
if (type == byte[].class || type == ByteBuffer.class) {
return Collections.singletonList(new HandlerWrapper(FrameType.BYTE, handler, type, false, true));
}
throw JsrWebSocketMessages.MESSAGES.unsupportedFrameType(type);
}
if (type == byte[].class || type == ByteBuffer.class || type == InputStream.class) {
return Collections.singletonList(new HandlerWrapper(FrameType.BYTE, handler, type, false, false));
}
if (type == String.class || type == Reader.class) {
return Collections.singletonList(new HandlerWrapper(FrameType.TEXT, handler, type, false, false));
}
if (type == PongMessage.class) {
return Collections.singletonList(new HandlerWrapper(FrameType.PONG, handler, type, false, false));
}
throw JsrWebSocketMessages.MESSAGES.unsupportedFrameType(type);
}
@Override
public void run() {
try {
WebSocketSession wsSession = getWebSocketSession();
if (wsSession == null) {
return;
}
// Close the message
if (frame instanceof CloseWebSocketFrame) {
wsSession.getWebSocketServerHandshaker().close(context.channel(), (CloseWebSocketFrame) frame.retain());
return;
}
// Ping message
if (frame instanceof PingWebSocketFrame) {
ByteBuffer request = frame.content().nioBuffer();
onWebsocketMessage(wsSession, frame, (PongMessage) () -> request);
return;
}
// Binary message
if (frame instanceof BinaryWebSocketFrame) {
onWebsocketMessage(wsSession, frame, frame.content().nioBuffer());
return;
}
// String message
if (frame instanceof TextWebSocketFrame) {
onWebsocketMessage(wsSession, frame, ((TextWebSocketFrame) frame).text());
}
}finally {
WebsocketRunnable.this.recycle();
}
}
@Override
public void onMessage(PongMessage message) {
getMessages().add(message);
if (getLatch() != null) {
getLatch().countDown();
}
}
@Override
public void onMessage(PongMessage message) {
getMessages().add(message);
if (getLatch() != null) {
getLatch().countDown();
}
}
private boolean validateOnPongMethod(Object webSocketEndpoint)
throws WebSocketMethodParameterException, WebSocketEndpointMethodReturnTypeException {
EndpointDispatcher dispatcher = new EndpointDispatcher();
Method method;
if (dispatcher.getOnPongMessageMethod(webSocketEndpoint).isPresent()) {
method = dispatcher.getOnPongMessageMethod(webSocketEndpoint).get();
} else {
return true;
}
validateReturnType(method);
boolean foundPrimaryPong = false;
for (Parameter parameter: method.getParameters()) {
Class<?> paraType = parameter.getType();
if (paraType == String.class) {
if (parameter.getAnnotation(PathParam.class) == null) {
throw new WebSocketMethodParameterException("Invalid parameter found on pong message method: " +
"string parameter without " +
"@PathParam annotation.");
}
} else if (paraType == PongMessage.class) {
if (foundPrimaryPong) {
throw new WebSocketMethodParameterException("Invalid parameter found on pong message method: " +
"only one PongMessage should be declared.");
}
foundPrimaryPong = true;
} else if (paraType != WebSocketConnection.class) {
throw new WebSocketMethodParameterException("Invalid parameter found on pong message method: " +
paraType);
}
}
return foundPrimaryPong;
}
private boolean validateReturnType(Method method) throws WebSocketEndpointMethodReturnTypeException {
Class<?> returnType = method.getReturnType();
boolean foundCorrectReturnType = returnType == String.class || returnType == ByteBuffer.class ||
returnType == byte[].class || returnType == PongMessage.class || returnType == void.class;
if (!foundCorrectReturnType) {
throw new WebSocketEndpointMethodReturnTypeException("Unexpected method return type: " + returnType);
}
return foundCorrectReturnType;
}
/**
* Extract OnMessage method for Pong from the endpoint if exists.
*
* @param webSocketEndpoint Endpoint to extract method.
* @return method optional to handle pong messages.
*/
public Optional<Method> getOnPongMessageMethod(Object webSocketEndpoint) {
Method[] methods = webSocketEndpoint.getClass().getMethods();
Method returnMethod = null;
for (Method method : methods) {
if (method.isAnnotationPresent(OnMessage.class)) {
Class<?>[] paraTypes = method.getParameterTypes();
List<Class<?>> paraList = Arrays.asList(paraTypes);
if (paraList.contains(PongMessage.class)) {
returnMethod = method;
}
}
}
return Optional.ofNullable(returnMethod);
}
private void handleControlCarbonMessage(WebSocketControlMessage controlCarbonMessage, PatternPathRouter.
RoutableDestination<Object> routableEndpoint, WebSocketConnection webSocketConnection) {
if (routableEndpoint == null) {
throw new RuntimeException("Error while handling the message. Routable endpoint is not registered for the" +
" request uri:" + controlCarbonMessage.getTarget());
}
Object webSocketEndpoint = routableEndpoint.getDestination();
Map<String, String> paramValues = routableEndpoint.getGroupNameValues();
Optional<Method> methodOptional = new EndpointDispatcher().getOnPongMessageMethod(webSocketEndpoint);
try {
methodOptional.ifPresent(method -> {
List<Object> parameterList = new LinkedList<>();
Arrays.stream(method.getParameters()).forEach(parameter -> {
if (parameter.getType() == PongMessage.class) {
parameterList.add(new WebSocketPongMessage(controlCarbonMessage.getByteBuffer()));
} else if (parameter.getType() == WebSocketConnection.class) {
parameterList.add(webSocketConnection);
} else if (parameter.getType() == String.class) {
PathParam pathParam = parameter.getAnnotation(PathParam.class);
if (pathParam != null) {
parameterList.add(paramValues.get(pathParam.value()));
}
} else {
parameterList.add(null);
}
});
executeMethod(method, webSocketEndpoint, parameterList, webSocketConnection);
});
} catch (Throwable throwable) {
handleError(throwable, routableEndpoint, webSocketConnection);
}
}
@SuppressWarnings("unchecked")
private void doAddMessageHandler(Class<?> target, MessageHandler listener) {
checkState();
// Message handlers that require decoders may map to text messages,
// binary messages, both or neither.
// The frame processing code expects binary message handlers to
// accept ByteBuffer
// Use the POJO message handler wrappers as they are designed to wrap
// arbitrary objects with MessageHandlers and can wrap MessageHandlers
// just as easily.
Set<MessageHandlerResult> mhResults = Util.getMessageHandlers(target, listener,
endpointConfig, this);
for (MessageHandlerResult mhResult : mhResults) {
switch (mhResult.getType()) {
case TEXT: {
if (textMessageHandler != null) {
throw new IllegalStateException(sm.getString("wsSession.duplicateHandlerText"));
}
textMessageHandler = mhResult.getHandler();
break;
}
case BINARY: {
if (binaryMessageHandler != null) {
throw new IllegalStateException(
sm.getString("wsSession.duplicateHandlerBinary"));
}
binaryMessageHandler = mhResult.getHandler();
break;
}
case PONG: {
if (pongMessageHandler != null) {
throw new IllegalStateException(sm.getString("wsSession.duplicateHandlerPong"));
}
MessageHandler handler = mhResult.getHandler();
if (handler instanceof MessageHandler.Whole<?>) {
pongMessageHandler = (MessageHandler.Whole<PongMessage>) handler;
} else {
throw new IllegalStateException(
sm.getString("wsSession.invalidHandlerTypePong"));
}
break;
}
default: {
throw new IllegalArgumentException(
sm.getString("wsSession.unknownHandlerType", listener, mhResult.getType()));
}
}
}
}
protected MessageHandler.Whole<PongMessage> getPongMessageHandler() {
return pongMessageHandler;
}
private boolean processDataControl() throws IOException {
TransformationResult tr = transformation.getMoreData(opCode, fin, rsv, controlBufferBinary);
if (TransformationResult.UNDERFLOW.equals(tr)) {
return false;
}
// Control messages have fixed message size so
// TransformationResult.OVERFLOW is not possible here
controlBufferBinary.flip();
if (opCode == Constants.OPCODE_CLOSE) {
open = false;
String reason = null;
int code = CloseCodes.NORMAL_CLOSURE.getCode();
if (controlBufferBinary.remaining() == 1) {
controlBufferBinary.clear();
// Payload must be zero or 2+ bytes long
throw new WsIOException(new CloseReason(
CloseCodes.PROTOCOL_ERROR,
sm.getString("wsFrame.oneByteCloseCode")));
}
if (controlBufferBinary.remaining() > 1) {
code = controlBufferBinary.getShort();
if (controlBufferBinary.remaining() > 0) {
CoderResult cr = utf8DecoderControl.decode(controlBufferBinary,
controlBufferText, true);
if (cr.isError()) {
controlBufferBinary.clear();
controlBufferText.clear();
throw new WsIOException(new CloseReason(
CloseCodes.PROTOCOL_ERROR,
sm.getString("wsFrame.invalidUtf8Close")));
}
// There will be no overflow as the output buffer is big
// enough. There will be no underflow as all the data is
// passed to the decoder in a single call.
controlBufferText.flip();
reason = controlBufferText.toString();
}
}
wsSession.onClose(new CloseReason(Util.getCloseCode(code), reason));
} else if (opCode == Constants.OPCODE_PING) {
if (wsSession.isOpen()) {
wsSession.getBasicRemote().sendPong(controlBufferBinary);
}
} else if (opCode == Constants.OPCODE_PONG) {
MessageHandler.Whole<PongMessage> mhPong = wsSession.getPongMessageHandler();
if (mhPong != null) {
try {
mhPong.onMessage(new WsPongMessage(controlBufferBinary));
} catch (Throwable t) {
handleThrowableOnSend(t);
} finally {
controlBufferBinary.clear();
}
}
} else {
// Should have caught this earlier but just in case...
controlBufferBinary.clear();
throw new WsIOException(new CloseReason(
CloseCodes.PROTOCOL_ERROR,
sm.getString("wsFrame.invalidOpCode", Integer.valueOf(opCode))));
}
controlBufferBinary.clear();
newFrame();
return true;
}
@Override
protected Object decode(PongMessage message) {
// Never decoded
return null;
}
@OnMessage
public void pong(PongMessage message) {
byte [] data = new byte[message.getApplicationData().remaining()];
message.getApplicationData().get(data);
MESSAGES.add("PONG:" + new String(data, StandardCharsets.UTF_8));
}
@SuppressWarnings("unchecked")
private void doAddMessageHandler(Class<?> target, MessageHandler listener) {
checkState();
// Message handlers that require decoders may map to text messages,
// binary messages, both or neither.
// The frame processing code expects binary message handlers to
// accept ByteBuffer
// Use the POJO message handler wrappers as they are designed to wrap
// arbitrary objects with MessageHandlers and can wrap MessageHandlers
// just as easily.
Set<MessageHandlerResult> mhResults =
Util.getMessageHandlers(target, listener, endpointConfig, this);
for (MessageHandlerResult mhResult : mhResults) {
switch (mhResult.getType()) {
case TEXT: {
if (textMessageHandler != null) {
throw new IllegalStateException(
sm.getString("wsSession.duplicateHandlerText"));
}
textMessageHandler = mhResult.getHandler();
break;
}
case BINARY: {
if (binaryMessageHandler != null) {
throw new IllegalStateException(
sm.getString("wsSession.duplicateHandlerBinary"));
}
binaryMessageHandler = mhResult.getHandler();
break;
}
case PONG: {
if (pongMessageHandler != null) {
throw new IllegalStateException(
sm.getString("wsSession.duplicateHandlerPong"));
}
MessageHandler handler = mhResult.getHandler();
if (handler instanceof MessageHandler.Whole<?>) {
pongMessageHandler =
(MessageHandler.Whole<PongMessage>) handler;
} else {
throw new IllegalStateException(
sm.getString("wsSession.invalidHandlerTypePong"));
}
break;
}
default: {
throw new IllegalArgumentException(sm.getString(
"wsSession.unknownHandlerType", listener,
mhResult.getType()));
}
}
}
}
protected MessageHandler.Whole<PongMessage> getPongMessageHandler() {
return pongMessageHandler;
}
private boolean processDataControl() throws IOException {
TransformationResult tr = transformation.getMoreData(opCode, fin, rsv, controlBufferBinary);
if (TransformationResult.UNDERFLOW.equals(tr)) {
return false;
}
// Control messages have fixed message size so
// TransformationResult.OVERFLOW is not possible here
controlBufferBinary.flip();
if (opCode == Constants.OPCODE_CLOSE) {
open = false;
String reason = null;
int code = CloseCodes.NORMAL_CLOSURE.getCode();
if (controlBufferBinary.remaining() == 1) {
controlBufferBinary.clear();
// Payload must be zero or greater than 2
throw new WsIOException(new CloseReason(
CloseCodes.PROTOCOL_ERROR,
sm.getString("wsFrame.oneByteCloseCode")));
}
if (controlBufferBinary.remaining() > 1) {
code = controlBufferBinary.getShort();
if (controlBufferBinary.remaining() > 0) {
CoderResult cr = utf8DecoderControl.decode(
controlBufferBinary, controlBufferText, true);
if (cr.isError()) {
controlBufferBinary.clear();
controlBufferText.clear();
throw new WsIOException(new CloseReason(
CloseCodes.PROTOCOL_ERROR,
sm.getString("wsFrame.invalidUtf8Close")));
}
// There will be no overflow as the output buffer is big
// enough. There will be no underflow as all the data is
// passed to the decoder in a single call.
controlBufferText.flip();
reason = controlBufferText.toString();
}
}
wsSession.onClose(new CloseReason(Util.getCloseCode(code), reason));
} else if (opCode == Constants.OPCODE_PING) {
if (wsSession.isOpen()) {
wsSession.getBasicRemote().sendPong(controlBufferBinary);
}
} else if (opCode == Constants.OPCODE_PONG) {
MessageHandler.Whole<PongMessage> mhPong =
wsSession.getPongMessageHandler();
if (mhPong != null) {
try {
mhPong.onMessage(new WsPongMessage(controlBufferBinary));
} catch (Throwable t) {
handleThrowableOnSend(t);
} finally {
controlBufferBinary.clear();
}
}
} else {
// Should have caught this earlier but just in case...
controlBufferBinary.clear();
throw new WsIOException(new CloseReason(
CloseCodes.PROTOCOL_ERROR,
sm.getString("wsFrame.invalidOpCode",
Integer.valueOf(opCode))));
}
controlBufferBinary.clear();
newFrame();
return true;
}
@Override
protected Object decode(PongMessage message) {
// Never decoded
return null;
}
@SuppressWarnings("unchecked")
private void doAddMessageHandler(Class<?> target, MessageHandler listener) {
checkState();
// Message handlers that require decoders may map to text messages,
// binary messages, both or neither.
// The frame processing code expects binary message handlers to
// accept ByteBuffer
// Use the POJO message handler wrappers as they are designed to wrap
// arbitrary objects with MessageHandlers and can wrap MessageHandlers
// just as easily.
Set<MessageHandlerResult> mhResults =
Util.getMessageHandlers(target, listener, endpointConfig, this);
for (MessageHandlerResult mhResult : mhResults) {
switch (mhResult.getType()) {
case TEXT: {
if (textMessageHandler != null) {
throw new IllegalStateException(
sm.getString("wsSession.duplicateHandlerText"));
}
textMessageHandler = mhResult.getHandler();
break;
}
case BINARY: {
if (binaryMessageHandler != null) {
throw new IllegalStateException(
sm.getString("wsSession.duplicateHandlerBinary"));
}
binaryMessageHandler = mhResult.getHandler();
break;
}
case PONG: {
if (pongMessageHandler != null) {
throw new IllegalStateException(
sm.getString("wsSession.duplicateHandlerPong"));
}
MessageHandler handler = mhResult.getHandler();
if (handler instanceof MessageHandler.Whole<?>) {
pongMessageHandler =
(MessageHandler.Whole<PongMessage>) handler;
} else {
throw new IllegalStateException(
sm.getString("wsSession.invalidHandlerTypePong"));
}
break;
}
default: {
throw new IllegalArgumentException(sm.getString(
"wsSession.unknownHandlerType", listener,
mhResult.getType()));
}
}
}
}
protected MessageHandler.Whole<PongMessage> getPongMessageHandler() {
return pongMessageHandler;
}
private boolean processDataControl() throws IOException {
TransformationResult tr = transformation.getMoreData(opCode, fin, rsv, controlBufferBinary);
if (TransformationResult.UNDERFLOW.equals(tr)) {
return false;
}
// Control messages have fixed message size so
// TransformationResult.OVERFLOW is not possible here
controlBufferBinary.flip();
if (opCode == Constants.OPCODE_CLOSE) {
open = false;
String reason = null;
int code = CloseCodes.NORMAL_CLOSURE.getCode();
if (controlBufferBinary.remaining() == 1) {
controlBufferBinary.clear();
// Payload must be zero or greater than 2
throw new WsIOException(new CloseReason(
CloseCodes.PROTOCOL_ERROR,
sm.getString("wsFrame.oneByteCloseCode")));
}
if (controlBufferBinary.remaining() > 1) {
code = controlBufferBinary.getShort();
if (controlBufferBinary.remaining() > 0) {
CoderResult cr = utf8DecoderControl.decode(
controlBufferBinary, controlBufferText, true);
if (cr.isError()) {
controlBufferBinary.clear();
controlBufferText.clear();
throw new WsIOException(new CloseReason(
CloseCodes.PROTOCOL_ERROR,
sm.getString("wsFrame.invalidUtf8Close")));
}
// There will be no overflow as the output buffer is big
// enough. There will be no underflow as all the data is
// passed to the decoder in a single call.
controlBufferText.flip();
reason = controlBufferText.toString();
}
}
wsSession.onClose(new CloseReason(Util.getCloseCode(code), reason));
} else if (opCode == Constants.OPCODE_PING) {
if (wsSession.isOpen()) {
wsSession.getBasicRemote().sendPong(controlBufferBinary);
}
} else if (opCode == Constants.OPCODE_PONG) {
MessageHandler.Whole<PongMessage> mhPong =
wsSession.getPongMessageHandler();
if (mhPong != null) {
try {
mhPong.onMessage(new WsPongMessage(controlBufferBinary));
} catch (Throwable t) {
handleThrowableOnSend(t);
} finally {
controlBufferBinary.clear();
}
}
} else {
// Should have caught this earlier but just in case...
controlBufferBinary.clear();
throw new WsIOException(new CloseReason(
CloseCodes.PROTOCOL_ERROR,
sm.getString("wsFrame.invalidOpCode",
Integer.valueOf(opCode))));
}
controlBufferBinary.clear();
newFrame();
return true;
}
@Override
protected Object decode(PongMessage message) {
// Never decoded
return null;
}
@OnMessage
public PongMessage onPongMessage(PongMessage pongMessage, WebSocketConnection webSocketConnection) {
log.info("Received a pong message.");
return pongMessage;
}
@OnMessage
public void onTextMessage(PongMessage pongMessage, WebSocketConnection webSocketConnection, String errorText)
throws IOException {
}
@OnMessage
public PongMessage onPong(@PathParam("param1") String param1, @PathParam("param2") String param2,
PongMessage pongMessage, WebSocketConnection webSocketConnection) {
return pongMessage;
}
@OnMessage
public PongMessage onPong(PongMessage pongMessage) {
return pongMessage;
}
@OnMessage
public void onMessage(PongMessage message) {
ByteBuffer byteMessage = message.getApplicationData();
String s = StandardCharsets.UTF_8.decode(byteMessage).toString();
this.messageQueue.offer(s);
}
/**
* Process a received pong. This is a NO-OP.
*
* @param pm Ignored.
*/
@OnMessage
public void echoPongMessage(PongMessage pm) {
// NO-OP
}