Spring + Web MVC: dispatcher-servlet.xml vs. applicationContext.xml (plus shared security)

后端 未结 6 2026
有刺的猬
有刺的猬 2020-11-29 15:17

What is the correct way to use the two contexts: dispatcher-servlet.xml and applicationContext.xml? What goes where?

I want to write a fair

相关标签:
6条回答
  • 2020-11-29 15:33
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
      <display-name>TestPOC</display-name>
    
      <servlet>
            <servlet-name>mvc-dispatcher</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>mvc-dispatcher</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
        </context-param>
    
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
    </web-app>
    
    0 讨论(0)
  • 2020-11-29 15:39
    <mvc:annotation-driven />
    <mvc:default-servlet-handler />
    <mvc:resources mapping="/resources/**" location="/resources/" />
    
    <context:component-scan base-package="com.tridenthyundai.ains" />
    
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
    
    <bean id="messageSource" 
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="/WEB-INF/messages" />
    </bean>
    
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    
        <property name="prefix">
            <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
    

    0 讨论(0)
  • 2020-11-29 15:43

    The dispatcher-servlet.xml file contains all of your configuration for Spring MVC. So in it you will find beans such as ViewHandlerResolvers, ConverterFactories, Interceptors and so forth. All of these beans are part of Spring MVC which is a framework that structures how you handle web requests, providing useful features such as databinding, view resolution and request mapping.

    The application-context.xml can optionally be included when using Spring MVC or any other framework for that matter. This gives you a container that may be used to configure other types of spring beans that provide support for things like data persistence. Basically, in this configuration file is where you pull in all of the other goodies Spring offers.

    These configuration files are configured in the web.xml file as shown:

    Dispatcher Config

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>WEB-INF/spring/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

    Application Config

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/application-context.xml</param-value>
    </context-param>
    
    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    

    To configure controllers, annotate them with @Controller then include the following in the dispatcher-context.xml file:

    <mvc:annotation-driven/>
    <context:component-scan base-package="package.with.controllers.**" />
    
    0 讨论(0)
  • 2020-11-29 15:45
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd ">
    
        <mvc:annotation-driven />
        <mvc:default-servlet-handler />
        <mvc:resources mapping="/resources/**" location="/resources/" />
    
        <context:component-scan base-package="com.sapta.hr" />
    
        <bean id="multipartResolver"
            class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
    
        <bean id="messageSource" 
            class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
            <property name="basename" value="/WEB-INF/messages" />
        </bean>
    
        <bean id="viewResolver"
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    
            <property name="prefix">
                <value>/WEB-INF/pages/</value>
            </property>
            <property name="suffix">
                <value>.jsp</value>
            </property>
        </bean>
    
    </beans>
    
    0 讨论(0)
  • 2020-11-29 15:46
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:cache="http://www.springframework.org/schema/cache"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd  http://www.springframework.org/schema/cache 
            http://www.springframework.org/schema/cache/spring-cache-3.2.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    
            <mvc:annotation-driven/>
            <context:component-scan base-package="com.testpoc.controller"/>
    
            <bean id="ViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="ViewClass" value="org.springframework.web.servlet.view.JstlView"></property>
                <property name="prefix">
                    <value>/WEB-INF/pages/</value>
                </property>
                <property name="suffix">
                    <value>.jsp</value>
                </property>
            </bean>
    
    </beans>
    
    0 讨论(0)
  • 2020-11-29 15:54

    To add to Kevin's answer, I find that in practice nearly all of your non-trivial Spring MVC applications will require an application context (as opposed to only the spring MVC dispatcher servlet context). It is in the application context that you should configure all non-web related concerns such as:

    • Security
    • Persistence
    • Scheduled Tasks
    • Others?

    To make this a bit more concrete, here's an example of the Spring configuration I've used when setting up a modern (Spring version 4.1.2) Spring MVC application. Personally, I prefer to still use a WEB-INF/web.xml file but that's really the only xml configuration in sight.

    WEB-INF/web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
      
      <filter>
        <filter-name>openEntityManagerInViewFilter</filter-name>
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
      </filter>
      
      <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy
        </filter-class>
      </filter>
     
      <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    
      <filter-mapping>
        <filter-name>openEntityManagerInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
      
      <servlet>
        <servlet-name>springMvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <init-param>
          <param-name>contextClass</param-name>
          <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>com.company.config.WebConfig</param-value>
        </init-param>
      </servlet>
      
      <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
      </context-param>
    
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.company.config.AppConfig</param-value>
      </context-param>
    
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
    
      <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
      
      <session-config>
        <session-timeout>30</session-timeout>
      </session-config>
    
      <jsp-config>
        <jsp-property-group>
          <url-pattern>*.jsp</url-pattern>
          <scripting-invalid>true</scripting-invalid>
        </jsp-property-group>
      </jsp-config>
      
    </web-app>
    

    WebConfig.java

    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = "com.company.controller")
    public class WebConfig {
    
      @Bean
      public InternalResourceViewResolver getInternalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
      }
    }
    

    AppConfig.java

    @Configuration
    @ComponentScan(basePackages = "com.company")
    @Import(value = {SecurityConfig.class, PersistenceConfig.class, ScheduleConfig.class})
    public class AppConfig {
      // application domain @Beans here...
    }
    

    Security.java

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
      @Autowired
      private LdapUserDetailsMapper ldapUserDetailsMapper;
    
      @Override
        protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          .antMatchers("/").permitAll()
          .antMatchers("/**/js/**").permitAll()
          .antMatchers("/**/images/**").permitAll()
          .antMatchers("/**").access("hasRole('ROLE_ADMIN')")
          .and().formLogin();
    
        http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
        }
    
      @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
          auth.ldapAuthentication()
          .userSearchBase("OU=App Users")
          .userSearchFilter("sAMAccountName={0}")
          .groupSearchBase("OU=Development")
          .groupSearchFilter("member={0}")
          .userDetailsContextMapper(ldapUserDetailsMapper)
          .contextSource(getLdapContextSource());
        }
    
      private LdapContextSource getLdapContextSource() {
        LdapContextSource cs = new LdapContextSource();
        cs.setUrl("ldaps://ldapServer:636");
        cs.setBase("DC=COMPANY,DC=COM");
        cs.setUserDn("CN=administrator,CN=Users,DC=COMPANY,DC=COM");
        cs.setPassword("password");
        cs.afterPropertiesSet();
        return cs;
      }
    }
    

    PersistenceConfig.java

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(transactionManagerRef = "getTransactionManager", entityManagerFactoryRef = "getEntityManagerFactory", basePackages = "com.company")
    public class PersistenceConfig {
    
      @Bean
      public LocalContainerEntityManagerFactoryBean getEntityManagerFactory(DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
        lef.setDataSource(dataSource);
        lef.setJpaVendorAdapter(getHibernateJpaVendorAdapter());
        lef.setPackagesToScan("com.company");
        return lef;
      }
    
      private HibernateJpaVendorAdapter getHibernateJpaVendorAdapter() {
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setDatabase(Database.ORACLE);
        hibernateJpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.Oracle10gDialect");
        hibernateJpaVendorAdapter.setShowSql(false);
        hibernateJpaVendorAdapter.setGenerateDdl(false);
        return hibernateJpaVendorAdapter;
      }
    
      @Bean
      public JndiObjectFactoryBean getDataSource() {
        JndiObjectFactoryBean jndiFactoryBean = new JndiObjectFactoryBean();
        jndiFactoryBean.setJndiName("java:comp/env/jdbc/AppDS");
        return jndiFactoryBean;
      }
    
      @Bean
      public JpaTransactionManager getTransactionManager(DataSource dataSource) {
        JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
        jpaTransactionManager.setEntityManagerFactory(getEntityManagerFactory(dataSource).getObject());
        jpaTransactionManager.setDataSource(dataSource);
        return jpaTransactionManager;
      }
    }
    

    ScheduleConfig.java

    @Configuration
    @EnableScheduling
    public class ScheduleConfig {
      @Autowired
      private EmployeeSynchronizer employeeSynchronizer;
    
      // cron pattern: sec, min, hr, day-of-month, month, day-of-week, year (optional)
      @Scheduled(cron="0 0 0 * * *")
      public void employeeSync() {
        employeeSynchronizer.syncEmployees();
      }
    }
    

    As you can see, the web configuration is only a small part of the overall spring web application configuration. Most web applications I've worked with have many concerns that lie outside of the dispatcher servlet configuration that require a full-blown application context bootstrapped via the org.springframework.web.context.ContextLoaderListener in the web.xml.

    0 讨论(0)
提交回复
热议问题