gpt4 book ai didi

java - Spring根应用上下文和servlet上下文混淆

转载 作者:IT老高 更新时间:2023-10-28 13:51:52 24 4
gpt4 key购买 nike

我知道我需要在我的 servlet 上下文中注册使用 @Controller 注释的类,以使我的 web 应用程序可访问。通常,我会这样做:

@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 放到 servlet 上下文中。这是我的 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 it)。现在我陷入了僵局:

  1. 如果我试图在根应用程序上下文中创建 TimeServiceWs bean,正如预期的那样,它看不到 SimpMessagingTemplate bean 并抛出 NoSuchBeanDefinitionException
  2. 如果我试图在 servlet 上下文中创建 TimeServiceWs bean,那么我无法将其 Autowiring 到任何其他服务,因为根上下文看不到 servlet 上下文 bean(至我知道)
  3. 如果我将所有配置移至 servlet 上下文,则所有 bean 都已成功创建,但出现以下异常:java.lang.IllegalStateException: No WebApplicationContext found and can't access my webapp

我该怎么办?根上下文中应该有什么? servlet 上下文中应该有什么?您能否再澄清一下这些上下文之间的区别?

如果您需要任何其他信息,请告诉我。

最佳答案

大多数 Spring MVC 应用程序都有一个包含所有服务层/DAO 层 bean 的根上下文,以及每个应用程序的 Spring Dispatcher servlet 一个 servlet 上下文,其中包含(至少)每个 servlet 的 Controller 。

这个想法是一个应用程序可能有多个 servlet 调度程序,例如一个用于 URL /shopping/*,另一个用于 URL /reporting/*,每个都有自己的一组 Controller 。

一个 servlet dispatcher 的 Controller 是相互隔离的,这意味着虽然它们也是 Spring bean,但它们不能相互注入(inject)。

根上下文中的服务层和 DAO bean 在所有 servlet 上下文中都是可见的,因此可以将服务层 bean 注入(inject)任何 Controller 中,但反之则不行。

根上下文被称为 Controller servlet 上下文的父级。

这都是一种将 bean 组彼此隔离的机制,以确保不会出现无意义的依赖关系。

鉴于此并通过问题:

  • 如果我尝试在根应用程序上下文中创建 TimeServiceWs bean,正如预期的那样,它看不到 SimpMessagingTemplate bean 并抛出 NoSuchBeanDefinitionException: 移动 SimpleMessagingTemplate对于根上下文,它是一个类似于 DAO 的 bean,可以在应用程序的任何地方使用,因此它应该位于共享的根上下文中。

  • 如果我尝试在 servlet 上下文中创建 TimeServiceWs bean,那么我无法将其 Autowiring 到任何其他服务:如果它打算 Autowiring 到其他服务,请离开然后在根上下文中。

    - 如果我将所有配置移动到 servlet 上下文,则所有 bean 都已成功创建,但我得到 java.lang.IllegalStateException: No WebApplicationContext found: 做相反的事情,基本上将所有 bean 移动到根上下文,并在 servlet 上下文中只保留特定于应用程序该部分的 bean,很多时候只保留 Controller 。

关于java - Spring根应用上下文和servlet上下文混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21319450/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com