我正在WebLogic12.1.3服务器上运行一个Spring3.1.2后端。为了接受websocket连接,我的配置器如下所示:
public class SpringConfigurator extends Configurator {
private static final Logger LOGGER = LoggerFactory.make();
private static final Map<String, Map<Class<?>, String>> cache = new ConcurrentHashMap<String, Map<Class<?>, String>>();
private static final String MAGIC_STR = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
private static final String NO_VALUE = ObjectUtils.identityToString(new Object());
@SuppressWarnings("unchecked")
@Override
public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
if (wac == null) {
String message = "Failed to find the root WebApplicationContext. Was ContextLoaderListener not used?";
LOGGER.error(message);
throw new IllegalStateException(message);
}
String beanName = ClassUtils.getShortNameAsProperty(endpointClass);
if (wac.containsBean(beanName)) {
T endpoint = wac.getBean(beanName, endpointClass);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Using @ServerEndpoint singleton " + endpoint);
}
return endpoint;
}
Component annot = AnnotationUtils.findAnnotation(endpointClass, Component.class);
if ((annot != null) && wac.containsBean(annot.value())) {
T endpoint = wac.getBean(annot.value(), endpointClass);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Using @ServerEndpoint singleton " + endpoint);
}
return endpoint;
}
beanName = getBeanNameByType(wac, endpointClass);
if (beanName != null) {
return (T) wac.getBean(beanName);
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Creating new @ServerEndpoint instance of type " + endpointClass);
}
return wac.getAutowireCapableBeanFactory().createBean(endpointClass);
}
// modifyHandshake() is called before getEndpointInstance()
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
super.modifyHandshake(sec, request, response);
}
private String getBeanNameByType(WebApplicationContext wac, Class<?> endpointClass) {
String wacId = wac.getId();
Map<Class<?>, String> beanNamesByType = cache.get(wacId);
if (beanNamesByType == null) {
beanNamesByType = new ConcurrentHashMap<Class<?>, String>();
cache.put(wacId, beanNamesByType);
}
if (!beanNamesByType.containsKey(endpointClass)) {
String[] names = wac.getBeanNamesForType(endpointClass);
if (names.length == 1) {
beanNamesByType.put(endpointClass, names[0]);
} else {
beanNamesByType.put(endpointClass, NO_VALUE);
if (names.length > 1) {
String message = "Found multiple @ServerEndpoint's of type " + endpointClass + ", names=" + names;
LOGGER.error(message);
throw new IllegalStateException(message);
}
}
}
String beanName = beanNamesByType.get(endpointClass);
return NO_VALUE.equals(beanName) ? null : beanName;
}
}问题是,当我试图通过javascript客户端打开websocket连接时,当我调试这个位置时,它会正确地生成响应头:
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
super.modifyHandshake(sec, request, response);
}但是,在客户端,它提供了以下错误:
到'ws://localhost:7001/ WebSocket‘的WebSocket连接失败:错误在>WebSocket握手:无效状态行
在工具中,响应如下:
HTTP/0.9 200 OK
我认为http请求并没有升级到websocket连接。
我非常感谢在这个问题上提供任何帮助。
发布于 2016-06-12 20:03:54
今天,在http://showcase.omnifaces.org/push/socket 12.2.1上测试WebLogic时,我正好遇到了这个问题。
在webapp的第一次测试尝试中,WebLogic在进行websocket连接时抛出以下异常:
java.lang.IllegalStateException: The async-support is disabled on this request: weblogic.servlet.internal.ServletRequest
Impl@6682044b[GET /omnifaces.push/counter?e6845a3a-26ed-4520-9824-63ffd85b24eb HTTP/1.1]
at weblogic.servlet.internal.ServletRequestImpl.startAsync(ServletRequestImpl.java:1949)
at weblogic.servlet.internal.ServletRequestImpl.startAsync(ServletRequestImpl.java:1925)
at javax.servlet.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:432)
at weblogic.websocket.tyrus.TyrusServletFilter.doFilter(TyrusServletFilter.java:234)
...结果,与我测试的所有其他服务器相反,WebLogic自己的负责处理websocket握手请求的TyrusServletFilter是在通过部署的webapp的web.xml提供的过滤器之后在内部安装的。webapp附带了一个字符编码过滤器和一个映射在/*上的GZIP过滤器,因此它们在websocket过滤器之前被调用。乍一看,这很奇怪,但我认为它就是这样的,所以我只是在那些webapp提供的过滤器中添加了<async-supported>true</async-supported>,这样TyrusServletFilter就可以完成它的工作了。
但是,在进行websocket连接时,当发送推送消息时,客户端会出现JavaScript错误,这正是您所面对的情况:
到'ws://localhost:7001/omnifaces.push/counter?e6845a3a-26ed-4520-9824-63ffd85b24eb‘的WebSocket连接失败:在WebSocket握手过程中出错:无效状态行
事实证明,WebSockets无法处理GZIP响应。在禁用GZIP过滤器之后,一切都继续完美无缺地工作。
然而,根本的问题是,WebLogic应该在所有webapp提供的过滤器之前安装它的TyrusServletFilter 。我测试过的所有其他Java服务器都正确地做到了这一点。正如您在对这个问题的评论中提到的,立即将所有websocket握手请求发送到目标URL模式,这是一个很好的解决方法。另一种方法是重新配置web.xml-provided过滤器,使其不再匹配websocket握手请求,例如使用更具体的-provided模式,或者映射到特定的servlet。
https://stackoverflow.com/questions/34297174
复制相似问题