您的位置:首页 > 编程语言 > Java开发

【WEB】struts2整合spring原理以及源码剖析

2015-04-14 10:33 281 查看

一、原理概述

1. struts和spring整合,到底是谁整合谁?

是struts整合spring还是spring整合struts?这个问题重要吗?有必要讨论吗?

说struts整合spring,是因为struts比spring晚出现,所以只能是struts整合spring,貌似有一定的道理,但是不绝对正确。一个框架的流行取决于市场的接受程度,在struts很流行的前提下如果spring没有那么流行,那么无论是谁先出现谁后出现,恐怕spring为了自身的发展也会要去整合struts。

事实上的确是struts整合spring,但原因不是两个框剪出现的时间,而是两个框架提供了什么样的jar包。struts和spring整合后的运行环境不再只是单纯的JVM,而是WEB服务器,spring提供接入web的jar包是spring-web-x.x.x.RELEASE.jar,这个jar包的作用是将spring容器整合到WEB容器(见上一篇博文:《【Spring】Spring&WEB整合原理及源码剖析》),而struts提供的jar包是struts2-spring-plugin-x.x.x.x.jar,这个jar包里面改写了struts默认的对象工厂ObjectFactory,重新提供了一个新的对象工厂SpringObjectFactory,在这个工厂类里面你会看到出现spring框架中的类和对象,也就是struts通过这个jar包,把spring整合到了自己的框架里面,从而享受spring带来的便利。

2. struts是表现层MVC框架,而spring是业务层框架,struts整合spring,整合的到底是什么东西?

spring的核心是IOC和AOP(加多spring MVC和spring JDBC/事务),通俗的讲spring是框架的框架,他自己本身就是一个框架,但是他主要服务于其他框架。所以整合的核心就落点于spring的”服务“,spring为其他框架提供了什么样的服务?换言之,struts需要把什么东西托管给spring,从而获得更好的服务?


这一切谜题的答案就在struts框架提供整合spring的jar包之中:struts2-spring-plugin-x.x.x.x.jar。

这个jar包里面主要提供了SpringObjectFactory这个对象工厂,将原来struts对象工厂创建的实例交由spring IOC容器来创建和管理,从而首先享受了spring提供的IOC服务,因为从spring容器获得bean实例,从而又享受到了spring带来的其他诸如AOP、spring JDBC、spring事务管理等等服务。


所以,struts整合spring,是将spring的IOC整合到了自己的框架里面!

3. 整合步骤如概述

1. spring整合web,参看上一篇文章《【Spring】Spring&WEB整合原理及源码剖析》,主要由spring框架提供的jar包完成:spring-web-x.x.x.RELEASE.jar;

2. struts接入spring,将原来struts自己ObjectFactory创建的对象交由SpringObjectFactory来创建并缓存,主要由struts提供的jar包完成:struts2-spring-plugin-2.3.15.3.jar;

3. 最后,不要忘记struts的Action托管给spring,并且设置scope="ptototype";



二、实现细节&源码code实现

一句话struts整合spring:配置好web.xml(spring接入web,struts配置过滤器,剩下的交由两个jar包处理即可,是不是太TM的简单了?一切就是那么简单!),导入spring-web-x.x.x.RELEASE.jar,导入struts2-spring-plugin-2.3.15.3.jar,完成!

因为spring整合web上一次有过详细讨论,这一次主要讨论的是struts提供的jar包,也即struts对象工厂的替换。

1. 怎么实现工厂替换

struts默认的对象工厂是ObjectFactory,该工厂提供了在struts启动的时候实例化、装配bean的操作,主要是struts-default.xml中配好的bean/result/interceptor(缓存在ContainerImpl中),以及运行期的action及其参数注入。

SpringObjectFactory是ObjectFactory的子类,要想替换ObjectFactory,利用面向对象三大特性“多态”即可完成。要想完成替换,需要告知struts你的意图,替换的开关在最先加载的框架起配置文件default.properties中,即struts.objectFactory = spring。要想打开这个开关,你可以在struts-default.xml、struts-plugin.xml、struts.xml、struts.properties、web.xml总共五处完成操作,当然struts-default.xml和struts-plugin.xml是不能修改的,除非系统已经提供。毋庸置疑,既然struts整合spring,那么struts提供的整合插件必然打开了这个开关,不需要你再手动配置。

struts.xml中对象工厂替换配置内容,默认开关是关闭的。

### if specified, the default object factory can be overridden here
### Note: short-hand notation is supported in some cases, such as "spring"
###       Alternatively, you can provide a com.opensymphony.xwork2.ObjectFactory subclass name here
# struts.objectFactory = spring(看我看我看我看我看我,我就是开关,默认是关闭的,已经在struts-spring-plugin-xxx.jar中打开了,引入了该jar包即可,剩下的什么也不用操作)

