【问题标题】:Working with multiple dispatcher servlets in a spring application在 Spring 应用程序中使用多个调度程序 servlet
【发布时间】:2014-05-27 19:14:21
【问题描述】:

在我的spring应用程序中,我有以下spring环境的配置类:

WebAppInitializer.java

@Order(value=1)
public class WebAppInitializer implements WebApplicationInitializer {

    @SuppressWarnings("resource")
    @Override
    public void onStartup(ServletContext container) {
      // Create the 'root' Spring application context
      AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
      rootContext.register(WebAppConfig.class);

      // Manage the lifecycle of the root application context
      //container.addListener(new ContextLoaderListener(rootContext));

      // Create the dispatcher servlet's Spring application context
      AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
      dispatcherContext.register(DispatcherConfig.class);

      // Register and map the dispatcher servlet
      ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
      dispatcher.setLoadOnStartup(1);
      dispatcher.addMapping("/");
    }

}

WebAppConfig.java

@EnableWebMvc
@EnableTransactionManagement(mode=AdviceMode.PROXY, proxyTargetClass=true)
@ComponentScan(value="spring.webapp.lojavirtual")
@Configuration
public class WebAppConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/bootstrap/**").addResourceLocations("/bootstrap/").setCachePeriod(31556926);
        registry.addResourceHandler("/extras/**").addResourceLocations("/extras/").setCachePeriod(31556926);
        registry.addResourceHandler("/jquery/**").addResourceLocations("/jquery/").setCachePeriod(31556926);
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

}

DispatcherConfig.java

@Controller
@Import(WebAppConfig.class)
public class DispatcherConfig {

    @Bean
    public ViewResolver jspResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

}

我想将其他调度程序 servlet 添加到我的应用程序中。我的第一个想法是将以下代码添加到上面的类中:

在 WebAppInitializer.java 中

像这样的新块,在适当的地方更改名称:

// Create the dispatcher servlet's Spring application context
      AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
      dispatcherContext.register(DispatcherConfig.class);

      // Register and map the dispatcher servlet
      ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
      dispatcher.setLoadOnStartup(1);
      dispatcher.addMapping("/");

并添加一个新类,如 DispatcherConfig.java,其名称在上面的代码中选择。

我的问题是:

1) 首先,我的做法是添加新的调度程序 servlet 的正确方法吗?

2) 其次,如果问题 1 的答案是“是”,我应该在 WebAppInitializer 中更改哪些名称?

3) 在我的控制器中,我如何将我的申请应该发送给哪个调度程序 servlet?我的控制器使用如下方法调用视图:

@RequestMapping(value="view_mapping")
public method() {
    ModelAndView mav = new ModelAndView()
    mav.setViewName("view_name");
    return mav;
}

【问题讨论】:

  • 您几乎总是不应该拥有多个 servlet,而应该将您需要的所有映射添加到一个中。为什么你认为你需要更多?

标签: java spring spring-mvc


【解决方案1】:

您可以拥有任意数量的DispatcherServlets。基本上,您需要做的是复制配置并给 servlet 一个不同的名称(否则它将覆盖前一个名称),并为其设置一些单独的配置类(或 xml 文件)。

您的控制器不应该关心它们在哪个DispatcherServlet 运行,也不应该包含代码来检测它(如果您添加另一个,而另一个您需要不断修改您的控制器来修复它)。

但是,虽然您通常可以拥有多个 servlet,但并不需要多个 servlet,您可以使用 DispatcherServlet 的单个实例来处理它。

【讨论】:

  • 请问,你能告诉我使用多个 dispatcherServlet 有什么好处吗?
  • 好的。实际上,人们在这里对这类问题投反对票。我还是会试试的
  • (1) 您能否解释一个在单个应用程序中使用多个 DispatcherServlet 的简单用例场景? (2) 它会以任何方式影响应用程序的性能吗? (3) 在单个应用程序中实现多个 DispatcherServlet 是否有利/不利?让我问的是,如果有超过 1 个 DS,它会像服务器端负载平衡器一样工作吗?这样甚至可能会有路由/分发。如果我错了,请纠正我,但理想情况下,应用程序中应该只有 1 个 DS。这就是我很想知道上面所说的原因。
  • 请不要用 cmets 来提问,你应该问一个正确的问题。
【解决方案2】:

如果您使用的是 spring 3.2 或更高版本,则可以使用以下代码。

为所有dispacher servlet创建不同的类并覆盖getServletName()方法,以避免同名冲突。

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

        @Override
        protected Class<?>[] getRootConfigClasses() {
            // TODO Auto-generated method stub
            return new Class<?>[] { RootConfig.class };
        }

        @Override
        protected Class<?>[] getServletConfigClasses() {
            // TODO Auto-generated method stub
            return new Class<?>[] { WebConfig.class };
        }

        @Override
        protected String[] getServletMappings() {
            // TODO Auto-generated method stub
            return new String[] { "/config1/*" };
        }
    }




 public class WebAppInitializer2 extends AbstractAnnotationConfigDispatcherServletInitializer {


        @Override
        protected Class<?>[] getRootConfigClasses() {
            // TODO Auto-generated method stub
            return new Class<?>[] { RootConfig.class };
        }

        @Override
        protected Class<?>[] getServletConfigClasses() {
            // TODO Auto-generated method stub
            return new Class<?>[] { WebConfig2.class };
        }

        @Override
        protected String[] getServletMappings() {
            // TODO Auto-generated method stub
            return new String[] { "/config2/*" };
        }

           @Override
            protected String getServletName() {
              // TODO Auto-generated method stub
             return "config2";
         }
    }

【讨论】:

  • 不是所有调度器 servlet 都通用的根配置类吗?这个事实在你的例子中意味着什么?
  • 为了创建多个Web应用初始化器,每个Web应用初始化器类都应该实现WebApplicationInitializer接口而不是扩展AbstractAnnotationConfigDispatcherServletInitializer
【解决方案3】:

我们可以拥有多个 Dispatcher Servlet,就像我们可以拥有 2 个(或更多)具有 2 个(或多个)servlet 名称的 DispatcherServlet。因此 D1 和 D2 可以映射到不同的 URL 路径。示例:-

<!-- configured by WEB-INF/mac-servlet.xml -->
<servlet>
    <servlet-name>mac</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- configured by WEB-INF/windows-servlet.xml -->
<servlet>
        <servlet-name>windows</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
</servlet>

URL 路径可以像这样映射:-

<servlet-mapping>
<servlet-name>mac</servlet-name>
<url-pattern>/mac/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>windows</servlet-name>
     <url-pattern>/windows/*</url-pattern>
</servlet-mapping>

【讨论】:

    猜你喜欢
    • 2012-08-17
    • 2015-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 2014-10-13
    • 2016-08-02
    • 2015-11-05
    相关资源
    最近更新 更多