Конфликт контекста приложения Spring и контекста сервлета
Я знаю, что мне нужно зарегистрировать аннотированные классы@Controller
в контексте моего сервлета, чтобы сделать мое веб-приложение доступным. Обычно я делаю это следующим образом:
@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);
}
}
Мне нужно использовать этот сервис в некоторых других сервисах (autowire его). И теперь ям в тупике:
Если я'я пытаюсь создатьTimeServiceWs
bean-компонент внутри корневого контекста приложения, как и ожидалосьне вижуSimpMessagingTemplate
боб и броскиNoSuchBeanDefinitionException
Если я'я пытаюсь создатьTimeServiceWs
бин внутри контекста сервлета, то яя не могу автоматически подключить его к какой-либо другой службе, потому что корневой контекст может 'не вижу контекста бина сервлета (насколько я знаю)Если я перенесу все свои конфигурации в контекст сервлета, все компоненты будут успешно созданы, но я получу следующее исключение:java.lang.IllegalStateException: No WebApplicationContext found
и может'т доступ к моему веб-приложениюЧто я должен сделать? Что должно быть внутри корневого контекста? Что должно быть внутри контекста сервлета? И не могли бы вы еще раз уточнить разницу между этими контекстами?
Если вам понадобится дополнительная информация, просто дайте мне знать.