### specifies the autoWiring logic when using the SpringObjectFactory.
### valid values are: name, type, auto, and constructor (name is the default)
struts.objectFactory.spring.autoWire = name

### indicates to the struts-spring integration if Class instances should be cached
### this should, until a future Spring release makes it possible, be left as true
### unless you know exactly what you are doing!
### valid values are: true, false (true is the default)
struts.objectFactory.spring.useClassCache = true

### ensures the autowire strategy is always respected.
### valid values are: true, false (false is the default)
struts.objectFactory.spring.autoWire.alwaysRespect = false
struts-plugin.xml,struts提供的整合jar包配置文件内容,可以看到开关已经打开, <constant name="struts.objectFactory" value="spring" />。

<?xml version="1.0" encoding="UTF-8" ?>
<!--
/*
 * $Id: struts-plugin.xml 1221225 2011-12-20 12:22:28Z jogep $
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0  *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
-->
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">
    
<struts>
    <bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />
    
    <!--  Make the Spring object factory the automatic default -->
    <constant name="struts.objectFactory" value="spring" />

    <constant name="struts.class.reloading.watchList" value="" />
    <constant name="struts.class.reloading.acceptClasses" value="" />
    <constant name="struts.class.reloading.reloadConfig" value="false" />

    <package name="spring-default">
        <interceptors>
            <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
        </interceptors>
    </package>    
</struts>


2. 替换了哪些内容

struts的默认工厂ObjectFactory里面提供了一堆的buildXXX方法,但是所有的buildXXX方法最终都通过调用buildBean来实现。其中涉及类的关系统如下所示。



更多细节,请参看源码注解。

package org.apache.struts2.spring;

import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.spring.SpringObjectFactory;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.StrutsConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.ServletContext;

/**
 * Struts object factory that integrates with Spring.
 * <p/>
 * Spring should be loaded using a web context listener
 * <code>org.springframework.web.context.ContextLoaderListener</code> defined in <code>web.xml</code>.
 *
 */
public class StrutsSpringObjectFactory extends SpringObjectFactory {
    private static final Logger LOG = LoggerFactory.getLogger(StrutsSpringObjectFactory.class);

    //@Inject
    //public StrutsSpringObjectFactory(
    //        @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE,required=false) String autoWire,
    //        @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE,required=false) String useClassCacheStr,
    //        @Inject ServletContext servletContext) {
    //    this(autoWire, "false", useClassCacheStr, servletContext);
    //}

