zoukankan      html  css  js  c++  java
  • spring web.xml 难点配置总结【转】

    web.xml

    web.xml是所有web项目的根源,没有它,任何web项目都启动不了,所以有必要了解相关的配置.

    ContextLoderListener,ContextLoaderServlet,DispatcherServlet 区别

    本段引用自 : http://blog.csdn.net/feiyu8607/article/details/6532397

    web.xml中可以有三种方式来配置xml去加载Bean:

    org.springframework.web.context.ContextLoaderListener
    org.springframework.web.context.ContextLoaderServlet
    org.springframework.web.servlet.DispatcherServlet

    1. ContextLoaderListener 和 ContextLoaderServlet : 本质上是等同的,都是调用ContextLoader来加载web程序的上下文,加载完成以后,都是在ServletContext中,只不过listener需要Servlet2.3及以上支持。
    2. ContextLoaderListene与DispatcherServlet : 用DispatcherServlet载入的Bean是隶属于此Servlet的(所以spring可以配置多个分别拥有各自环境的DispatcherServlet),因此其他servlet无法获取到该Context。这一现象在buffalo配置时曾经出现(无法找到服务bean)。分析了buffalo和spring的源码后,将xml在ContextLoaderListener配置才得以解决。   所以web.xml文件中若只使用了一个dispatcherservlet来进行分发,则使用dispatcherservlet contextloaderlistener 来加载bean实例是等效的。

     各元素初始化过程

    本段引用自: http://blog.csdn.net/fupengyao/article/details/50605954

    初始化过程:

    1. 在启动Web项目时,容器(比如Tomcat)会读web.xml配置文件中的两个节点<listener>和<contex-param>。
    2. 接着容器会创建一个ServletContext(上下文),应用范围内即整个WEB项目都能使用这个上下文。
    3. 接着容器会将读取到<context-param>转化为键值对,并交给ServletContext。
    4. 容器创建<listener></listener>中的类实例,即创建监听(备注:listener定义的类可以是自定义的类但必须需要继承ServletContextListener)。
    5. 在监听的类中会有一个contextInitialized(ServletContextEvent event)初始化方法,在这个方法中可以通过event.getServletContext().getInitParameter("contextConfigLocation") 来得到context-param 设定的值。在这个类中还必须有一个contextDestroyed(ServletContextEvent event) 销毁方法.用于关闭应用前释放资源,比如说数据库连接的关闭。
    6. 得到这个context-param的值之后,你就可以做一些操作了.注意,这个时候你的WEB项目还没有完全启动完成.这个动作会比所有的Servlet都要早。

    所以 web.xml的加载过程是context-param >> listener  >> fileter  >> servlet

    context-param和init-param区别

    web.xml里面可以定义两种参数:
    (1)application范围内的参数,存放在servletcontext中,可以在servlet中通过getServletContext().getInitParameter("fruitName");

    在web.xml中配置如下:

    <context-param>  
               <param-name>fruitName</param-name>  
               <param-value>orange</param-value>  
    </context-param>

    (2)servlet范围内的参数,只能在servlet的init()方法中通过this.getInitParameter("fruitName")取得.

    在web.xml中配置如下:

    <servlet>  
        <servlet-name>PersonServlet</servlet-name>  
        <servlet-class>com.king.servlet.PersonServlet</servlet-class>  
        <init-param>  
           <param-name>fruitName</param-name>  
           <param-value>watermelon</param-value>  
        </init-param>  
        <load-on-startup>0</load-on-startup>  
    </servlet>  

    ContextLoderListener配置

    1. <param-name>contextConfigLocation</param-name>为固定写法.
    2. <param-value></param-value>中可以通过classpath或/WEB-INF 两种路径来加载xml文件.
    <!-- application范围内的参数,存放在ServletContext中 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                  <!--加入Spring总体配置文件-->
                classpath:config/applicationContext.xml
                <!-- /WEB-INF/classes/applicationContext.xml,/WEB-INF/classes/spring-srevlet.xml -->
            </param-value>
        </context-param>
    
        <!-- Spring监听器 -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>

    filter配置

    说明都在注释中

    <!--  配置Spring框架自身的拦截器 解决乱码问题  --> 
         <filter>
            <filter-name>SpringCharacterEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
            </init-param>
            <init-param>
                <param-name>forceEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter> 
        
        <filter-mapping>
            <filter-name>SpringCharacterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

    servlet配置

    说明都在注释中

        <servlet>
            <!-- DispatcherServlet会默认加载WEB-INF/[DispatcherServlet的Servlet名字]-servlet.xml配置文件 -->
            <servlet-name>springServlet</servlet-name>
            <!-- 把所有请求交给Spring Web MVC框架处理 -->
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <!-- 下面的配置最好直接在一行,且不要有空格,如果输成 "classpath:空格config/applicationContext.xml"  By朱青 -->
                <!-- 将会报错:org.xml.sax.SAXParseException: Content is not allowed in prolog.  -->
                <param-value>classpath:config/spring/springMVC.xml</param-value>
            </init-param>
             <load-on-startup>1</load-on-startup> 
            <!-- 1)load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法)。
            2)它的值必须是一个整数,表示servlet应该被载入的顺序
            2)当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet;
            3)当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载。
            4)正数的值越小,该servlet的优先级越高,应用启动时就越先加载。
            5)当值相同时,容器就会自己选择顺序来加载。 -->
        </servlet>
        <servlet-mapping>
            <servlet-name>springServlet</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>

    注解,定时任务等xml配置在哪加载合适?

    如果您把上面的段落都仔细阅读完了,会发现<servlet>配置如果<load-on-startup>没有手动配置,那么默认是servlet第一次被访问到才会去初始化的,如果该servlet等web应用启动后,过了很久都没有被访问,那么注释和定时任务都是不会启动的.

    而且我们应当小心listener和servlet重复加载注解引起的启动时间浪费  及  重复加载定时任务引起的数据冲突或不一致.

    所以注解,定时任务都建议放在全局监听的<context-param>中,而不建议放在<servlet>的<init-param>中.

    BeanFactory获取

    在EE web应用的servlet或controller中,可通过WebApplicationContextUtils来获取BeanFactory

    BeanFactory factory = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
    UserManager userManager = (UserManager)factory.getBean("userManager");

    在SE 标准应用中可直接通过java代码来获取BeanFactory

    BeanFactory factory = new ClassPathXmlApplictionContext("applicationContext.xml");

    真实环境web.xml,applicationContext.xml,springMVC.xml

    web.xml

    <?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_2_5.xsd" id="WebApp_ID" version="2.5">
    
    
        <display-name>SpringMVC</display-name>
        
        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
            <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    
        <error-page>
            <error-code>500</error-code>
    <!-- <exception-type>java.lang.NullPointerException</exception-type> -->   <!-- 还有一种配置是指定异常跳转 -->
            <location>/WEB-INF/jsp/common/errorPage.jsp</location>
        </error-page>
    
        <!-- 基础总配置文件位置 -->
        <!-- application范围内的参数,存放在ServletContext中 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                  <!--加入Spring总体配置文件-->
                classpath:config/applicationContext.xml
                <!-- /WEB-INF/classes/applicationContext.xml,/WEB-INF/classes/spring-srevlet.xml -->
            </param-value>
        </context-param>
    
        <!-- Spring监听器 -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        
        <!-- log4j configuration load -->
         <servlet> 
            <servlet-name>log4jInit</servlet-name> 
            <servlet-class>config.log.Log4jInit</servlet-class> 
            <init-param> 
                <param-name>log4j-config-file</param-name> 
                <param-value>/WEB-INF/classes/config/log/log4j.properties</param-value> 
            </init-param> 
            <load-on-startup>1</load-on-startup> 
        </servlet> 
        
        
            <!--  配置Spring框架自身的拦截器 解决乱码问题  --> 
         <filter>
            <filter-name>SpringCharacterEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
            </init-param>
            <init-param>
                <param-name>forceEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter> 
        
        <filter-mapping>
            <filter-name>SpringCharacterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        
        <servlet>
            <!-- DispatcherServlet会默认加载WEB-INF/[DispatcherServlet的Servlet名字]-servlet.xml配置文件 -->
            <servlet-name>springServlet</servlet-name>
            <!-- 把所有请求交给Spring Web MVC框架处理 -->
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <!-- 下面的配置最好直接在一行,且不要有空格,如果输成 "classpath:空格config/applicationContext.xml"  By朱青 -->
                <!-- 将会报错:org.xml.sax.SAXParseException: Content is not allowed in prolog.  -->
                <param-value>classpath:config/spring/springMVC.xml</param-value>
            </init-param>
             <load-on-startup>1</load-on-startup> 
            <!-- 1)load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法)。
            2)它的值必须是一个整数,表示servlet应该被载入的顺序
            2)当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet;
            3)当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载。
            4)正数的值越小,该servlet的优先级越高,应用启动时就越先加载。
            5)当值相同时,容器就会自己选择顺序来加载。 -->
        </servlet>
        <servlet-mapping>
            <servlet-name>springServlet</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>
        
        <!-- session超时 -->
        <session-config>
            <session-timeout>60</session-timeout>
        </session-config>
    </web-app>
    View Code

    applicationContext.xml

    <?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:aop="http://www.springframework.org/schema/aop"
        xmlns:util="http://www.springframework.org/schema/util" 
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
                               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"
                               >
        
        
        <!-- 启动spring注解,当自动扫描启动后,该配置可以去掉 -->
        <context:annotation-config />
        
        <!-- 自动扫描 --> 
        <context:component-scan base-package="com.bobo.code" />
        
        <!-- 6. 不同环境之间切换配置文件,可以读取该配置文件的${test.jdbc.username}代表key去取value ,
                [1]. 在Spring的Bean定义中使用
                [2]. 也可用于Spring在java代码中的注解
        -->
    <!--     <context:property-placeholder location="classpath:/config/database/mysql_jdbc.properties" />  -->
        <context:property-placeholder location="classpath:/config/database/oracle_jdbc_virtual_tele.properties" /> 
        
        <!--DataBase Configuration -->
        <!-- Spring的事务管理器有5个,都实现了PlatformTransactionManager接口 
            DataSourceTransactionManager                 JDBC事务管理器 
            HibernateTransactionManager                    Hibernate事务管理器 
            JdoTransactionManager                               JDO事务管理器 
            JtaTransactionManager                           JTA事务管理器      
            PersistenceBrokerTransactionManager    Apache的OJB事务管理器 -->
        <!-- <bean id="dataSource"    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> -->
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
            <property name="driverClassName" value="${dataSource.driverClassName}" />
            <property name="url" value="${dataSource.url}" />
            <property name="username" value="${dataSource.username}" />
            <property name="password" value="${dataSource.password}" />
        </bean> 
    
        <!-- 7. 配置myBatis客户端 -->
         <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">  
              <property name="configLocation">
                <value>classpath:config/mybatis/sqlmap-config.xml</value>
            </property>  
            <property name="dataSource" ref="dataSource" />  
        </bean>
    
        
        <bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
    
        
        
        <!-- 表示事务的开始策略。
            propagation="REQUIRED"  表示name的那个方法必须要在一个事务的环境中运行。
            read-only="true"  表示只读事务,就是不涉及到数据的修改,只是查询,这是对事务的优化。
         -->
        <!-- 配置事务的传播特性 -->
        <!-- 8. 配置事务的传播特性     -->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="*" propagation="REQUIRED" />
            </tx:attributes>
        </tx:advice>
    
      
      
        <!-- 10. 配置哪些类哪些方法使用事务<aop:pointcut id="allManagerMethod" expression="execution(* com.test.server.dao.*.impl.*(..))"/> -->
        <aop:config>
            <aop:pointcut                  id="allManagerMethod"     expression="execution(* com.bobo.code.service.impl.*.*(..))" />
            <aop:advisor  pointcut-ref="allManagerMethod" advice-ref = "txAdvice"/>
        </aop:config>
    
    
        
    
    
    
    
    
    
    
    
    
    
    
    
        
        <!-- 
        <import resource="classpath*:config/spring/dataSource.xml"/>
        <import resource="classpath*:config/spring/spring-bean.xml"/> -->
        <import resource="classpath*:config/spring/timetrigger.xml"/>
    </beans>
    View Code

    springMVC.xml

    <?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:aop="http://www.springframework.org/schema/aop" 
        xmlns:util="http://www.springframework.org/schema/util"  
        xmlns:tx="http://www.springframework.org/schema/tx" 
        xmlns:mvc="http://www.springframework.org/schema/mvc"  
        xmlns:context="http://www.springframework.org/schema/context" 
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-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 -->
    
        <!--  通过Web.xml的DispatcherServlet加载 -->
        
        <!-- 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的 -->
        <!-- <mvc:annotation-driven /> --> 
        
        <!-- 2. 组件扫描路径配置,让Spring 容器知道需要扫描哪些包路径下可以加载到容器中的类 -->
        <!--     多个扫描路径配置  base-package="com.app,com.core,JUnit4" 也可以写多份,一般直接写多份 -->
        <context:component-scan base-package="com.bobo.code" />
    
         <!-- 启动spring事务注解, $该启用必须在springMVC中,而不能在applicationContext.xml中配置,不然事务注解无效$
             也就是说只有这一行才能真正开启事务,单独地在类或方法上注解@Transaction只是作了事务标记而以-->  
         <tx:annotation-driven  transaction-manager="transactionManager" />
        <!-- 3. 处理在类级别上的@RequestMapping注解 -->
        
        <bean    class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
            <property name="interceptors">
                <list>
                    <!-- 多个拦截器,顺序执行 -->
                    <!-- <ref bean="SpringMVCInterceptor" /> -->
                    <!-- <ref bean="OpenSessionInViewInterceptor" /> -->
                </list>
            </property>
        </bean>
        
        <!-- 4.处理方法级别上的@RequestMapping注解 -->
        <bean 
                class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
            <property name="webBindingInitializer">
                <bean
                    class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
                    <property name="conversionService">
                        <bean
                            class="org.springframework.format.support.FormattingConversionServiceFactoryBean"></bean>
                    </property>
                </bean>
            </property>
        </bean>
    
        <!-- 5.对模型视图名称的解析,即给模型视图名称添加前后缀 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/" /> <!-- 让ModelAndView("jsp/teacher/listTeachers.jsp") 从/WEB-INF/目录下开始 -->
            <property name="suffix" value="" />
            <!-- <property name="suffix" value=".jsp" /> -->
            <!-- Spring内部资源解析类 -->
            <property name="viewClass"    value="org.springframework.web.servlet.view.InternalResourceView" />
        </bean>
        
        <!-- 6.异常解析器 -->  
      <bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
        <property name="exceptionMappings">  
          <props>  
            <prop key="org.springframework.web.multipart.MaxUploadSizeExceededException">jsp/common/exception</prop>  
          </props>  
        </property>  
      </bean>  
        
    </beans>
    View Code

    遗留问题(目前未知原因)

    我的一个spring 远程方法调用的 测试项目中,xml配置文件只能放在servlet中去访问才能生效,如果放在context中直接报404异常(404代表应该能访问到,但是不存在该servlet地址).   只能猜测,不用该servlet就无法让外部应用访问到该地址,也许地址必须通过servlet的暴露才能访问到.

  • 相关阅读:
    20201031
    20201028
    20201026
    20201027
    20201020
    ReentrantReadWriteLock原理分析
    java中Thread源码介绍
    CountDownLatch原理分析
    Semaphore原理分析
    AQS-共享模式分析
  • 原文地址:https://www.cnblogs.com/whatlonelytear/p/5848531.html
Copyright © 2011-2022 走看看