我对 PAX-Web 有疑问。我尝试将 Websocket 服务注册为声明性的,但无法从 Web 访问它。我已经尝试了给定的 websocket-jsr356-6.0.3.war,它工作正常。正如我所看到的,WAR 文件对 org.osgi.service.http.HttpContext 的处理方式不同。我尝试了以下场景:
场景 1 - OSGi R6 白板 HTTP 方法
创建一个 ServletContextHelper:
package hu.blackbelt.judo.common.rest.regular;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.http.context.ServletContextHelper;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
@Component(immediate = true)
@Service(ServletContextHelper.class)
@Properties(value = {
@Property(name = HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, value = "chat"),
@Property(name = HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, value = "/test")
})
public class ChatServletContext extends ServletContextHelper {
}
并添加 Websocket 端点:
package hu.blackbelt.judo.common.rest.regular;
import lombok.extern.slf4j.Slf4j;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import javax.websocket.EncodeException;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
@Component(immediate = true)
@Service(Object.class)
@Properties(value = {
@Property(name = HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
value = "=(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=chat)")
})
@Slf4j
public class ChatEndpoint {
public static final String ROOM = "room";
@OnOpen
public void onOpen(final Session session, @PathParam(ROOM) final String room) {
LOGGER.info("session openend and bound to room: " + room);
session.getUserProperties().put(ROOM, room);
}
@OnMessage
public void onMessage(final Session session, final ChatMessage chatMessage) {
String room = (String) session.getUserProperties().get(ROOM);
try {
for (Session s : session.getOpenSessions()) {
if (s.isOpen()
&& room.equals(s.getUserProperties().get(ROOM))) {
s.getBasicRemote().sendObject(chatMessage);
}
}
} catch (IOException | EncodeException e) {
LOGGER.warn("onMessage failed", e);
}
}
}
日志显示端点已被捕获。我已经调试并且 Pax-Web 正在注册它。
日志显示以下行:
2017-05-04 02:36:02,698 | INFO | Thread-70 | WebSocketTracker | 330 - org.ops4j.pax.web.pax-web-extender-whiteboard - 6.0.3 | found websocket endpoint!!
但是无法通过以下 URL 访问 websocket:ws://localost:8181/test/chat/testroom
场景 2 - 注册的 HttpContext 上的 Pax-Web 属性(使用 JAX-RS 可以工作)
创建 HttpContext 实例:(利用 OSGi 给定的 Helper 抽象类):
package hu.blackbelt.judo.common.rest.regular;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.context.ServletContextHelper;
@Component(immediate = true)
@Service(HttpContext.class)
@Properties(value = {
@Property(name = "httpContext.id", value = "chat"),
@Property(name = "httpContext.path", value = "test")
})
public class ChatHttpContext extends ServletContextHelper implements HttpContext {
}
和 Websocket 端点:
package hu.blackbelt.judo.common.rest.regular;
import lombok.extern.slf4j.Slf4j;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
import javax.websocket.EncodeException;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
@SuppressWarnings({"checkstyle:missingctor", "checkstyle:illegaltoken"})
@Component(immediate = true)
@Service(Object.class)
@Properties(value = {
@Property(name = "httpContext.id", value = "chat")
})
@ServerEndpoint(value = "/chat/{room}", encoders = ChatMessageEncoder.class, decoders = ChatMessageDecoder.class)
@Slf4j
public class ChatEndpoint {
public static final String ROOM = "room";
@OnOpen
public void onOpen(final Session session, @PathParam(ROOM) final String room) {
LOGGER.info("session openend and bound to room: " + room);
session.getUserProperties().put(ROOM, room);
}
@OnMessage
public void onMessage(final Session session, final ChatMessage chatMessage) {
String room = (String) session.getUserProperties().get(ROOM);
try {
for (Session s : session.getOpenSessions()) {
if (s.isOpen()
&& room.equals(s.getUserProperties().get(ROOM))) {
s.getBasicRemote().sendObject(chatMessage);
}
}
} catch (IOException | EncodeException e) {
LOGGER.warn("onMessage failed", e);
}
}
}
但是无法通过以下 URL 访问 websocket:ws://localost:8181/test/chat/testroom
我怎样才能实现 webcsocket 可用?我不想将我的捆绑包重新打包为 WAB。有什么办法吗?