    /**
     * Constructs the spring object factory
     * @param autoWire The type of autowiring to use
     * @param alwaysAutoWire Whether to always respect the autowiring or not
     * @param useClassCacheStr Whether to use the class cache or not
     * @param servletContext The servlet context
     * @since 2.1.3
     */
    @Inject
    public StrutsSpringObjectFactory(
            @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE,required=false) String autoWire,
            @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE_ALWAYS_RESPECT,required=false) String alwaysAutoWire,
            @Inject(value=StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE,required=false) String useClassCacheStr,
            @Inject ServletContext servletContext,
            @Inject(StrutsConstants.STRUTS_DEVMODE) String devMode,
            @Inject Container container) {
          
        super();
        boolean useClassCache = "true".equals(useClassCacheStr);
        if (LOG.isInfoEnabled()) {
            LOG.info("Initializing Struts-Spring integration...");
        }
		/**
		* 从ServletContext中获取spring IOC容器
		* 	该容器在spring web的jar包中创建完成并放入ServletContext,具体代码在ContextLoader类中
		*/
        Object rootWebApplicationContext =  servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

        if(rootWebApplicationContext instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException)rootWebApplicationContext;
            LOG.fatal(runtimeException.getMessage());
            return;
        }
		
		//强转成父类型
        ApplicationContext appContext = (ApplicationContext) rootWebApplicationContext;
        if (appContext == null) {
            // uh oh! looks like the lifecycle listener wasn't installed. Let's inform the user
            String message = "********** FATAL ERROR STARTING UP STRUTS-SPRING INTEGRATION **********\n" +
                    "Looks like the Spring listener was not configured for your web app! \n" +
                    "Nothing will work until WebApplicationContextUtils returns a valid ApplicationContext.\n" +
                    "You might need to add the following to web.xml: \n" +
                    "    <listener>\n" +
                    "        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>\n" +
                    "    </listener>";
            LOG.fatal(message);
            return;
        }
        
		//从struts容器中获取一些开发模式的实例
        String watchList = container.getInstance(String.class, "struts.class.reloading.watchList");
        String acceptClasses = container.getInstance(String.class, "struts.class.reloading.acceptClasses");
        String reloadConfig = container.getInstance(String.class, "struts.class.reloading.reloadConfig");
		
		//对于开发模式的处理
        if ("true".equals(devMode)
                && StringUtils.isNotBlank(watchList)
                && appContext instanceof ClassReloadingXMLWebApplicationContext) {
            //prevent class caching
            useClassCache = false;

            ClassReloadingXMLWebApplicationContext reloadingContext = (ClassReloadingXMLWebApplicationContext) appContext;
            reloadingContext.setupReloading(watchList.split(","), acceptClasses, servletContext, "true".equals(reloadConfig));
            if (LOG.isInfoEnabled()) {
        	LOG.info("Class reloading is enabled. Make sure this is not used on a production environment!", watchList);
            }

            setClassLoader(reloadingContext.getReloadingClassLoader());

            //we need to reload the context, so our isntance of the factory is picked up
            reloadingContext.refresh();
        }
		/**
		* 为SpringObjectFactory设置容器(替代ContainerImpl)
		* 	方法setApplicationContext来自父类SpringObjectFactory
		*	SpringObjectFactory中方法重写了ApplicationContextAware(spring中的类)
		* 此时,struts开始和spring发生耦合,struts获得了spring的IOC容器
		*/
        this.setApplicationContext(appContext);
		/**
		* 开启spring工厂开关后,struts配置文件default.properties中关于springObjectFactory开始生效
		* 	默认是按照name进行装配	struts.objectFactory.spring.autoWire = name
		*	提供的装配类型有:
		*	name(名字装配)、type(类型装配)、constructor(按构造器装配)、auto(自动装配)、no(不自动装配)
		*/
        int type = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;   // default
        if ("name".equals(autoWire)) {
            type = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
        } else if ("type".equals(autoWire)) {
            type = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
        } else if ("auto".equals(autoWire)) {
            type = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
        } else if ("constructor".equals(autoWire)) {
            type = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
        } else if ("no".equals(autoWire)) {
            type = AutowireCapableBeanFactory.AUTOWIRE_NO;
        }
        this.setAutowireStrategy(type);

        this.setUseClassCache(useClassCache);

        this.setAlwaysRespectAutowireStrategy("true".equalsIgnoreCase(alwaysAutoWire));

        if (LOG.isInfoEnabled()) {
            LOG.info("... initialized Struts-Spring integration successfully");
        }
    }
}
package com.opensymphony.xwork2.spring;

import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.UnsatisfiedDependencyException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.HashMap;
import java.util.Map;

/**
 * Simple implementation of the ObjectFactory that makes use of Spring's application context if one has been configured,
 * before falling back on the default mechanism of instantiating a new class using the class name. <p/> In order to use
 * this class in your application, you will need to instantiate a copy of this class and set it as XWork's ObjectFactory
 * before the xwork.xml file is parsed. In a servlet environment, this could be done using a ServletContextListener.
 *
 * @author Simon Stewart (sms@lateral.net)
 */
public class SpringObjectFactory extends ObjectFactory implements ApplicationContextAware {
    private static final Logger LOG = LoggerFactory.getLogger(SpringObjectFactory.class);

    protected ApplicationContext appContext;//spring IOC容器
    protected AutowireCapableBeanFactory autoWiringFactory;//spring中用于自动装配的类
    protected int autowireStrategy = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;//默认按照name进行装配,配置项在default.properties中
    private final Map<String, Object> classes = new HashMap<String, Object>();
    private boolean useClassCache = true;
    private boolean alwaysRespectAutowireStrategy = false;

    @Inject(value="applicationContextPath",required=false)
    public void setApplicationContextPath(String ctx) {
        if (ctx != null) {
            setApplicationContext(new ClassPathXmlApplicationContext(ctx));
        }
    }

    /**
     * Set the Spring ApplicationContext that should be used to look beans up with.
     *
     * @param appContext The Spring ApplicationContext that should be used to look beans up with.
     */
    public void setApplicationContext(ApplicationContext appContext)
            throws BeansException {
        this.appContext = appContext;
        autoWiringFactory = findAutoWiringBeanFactory(this.appContext);
    }

