Spring root应用程序上下文和servlet上下文混淆 [英] Spring root application context and servlet context confusion

查看:156
本文介绍了Spring root应用程序上下文和servlet上下文混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道我需要在我的servlet上下文中注册带注释 @Controller 的类,以使我的webapp可访问。 Usualy,我按照以下方式进行:

I know that I need to register classes annotated @Controller in my servlet context to make my webapp accesible. Usualy, I do it the following way:

@Configuration
@EnableWebMvc
@ComponentScan({"foo.bar.controller"})
public class WebConfig extends WebMvcConfigurerAdapter {
    //other stuff like ViewResolvers, MessageResolvers, MessageConverters, etc.
}

我添加到根应用程序上下文中的所有其他配置类。以下是我的dispetcher初始化程序通常如下所示:

All other configuration classes I added to my root application context. Here is how my dispetcher initializer usualy look like:

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示例:

But things are getting more interesting when I started to use WebSockets. To get websockets working you have to put WebSoketConfig.class to servlet context. Here is my example of 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");
    }

}

此外,我创建了一个用于向主题发送消息的服务:

Also, I've created a service to send a message to the topic:

@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);
    }
}

我需要在其他服务中使用此服务(自动装配它)。现在我陷入僵局:

I need to use this service in some other sevices (autowire it). And now I'm in deadlock:


  1. 如果我正在尝试创建 TimeServiceWs bean在根应用程序上下文中,正如预期的那样,它看不到 SimpMessagingTemplate bean并抛出 NoSuchBeanDefinitionException

  2. 如果我在servlet上下文中尝试创建 TimeServiceWs bean,那么我无法将其自动装配到任何其他服务,因为根上下文可以'请参阅servlet上下文bean(据我所知)

  3. 如果我将所有配置移动到servlet上下文,则会成功创建所有bean,但是我得到以下异常: java.lang.IllegalStateException:找不到WebApplicationContext 并且无法访问我的webapp

  1. If I'm trying to create TimeServiceWs bean inside root application context, as expected it doesn't see SimpMessagingTemplate bean and throws NoSuchBeanDefinitionException
  2. If I'm trying to create TimeServiceWs bean inside servlet context, then I'm unable to autowire it to any another service, because root context can't see servlet context beans(as far as I know)
  3. If I move all my configurations to servlet context, all beans are successfully created, but I get the following exception: java.lang.IllegalStateException: No WebApplicationContext found and can't access my webapp

什么是我该怎么办?在根上下文中应该是什么? servlet上下文应该是什么?您能再次澄清这些背景之间的区别吗?

What am I supposed to do? What should be inside root context? What should be inside servlet context? And could you please clarify the difference between these context one more time please?

如果您需要任何额外的信息,请告诉我。

If you will need any additional inforamtion, just let me know.

推荐答案

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

Most Spring MVC applications have one root context containing all service layer / DAO layer beans, and one servlet context per spring dispatcher servlet of the application, which contains (at least) the controllers of each servlet.

这个想法是一个应用程序可能有几个servlet调度程序,例如一个用于URL /购物/ * 和另一个URL / reporting / * ,每个都有自己的一套控制器。

The idea being that is that one application might have several servlet dispatchers, for example one for URL /shopping/* and the other for URL /reporting/*, each with it's own set of controllers.

一个servlet调度程序的控制器彼此隔离,这意味着虽然它们也是Spring bean,但它们不能互相注入。

The controllers of one servlet dispatcher are isolated from each other, meaning although they are also Spring beans, they cannot be injected in each other.

服务根上下文中的层和DAO bean在所有servlet上下文中都是可见的,因此服务层bean可以是注入任何控制器,但不是相反。

Service layer and DAO beans in the root context are visible in all servlet contexts, so Service layer beans can be injected in any controller, but not the other way around.

根上下文被称为控制器servlet上下文/上下文的父。

The root context is said to be the parent of the controller servlet context/contexts.

这都是一种将bean组彼此隔离的机制,以确保不存在任何不可靠的依赖关系。

It's all meant to be a mechanism of isolating groups of beans from each other to ensure no unmeant dependencies are possible.

鉴于此和通过问题:


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

  • If I'm trying to create TimeServiceWs bean inside root application context, as expected it doesn't see SimpMessagingTemplate bean and throws NoSuchBeanDefinitionException: Move the SimpleMessagingTemplate to the root context, it's a bean like a DAO that can be useful anywhere in the application so it should be in the shared root context.

如果我正在尝试在servlet上下文中创建TimeServiceWs bean,那么我无法将其自动装配到任何其他服务:如果要将其自动连接到其他服务,请保留i然后是根上下文。

If I'm trying to create TimeServiceWs bean inside servlet context, then I'm unable to autowire it to any another service: If it's meant to be autowired to other services, leave it in the root context then.

- 如果我将所有配置移动到servlet上下文,所有bean都已成功创建,但我得到了java.lang .IllegalStateException:找不到WebApplicationContext: 执行相反的操作,基本上将所有bean移动到根上下文,并在servlet上下文中仅保留特定于应用程序该部分的bean,多次控制器。

- If I move all my configurations to servlet context, all beans are successfully created, but I get java.lang.IllegalStateException: No WebApplicationContext found: Do the opposite, move basically all beans to the root context, and leave on the servlet context only the beans that are specific of that part of the application, many times only the controllers.

这篇关于Spring root应用程序上下文和servlet上下文混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