@ServerEndpoint 和@Autowired

@ServerEndpoint and @Autowired

如何将字段自动连接到@ServerEndpoint。以下不起作用。

@Component
@ServerEndpoint("/ws")
public class MyWebSocket {   
    @Autowired
    private ObjectMapper objectMapper;
}

但是,如果我删除 @ServerEndpoint,它会正常工作。

我正在使用 spring 3.2.1 和 Java 7

JavaEE 7 规范说

@ServerEndpoint
The annotated class must have a public no-arg constructor.

看来您正在尝试集成 Spring 和 Java WebSocket API。由 @Component 注释的 class 被注册到 spring bean 并且其实例默认由 spring 作为单例管理。但是,由 @ServerEndpoint 注释的 class 注册到服务器端 WebSocket 端点,每次相应端点的 WebSocket 连接到服务器时,它的实例都由 JWA 实现创建和管理。因此,您不能同时使用这两个注释。

也许最简单的解决方法是使用 CDI 而不是 Spring。当然,你的服务器要支持CDI。

@ServerEndpoint("/ws")
public class MyWebSocket {   
    @Inject
    private ObjectMapper objectMapper;
}

如果这对您不可行,您可以通过使用您自己的 ServerEndpointConfig.Configurator. Then, you can instantiate the class by yourself and autowire it using an instance of BeanFactory or ApplicationContext. Actually, there is already similar answer to this usage. See that question and Martins' working example (Especially, a customized Configurator 版本与 [=28= 集成来拦截用 ServerEndpoint 注释的 class 的实例化过程]).

您实际上应该可以将此添加到您的 class。:

@PostConstruct
public void init(){
    SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}

可以使用 SpringConfigurator (spring 4) 解决此问题:

将配置器添加到您的 ServerEndpoint:

@ServerEndpoint(value = "/ws", configurator = SpringConfigurator.class)

需要 Maven 依赖项:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>${spring.version}</version>
</dependency>

我的解决方案是:

public WebsocketServletTest() {
      SpringApplicationListener.getApplicationContext().getAutowireCapableBeanFactory().autowireBean(this);
}

其中SpringApplicationListener是一个ApplicationContextAware,它将上下文存储在一个静态变量中