    /**
     * Sets the autowiring strategy
     * 装配策略
     * @param autowireStrategy
     */
    public void setAutowireStrategy(int autowireStrategy) {
        switch (autowireStrategy) {
            case AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT:
                if (LOG.isInfoEnabled()) {
                    LOG.info("Setting autowire strategy to autodetect");
                }
                this.autowireStrategy = autowireStrategy;
                break;
            case AutowireCapableBeanFactory.AUTOWIRE_BY_NAME:
                if (LOG.isInfoEnabled()) {
                    LOG.info("Setting autowire strategy to name");
                }
                this.autowireStrategy = autowireStrategy;
                break;
            case AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE:
                if (LOG.isInfoEnabled()) {
                    LOG.info("Setting autowire strategy to type");
                }
                this.autowireStrategy = autowireStrategy;
                break;
            case AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR:
                if (LOG.isInfoEnabled()) {
                    LOG.info("Setting autowire strategy to constructor");
                }
                this.autowireStrategy = autowireStrategy;
                break;
            case AutowireCapableBeanFactory.AUTOWIRE_NO:
                if (LOG.isInfoEnabled()) {
                    LOG.info("Setting autowire strategy to none");
                }
                this.autowireStrategy = autowireStrategy;
                break;
            default:
                throw new IllegalStateException("Invalid autowire type set");
        }
    }

    public int getAutowireStrategy() {
        return autowireStrategy;
    }

    /**
     * If the given context is assignable to AutowireCapbleBeanFactory or contains a parent or a factory that is, then
     * set the autoWiringFactory appropriately.
     *
     * @param context
     */
    protected AutowireCapableBeanFactory findAutoWiringBeanFactory(ApplicationContext context) {
        if (context instanceof AutowireCapableBeanFactory) {
            // Check the context
            return (AutowireCapableBeanFactory) context;
        } else if (context instanceof ConfigurableApplicationContext) {
            // Try and grab the beanFactory
            return ((ConfigurableApplicationContext) context).getBeanFactory();
        } else if (context.getParent() != null) {
            // And if all else fails, try again with the parent context
            return findAutoWiringBeanFactory(context.getParent());
        }
        return null;
    }

    /**
     * Looks up beans using Spring's application context before falling back to the method defined in the {@link
     * ObjectFactory}.
     *
     * @param beanName     The name of the bean to look up in the application context
     * @param extraContext
     * @return A bean from Spring or the result of calling the overridden
     *         method.
     * @throws Exception
     */
    @Override
    public Object buildBean(String beanName, Map<String, Object> extraContext, boolean injectInternal) throws Exception {
        Object o;
        
        if (appContext.containsBean(beanName)) {
            o = appContext.getBean(beanName);
        } else {
            Class beanClazz = getClassInstance(beanName);
            o = buildBean(beanClazz, extraContext);
        }
        if (injectInternal) {
            injectInternalBeans(o);
        }
        return o;
    }

    /**
     * @param clazz
     * @param extraContext
     * @throws Exception
	 * 所有创建和装配对象的最终方法,也是最重要的方法
	 * 	不再由struts创建并缓存
	 * 	而是由spring的自动装配类autoWiringFactory来创建和装配,最后
     */
    @Override
    public Object buildBean(Class clazz, Map<String, Object> extraContext) throws Exception {
        Object bean;

        try {
            // Decide to follow autowire strategy or use the legacy approach which mixes injection strategies
            if (alwaysRespectAutowireStrategy) {
                // Leave the creation up to Spring
                bean = autoWiringFactory.createBean(clazz, autowireStrategy, false);
                injectApplicationContext(bean);
                return injectInternalBeans(bean);//放入容器
            } else {
                bean = autoWiringFactory.autowire(clazz, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
                bean = autoWiringFactory.applyBeanPostProcessorsBeforeInitialization(bean, bean.getClass().getName());
                // We don't need to call the init-method since one won't be registered.
                bean = autoWiringFactory.applyBeanPostProcessorsAfterInitialization(bean, bean.getClass().getName());
                return autoWireBean(bean, autoWiringFactory);//自动装配bean,并放入容器
            }
        } catch (UnsatisfiedDependencyException e) {
            if (LOG.isErrorEnabled())
                LOG.error("Error building bean", e);
            // Fall back
            return autoWireBean(super.buildBean(clazz, extraContext), autoWiringFactory);
        }
    }

    public Object autoWireBean(Object bean) {
        return autoWireBean(bean, autoWiringFactory);
    }

    /**
     * @param bean
     * @param autoWiringFactory
     */
    public Object autoWireBean(Object bean, AutowireCapableBeanFactory autoWiringFactory) {
        if (autoWiringFactory != null) {
            autoWiringFactory.autowireBeanProperties(bean,
                    autowireStrategy, false);
        }
        injectApplicationContext(bean);

        injectInternalBeans(bean);

        return bean;
    }

    private void injectApplicationContext(Object bean) {
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(appContext);
        }
    }

