背景

最近在我的项目上用了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");    }