背景
最近在我的项目上用了WebSocket,然而遇到了一个很奇怪的问题,利用启动时抛出
Failed to register @ServerEndpoint class
配置类
package com.smec.fin.config.websocket;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;/** * @Description: * @author: wei.wang * @since: 2020/7/28 10:29 * @history: 1.2020/7/28 created by wei.wang */@Configurationpublic class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }}
接管连贯的类
package com.smec.fin.service.impl;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import javax.websocket.*;import javax.websocket.server.ServerEndpoint;import java.io.IOException;import java.util.concurrent.CopyOnWriteArraySet;/** * @Description: * @author: wei.wang * @since: 2020/7/28 10:46 * @history: 1.2020/7/28 created by wei.wang */@ServerEndpoint("/websocket")@Componentpublic class WebSocketServer { private static Logger logger = LoggerFactory.getLogger(WebSocketServer.class); /** * 动态变量,用来记录以后在线连接数。 */ private static volatile int onlineCount = 0; /** * concurrent包的线程平安Set,用来寄存每个客户端对应的WebSocket对象,目前只有一个客户端,所以应用Set */ private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>(); /** * 与某个客户端的连贯会话,须要通过它来给客户端发送数据 */ private Session session; /** * 连贯建设胜利调用的办法 */ @OnOpen public void onOpen(Session session) { this.session = session; //退出set中 webSocketSet.add(this); //在线数加1 addOnlineCount(); logger.info("开始监听,以后在线人数为{}", getOnlineCount()); } /** * 连贯敞开调用的办法 */ @OnClose public void onClose() { logger.info("有一连贯敞开!以后在线人数为" + getOnlineCount()); //从set中删除 webSocketSet.remove(this); //在线数减1 subOnlineCount(); logger.info("有一连贯敞开!以后在线人数为" + getOnlineCount()); } /** * 收到客户端音讯后调用的办法 * * @param message 客户端发送过去的音讯 */ @OnMessage public void onMessage(String message) { logger.info("收到信息:" + message); System.out.println("webSocketSet Size " + webSocketSet.size()); } /** * 发送音讯 * * @param message */ public void sendMessageToPad(String message) { for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } /** * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { logger.error("产生谬误"); error.printStackTrace(); } /** * 实现服务器被动推送 */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketServer.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketServer.onlineCount--; }}
看起来都没问题,咱们把异样信息都打进去
Caused by: javax.websocket.DeploymentException: Cannot deploy POJO class [com.smec.fin.service.impl.WebSocketServer$$EnhancerBySpringCGLIB$$6b71ea8] as it is not annotated with @ServerEndpoint at org.apache.tomcat.websocket.server.WsServerContainer.addEndpoint(WsServerContainer.java:245) at org.apache.tomcat.websocket.server.WsServerContainer.addEndpoint(WsServerContainer.java:228) at org.springframework.web.socket.server.standard.ServerEndpointExporter.registerEndpoint(ServerEndpointExporter.java:156) ... 17 common frames omitted
问题起因
问题定位到WsServerContainer.java:245行,打上断点,咱们发现pojo被代理了,其实依据打印日志com.smec.fin.service.impl.WebSocketServer$$EnhancerBySpringCGLIB$$6b71ea8也能够看进去,应用了CGLIB代理,那么问题就很显著了,此类被AOP做了代理,在AOP中将此类移除就能够了。
失常的pojo
被代理的pojo
AOP配置
将WebSocketServer类从AOP中移除,我的项目即可失常启动
@AfterThrowing(pointcut = "execution( * com.smec.fin.service..*.*(..)) && !execution(* com.smec.fin.service.impl.WebSocketServer.*(..))", throwing = "e") public void afterThrowing(JoinPoint joinPoint, Throwable e) { logger.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), e.getCause() != null ? e.getCause() : "NULL"); }