spring4.2.5+websocket+sockjs+stomp关于@MessageMapping注解的Controller类的方法不起作用的问题

想要在站点里弄个站点内部通讯的小功能,遇到一个很神奇的问题:

加了注解的@MessageMapping的Controller类的方法如:

@MessageMapping("/send/{id}")
@SendTo("/topic/{id}")
public MessageEntity sendMesage(@Payload MessageEntity message){

     return message;

}

但是前端使用 :

stompClient.send('/app/send/you',{},JSON.stringify({sender:'me',type:'E'}));

前端页面发送没异常,后台也没异常,就是请求不到 上述的Controller加了注解的方法上面。

上网搜索一圈是结果,发现有个国外站点的问题和我这个类似

链接:

Spring 4 WebSocket + sockJS:. Getting "No matching method found" in trace and @MessageMapping handler not invoked - Stack Overflow

其中有一个回答有点接近答案:

WebSocketConfig configuration class should be loaded as part of Servlet configuration, not Root configuration.

Make sure WebSocketConfig.class returned from your implementation of AbstractAnnotationConfigDispatcherServletInitializer.getRootConfigClasses()

If you put it in root context, everything will work fine, you can use SimpMessagingTemplate, broker relay, but not @MessageMapping in controllers.

You can set breakpoint in WebSocketAnnotationMethodMessageHandler.initControllerAdviceCache() and check what beanss are loaded in context. If no @Controller marked bean in that method, @MessageMapping will not work.

这段话的意思是:

WebSocketConfig 配置类应该被当做Servlet配置加载,而不是 Root配置。请确保WebSocketConfig.class 从你的AbstractAnnotationConfigDispatcherServletInitializer.getRootConfigClasses()实现中返回。

你可以在WebSocketAnnotationMethodMessageHandler.initControllerAdviceCache()方法中设置断点查看上下文有哪些beans被加载,如果没有 @Controler标记的 bean 在方法里。@MessageMapping 将不会发挥作用。


但据我观察,我的这个类Controller是加载了的,而且其中的 一些action方法还可以执行。那问你可能就不是出在这个Controller没加载的问题。

难道是WebSocketConfig加载顺序有问题?我就按网上其他人的答案,重写 集成 AbstractAnnotationConfigDispatcherServletInitializer 这个类的方法。将WebSocketConfig.class 在 getServletConfigClasses 方法里返回。

然后测试后并没啥卵用。依旧是访问不到。


正在我要崩溃的时候,突然我想到了,加了注解@Controller类均被SpringMVC实例化加载的。他肯定不知道 @MessageMapping 注解是什么意思。而且这些消息通讯的动态接口要预先在WebSocket装配好才对呀。没装配的话,是不是WebSocketConfig在装配的时候,没有加载到这个Controller类,所以里面的加了注解 @MessageMapping的接口路径没有被注册上呢。

鬼使神差的在 WebSocketConfig配置类上加了 @CompanentScan(basePackageClasses="ChatController.class") 在上面: 

启动后,发现问你居然解决了。啊哈哈哈...这太扯淡了。