    public Class getClassInstance(String className) throws ClassNotFoundException {
        Class clazz = null;
        if (useClassCache) {
            synchronized(classes) {
                // this cache of classes is needed because Spring sucks at dealing with situations where the
                // class instance changes
                clazz = (Class) classes.get(className);
            }
        }

        if (clazz == null) {
            if (appContext.containsBean(className)) {
                clazz = appContext.getBean(className).getClass();
            } else {
                clazz = super.getClassInstance(className);
            }

            if (useClassCache) {
                synchronized(classes) {
                    classes.put(className, clazz);
                }
            }
        }

        return clazz;
    }

    /**
     * This method sets the ObjectFactory used by XWork to this object. It's best used as the "init-method" of a Spring
     * bean definition in order to hook Spring and XWork together properly (as an alternative to the
     * org.apache.struts2.spring.lifecycle.SpringObjectFactoryListener)
     * @deprecated Since 2.1 as it isn't necessary
     */
    @Deprecated public void initObjectFactory() {
        // not necessary anymore
    }

    /**
     * Allows for ObjectFactory implementations that support
     * Actions without no-arg constructors.
     *
     * @return false
     */
    @Override
    public boolean isNoArgConstructorRequired() {
        return false;
    }

    /**
     *  Enable / disable caching of classes loaded by Spring.
     *
     * @param useClassCache
     */
    public void setUseClassCache(boolean useClassCache) {
        this.useClassCache = useClassCache;
    }

    /**
     * Determines if the autowire strategy is always followed when creating beans
     *
     * @param alwaysRespectAutowireStrategy True if the strategy is always used
     */
    public void setAlwaysRespectAutowireStrategy(boolean alwaysRespectAutowireStrategy) {
        this.alwaysRespectAutowireStrategy = alwaysRespectAutowireStrategy;
    }
}


3. 带来的效果

struts中的Action, Inteceptor, Result, Converter, Validator的创建和装配交由Spring,struts自己创建的对象允许spring装配。

4. 启动顺序

web容器、spring、struts三者的启动顺序,web容器(ServletContext)会最先启动,接着是spring,最后才是struts。

从启动类型来看。web容器的启动依赖于web.xml,而xml中的配置加载顺序是context-param>listener>filter>servlet,context-param加载后会以KV形式set到web容器ServletContext中,所以web容器最先启动;接着是listener,spring 2.4以后只提供了listener方式整合web,因此接着启动的是spring;最后是通过filter实现拦截HTTP的struts。

从依赖关系来看。struts启动依赖于对象工厂,而struts的对象工厂依赖于spring的WebApplicationContext,而spring的WebApplicationContext的创建则依赖于ServletContext,因此最先启动的是web容器,接着是spring和struts。

5. 伪类名

action要交由spring创建和注入,则需要在struts中配置的时候起class属性采用伪类名,即applicationContext.xml中bean的属性id,否则是由struts自己创建action,但是是spring来装配。

三、整合实现范例

如上所述,一句话struts整合spring,配置文件的参考范例如下,亲测无误。

1. web.xml

<span style="font-family:Microsoft YaHei;"><?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>ss01</display-name>
	
	<!-- 
		1. context-param中的param会以KV的方式存入ServletContext
		2. 如果applicationContext.xml没有放在默认路径/WEB-INF/applicationContext.xml(定义在XmlWebApplicationContext中),
		则需要配置contextConfigLocation(定义在ContextLoader中)
		3. 其value是配置文件applicationContext.xml的存放路径,如果不是web根目录下,则需要加classpath修饰
	 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<!-- 
		配置上下文加载侦听器:spring容器随着web容器的启动而加载
	 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<!-- 
		struts的侦听器:主要由init和doFilter完成,具体细节此处不再详谈
			struts初始化以及HTTP预处理主要对象:Dispatcher, PrepareOperations, ExecuteOperations
			struts执行主要对象:ActionProxy, ActionInvocation, Action, Intecepter, Result
			struts数据流主要对象:ValueStack和ActionContext
	 -->
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app></span>

2. applicationContext.xml

<span style="font-family:Microsoft YaHei;"><?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:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="
 http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans.xsd  http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd  http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop.xsd  http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx.xsd"> 	
	<bean id="loginAction" class="cn.wxy.action.LoginAction" scope="prototype" />
</beans></span>

3. struts.xml

<span style="font-family:Microsoft YaHei;"><?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
	<package name="user" namespace="/user" extends="struts-default">
		<action name="login" class="loginAction">
			<result>/WEB-INF/jsp/succ.jsp</result>
		</action>
	</package>
</struts></span>


附注:

本文如有错漏,烦请不吝指正,谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