8

In my spring application, I have the following configuration classes for the spring environment:

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

}

I want add others dispatcher servlet to my application. My first idea was ass the following code to the classes above:

In WebAppInitializer.java

A new block like this, changing the names in the proper places:

// 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("/");

And add a new class like DispatcherConfig.java, with the name chosen in the code above.

My questions are:

1) First of all, my approach is the right way to add a new dispatcher servlet?

2) Second, if the answer for question 1 is 'yes', which names I should change in the WebAppInitializer?

3) In my controller(s), how I sinalize for which dispatcher servlet my requisition should go? My controllers use methods like the following for call a view:

@RequestMapping(value="view_mapping")
public method() {
    ModelAndView mav = new ModelAndView()
    mav.setViewName("view_name");
    return mav;
}
Kleber Mota
  • 8,521
  • 31
  • 94
  • 188

3 Answers3

16

You can have as many DispatcherServlets as you want. Basically what you need to do is duplicate the configuration and give the servlet a different name (else it will overwrite the previous one), and have some separate configuration classes (or xml files) for it.

Your controllers shouldn't care in which DispatcherServlet they run neither should you include code to detect that (what if you add another, and another you would need to keep modifying your controllers to fix that).

However while you can have multiple servlets in general there isn't much need for multiple servlets and you can handle it with a single instance of the DispatcherServlet.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • please, can you tell me what is advantage of using multiple dispatcherServlets? – Tahir Hussain Mir Jan 23 '17 at 08:36
  • okay. Actually, people downvote here for that kind of questions. I will still try – Tahir Hussain Mir Jan 23 '17 at 09:12
  • The question has now been asked: https://stackoverflow.com/q/53533321/14955 https://stackoverflow.com/q/12059307/14955 – Thilo Nov 29 '18 at 06:57
  • (1) Can you please explain a simple use case scenario of using more than one DispatcherServlets in a single application? (2) Can it affect the performance of the application in any way? (3) Is it an advantage/disadvantage to implement more than one DispatcherServlets in a single application? What makes me ask this is, if there are more than 1 DS's will it act like a server-side-load-balancer? So that there may be even routing/distribution. Please correct me if I'm wrong, but ideally, there should be only 1 DS in an application. That's the reason I am curious to find out the above said. – Aniket Jul 16 '21 at 04:06
  • Please don't use comments to ask a question, you should ask a proper question instead. – M. Deinum Jul 16 '21 at 06:48
2

If you are using spring 3.2 or above you can go with below code.

Make different class for all the dispacher servlet with overriding getServletName() method, to avoid same name conflicts.

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";
         }
    }
Jekin Kalariya
  • 3,475
  • 2
  • 20
  • 32
  • 4
    Aren't the root config classes common for all dispatcher servlets? What does that fact imply in your example? – croraf Dec 16 '16 at 22:14
  • for creating several web app initializers, each web app initializer class should implement the `WebApplicationInitializer` interface rather than extending the `AbstractAnnotationConfigDispatcherServletInitializer` class – jcflorezr Mar 06 '18 at 20:03
0

We can have to multiple Dispatcher Servlets, like we can have 2(or more) DispatcherServlet with 2( or more) servlets name.So the D1 and D2 could map to different URL path.Example:-

<!-- 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 path could be mapped like :-

<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>
wonder
  • 193
  • 1
  • 13