Я знаю, что мне нужно зарегистрировать классы, аннотированные @Controller
в моем контексте сервлета, чтобы сделать мой webapp доступным. Обычно, я делаю это следующим образом:
@Configuration
@EnableWebMvc
@ComponentScan({"foo.bar.controller"})
public class WebConfig extends WebMvcConfigurerAdapter {
//other stuff like ViewResolvers, MessageResolvers, MessageConverters, etc.
}
Все остальные классы конфигурации, которые я добавил в свой контекст корневого приложения. Вот как обычно выглядит мой инициализатор диспетчера:
public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class, ServiceConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
Но все становится интереснее, когда я начал использовать WebSockets. Чтобы работать в websockets, вы должны поместить WebSoketConfig.class в контекст сервлета. Вот мой пример WebSocketConfig:
@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").withSockJS();
}
@Override
public void configureClientInboundChannel(ChannelRegistration channelRegistration) {
channelRegistration.taskExecutor().corePoolSize(4).maxPoolSize(8);
}
@Override
public void configureClientOutboundChannel(ChannelRegistration channelRegistration) {
channelRegistration.taskExecutor().corePoolSize(4).maxPoolSize(8);
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue", "/topic");
registry.setApplicationDestinationPrefixes("/app");
}
}
Кроме того, я создал службу для отправки сообщения в тему:
@Service
public class TimeServiceWsImpl implements TimeServiceWs {
@Autowired
private SimpMessagingTemplate messagingTemplate;
@Override
public void sentCurrentTime() {
long currentTime = System.currentTimeMillis();
String destination = "/topic/chatty";
logger.info("sending current time to websocket /topic/time : " + currentTime);
this.messagingTemplate.convertAndSend(destination, currentTime);
}
}
Мне нужно использовать эту услугу в некоторых других услугах (autwire it). И теперь я в тупике:
- Если я пытаюсь создать
TimeServiceWs
bean внутри корневого контекста приложения, как ожидалось, он не видитSimpMessagingTemplate
bean и бросаетNoSuchBeanDefinitionException
- Если я пытаюсь создать
TimeServiceWs
bean внутри контекста сервлета, тогда я не могу его автоустановить к какой-либо другой службе, потому что корневой контекст не может видеть контекст сервлета beans (насколько я знаю) - Если я переместил все свои конфигурации в контекст сервлета, все beans будут успешно созданы, но я получаю следующее исключение:
java.lang.IllegalStateException: No WebApplicationContext found
и не могу получить доступ к моему webapp
Что я должен делать? Что должно быть внутри корневого контекста? Что должно быть внутри контекста сервлета? И не могли бы вы прояснить разницу между этим контекстом еще раз?
Если вам понадобится дополнительная информация, просто дайте мне знать.