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

3Spring整合struts2

2016-07-09 16:55 399 查看
1Spring整合Struts2

web应用中配置spring容器

首先在Struts2中整合Spring需要另外加入的包:

struts2-spring-plugin-2.1.8.1.jar,spring.jar,log4j-1.2.15.jar

其中spring.jar是从下载的Spring包中的dist目录下。

struts2-spring-plugin.jar是在Struts2的包的lib目录下。如果缺少该包tomcat会有error  filterStart异常。

一般加入struts2的需要的包和上面的包就可以了,如果启动报aspectj方面的错则还需要加上aspectjweaver.jar。

然后在web.xml中进行配置让其随web服务启动而创建。

对于使用Spring的Web应用,无需手动创建Spring容器,而是通过配置文件,声明式地创建Spring容器。因此在web应用中创建Spring容器有如下两种方式:

一种是直接在web.xml文件中配置创建Spring容器。

另一种是利用第三方MVC框架的扩展点,创建Spring容器。

我们采用第一种方式:

Spring提供了一个ServletContextListener的一个实现类ContextLoaderListener,该类可以作为Listener使用,它会在创建时自动查找WEB-INF下的applicationContext.xml文件。因此如果只有一个applicationContext.xml配置文件,则只需要在web.xml文件中增加如下配置片段即可。

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

如果有多个配置文件需要载入,可考虑在web.xml中使用<context-param.../>元素来确定配置文件的文件名。ContextLoaderListener加载时,会查找名为contextConfigLocation的初始化参数。如:

<context-param>

<!--参数名为contextConfigLocation-->

<param-name>contextConfigLocation</param-name>

<!--多个配置文件之间以逗号隔开,/WEB-INF/conf/spring/applicationContext*.xml表示加载spring下所有以applicationContext开头的xml文件-->

<param-value>/WEB-INF/conf/spring/applicationContext*.xml,/WEB-INF/applicationContext.xml</param-value>

</context-param>

<!--使用ContextLoaderListener初始化Spring容器-->

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

*****************

如果没有使用contextConfigLocation指定配置文件,则Spring自动查找/WEB-INF/applicationContext.xml配置文件;如果有contextConfigLocation,则利用该参数确定的配置文件,如果无法找到合适的配置文件,Spring将无法正常初始化。

*****************

关于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"

    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
 

<bean id="myService" class="lee.MyServiceImpl"/>

<bean id="loginAction" class="lee.LoginAction" scope="prototype">

<property name="ms" ref="myService"/>

</bean>

</beans>

applicationContext.xml中用于配置<bean>进行依赖注入。

Spring根据指定配置文件创建WebApplicationContext对象,并将其保存到Web应用的ServletContext中,大部分情况下,应用中Bean无法感受到ApplicationContext的存在,只要利用ApplicationContext的IoC即可。如果需要在应用中获得ApplicationContext对象,可以通过如下代码获取:

WebApplicationContext ctx=WebApplicationContextUtils.getWebApplicationContext(servletContext);

Spring还提供了一个特殊的类ContextLoaderServlet,该Servlet在启动时,也会自动查找WEB-INF路径下的applicationContext.xml文件,为了让ContextLoaderServlet随应用启动而启动,应将此Servlet配置成load-on-startup的Servlet。如果只有一个配置文件为applicationContext.xml则在web.xml文件中增加的配置为:

<servlet>

<servlet-name>context</servlet-name>

<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<load-on-startup>1</load-on-startup>的值小一点,有助于ApplicationContext更快的初始化。

该Servlet用于提供后台服务,主要用于创建Spring容器,无须相应客户请求,因此无需为它配置<servlet-mapping/>元素。如果有多个配置文件或配置文件名不是applicationContext.xml则一样使用上面的<context-param/>元素来确定多个配置文件。

由于Servlet规范,Listener比Servlet优先加载,因此,采用ContextLoaderListener创建ApplicationContext的时机更早。

经过上面的配置,Spring和Struts2已经整合到一起。下面是一个应用整合后的实例。

Spring和Struts整合后的实例:

以前控制器是如何获得业务逻辑组件的呢?是通过new关键字创建业务逻辑组件,然后调用业务逻辑组件的方法,根据业务逻辑组件方法的返回值来确定结果,最后导向视图。

控制器如果访问到Spring容器中的业务逻辑组件(就是模型)呢?为了让Action(就是控制器)访问Spring的业务逻辑组件,有两种策略:

一种是Spring容器负责管理控制器Action,并利用依赖注入为控制器注入业务逻辑组件。

另一种是利用Spring的自动装配,Action将会自动从Spring容器中获取所需要的业务逻辑组件。

***********使用让Spring容器管理控制器通过为Action注入**************

Spring插件提供了一种伪Action,当我们在struts.xml文件中配置Action时,通常需要制定class属性,该属性就是用于创建Action实例的实现类。当Spring插件允许我们制定class属性时,不再指定Action的实际实现类,而是指定Spring容器中的BeanID。这种整合策略的关键:当struts2将请求转发给指定的Action时,Struts2中的该Action只是一个"傀儡",它只是一个代号,并没有指定实际的实现类,而隐藏在该Action下的Spring容器中的Action实例,才是真正处理用户请求的控制器。下面我们来进行演示:

首先我们书写一个login.jsp,其内容是输入用户名/密码进行登录。

然后我们书写一个LoginAction用于对前面登录的验证:

package lee;

public class LoginAction{

private String username;

private String password;

private String tip;

//MyService是一个业务逻辑组件

private MyService ms;

public void setMs(MyService ms){

this.ms=ms;



public MyService getMs(MyService ms){

return ms;



public void setUsername(String username){

this.username=username;

}

public String getUsername(String username){

return username;

}

public void setPassword(String password){

this.password=password;

}

public String getPassword(String Password){

return Password;

}

public void setTip(String tip){

this.tip=tip;

}

public String getTip(String tip){

return tip;

}

public String execute() throws Exception{

if(ms.valid(username,password)){

setTip("哈哈,整合成功了");

return "success";

}

else{

return "error";

}

}

}

上面的程序提供了一个MyService组件,并为该组件提供了setter和getter方法,通过setter方法,就可以让Spring管理Action和MyService组件的依赖关系,避免控制器和业务组件之间的硬编码耦合(采用new创建)。在execute()方法我们调用MyService组件的valid()来进行验证。下面我们在applicationContext.xml文件中进行配置,将LoginActin所需要的组件MyService组件注入进来。

<?xml version="1.0" encoding="UTF-8"?>

<beans

    xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
 

<bean id="myService" class="lee.MyServiceImpl"/>

<bean id="loginAction" class="lee.LoginAction" scope="prototype">

<property name="ms" ref="myService"/>

</bean>

</beans>

在Struts2的中如何使用被Spring管理的这个Action。那么在struts.xml文件中的配置如下:

<package name="lee" extends="struts-default">

<action name="Login"  class="loginAction">

<result name="error">/error.jsp</result>

<result name="success">/welcome.jsp</result>

</action>

</package>

可以看到class的取值不再是一个实际的实现类,而是Spring容器的BeanID:loginAction。这样被Sprign容器管理的loginAction就会被使用到。

在开发中所有的业务组件都是有接口和实现类两部分组成。上例中使用的MyService业务组件我们分成MyService接口和MyService的实现类MyServiceImpl。

MyService接口类如下:

package lee;

public interface MyService{

public boolean valid(String username,String password);

}

实现MyService接口类的MyServiceImpl如下:

package lee;

public class MyServiceImpl implements MyService{

//实现接口的valid方法

public boolean valid(String username,String password){

if(username.equals("kk") && password.equals("123")){

return true;

}

return false;

}

}

将该业务组件部署到Spring容器中,配置业务逻辑组件的片段如下:

<bean id="myService" class="lee.MyServiceImpl"/>

然后就可以在applicationContext.xml中将此业务逻辑组件注入到Action的中。如

<property name="ms" ref="myService"/>

上面实例是采用Spring容器管理Action控制器,它也有一些不足之处:

Spring管理action,必须将所有的Action配置在Spring容器中,而struts.xml文件中还需要配置一个"伪Action",从而导致配置文件臃肿。

Action的业务逻辑组件接容器的注入,将降低可读性。

***********使用自动装配******************

在这种策略下,Action还是由Spring插件创建,Spring在创建Action实例时,利用Spring的自动装配策略,将对应的业务逻辑组件注入Action实例,这种整合策略配置文件简单,但控制器和业务逻辑组件耦合较高。

采用自动装配,我们还是采用传统方式配置struts2的Action,配置Action时一样指定其具体的实现类。

所谓自动装配,即让spring自动管理Bean与Bean之间的依赖关系,无须使用ref显式指定依赖Bean,Spring容器会自动检查XML配置文件内容,为主调Bean注入依赖Bean,自动装配可以减少配置文件的工作量,但会降低依赖关系的透明性和清晰性。如果我们不指定自动装配,系统默认使用按name自动装配。

采用Spring插件的自动装配策略需要在Struts2通过struts.objectFactory.spring.autoWire常量指定,该常量可以接受如下几个值:

name,根据属性名自动装配。Spring插件会查找容器中全部Bean,找出其中id属性与Action所需的业务逻辑组件同名的Bean,将该Bean实例注入到Action实例中。

type,根据属性类型自动装配,Spring插件会查找容器中全部Bean,找出其类型恰好与Action所需的业务逻辑组件相同的Bean,将该Bean实例注入到Action实例。如果有多个这样的Bean,就抛出一个致命的异常,如果没有匹配的Bean,则什么都不发生,属性不会被设置。

auto,Spring插件会自动见此需要使用那种自动装配方式。

constructor,与type类似,区别是constructor使用构造器来构造注入所需参数,而不是使用设值注入方式。

对于上面的Spring容器管理Action实例,如果换成Spring自动装配,首先需要在struts.xml为struts.objectFactory.spring.autoWire常量指定值,Action的配置仍然采用struts2的方式指定具体实现类。

<constant name="struts.objectFactory" value="spring"/>

<constant name="struts.objectFactory.spring.autoWire" value="type"/>

<package name="lee" extends="struts-default">

<action name="Login"  class="lee.LoginAction">

<result name="error">/error.jsp</result>

<result name="success">/welcome.jsp</result>

</action>

</package>

我们选择根据属性名进行自动装配,那么我们在applicationContext.xml中需要配置与逻辑组件名(private MyService ms;)相同的BeanID。如:

<bean id="ms" class="lee.MyServiceImpl"/>

<bean id="loginAction" class="lee.LoginAction" scope="prototype">

</bean>

**************************

基于注释的配置

基于注释的配置越来越流行,Spring 2.5顺应了这种趋势,提供了完全基于注释配置Bean,装配Bean的功能。可以使用基于注释的Spring IoC替换原来基于XML的配置。

注释配置相对于XML配置具有很多的优势:

它可以充分利用java的反射机制获取类结构的信息,这些信息可以有效减少配置的工作。

注释和java代码位于一个文件中,有助于增强程序的内聚性。

Spring不但支持自己定义的@Autowired(byType自动装配)和(@Qualifier("name")精确装配byName)的注释,还支持由JSR-250规范定义的注释,它们分别是@Resource,@PostConstruct以及@PerDestroy。

@Resource

@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,@Resource默认按byName自动注入。@Resource有两个属性name和type,Spring将@Resource注释的name属性解析为Bean的名字,而type属性则解析为Bean的类型,所以如果@Resource使用了name属性,则使用byName的自动注入策略,而使用来type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,将通过反射机制使用byName自动注入策略。

@Resource注释位于Spring发布包的lib/j2ee/common-annotations.jar类包中,因此使用之前必须将其加入到项目的类库中。例如:

package com.baobaotao;

import javax.annotation.Resource;

public class Boss {

    // 自动注入类型为 Car 的 Bean

    @Resource(type=Car.class)

    private Car car;

    // 自动注入 bean 名称为 office 的 Bean

    @Resource(name = "office")

    private Office office;

}

要让 JSR-250 的注释生效,除了在 Bean 类中标注这些注释外,还需要在 Spring 容器中注册一个负责处理这些注释的 BeanPostProcessor:

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

CommonAnnotationBeanPostProcessor 实现了BeanPostProcessor接口,它负责扫描使用了 JSR-250 注释的Bean,并对它们进行相应的操作。

@PostConstruct 和 @PreDestroy

Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,您既可以通过实现 InitializingBean/DisposableBean 接口来定制初始化之后 / 销毁之前的操作方法,也可以通过 <bean> 元素的 init-method/destroy-method 属性指定初始化之后 / 销毁之前调用的操作方法。关于 Spring 的生命周期,笔者在《精通 Spring 2.x—企业应用开发精解》第 3 章进行了详细的描述,有兴趣的读者可以查阅。

JSR-250 为初始化之后/销毁之前方法的指定定义了两个注释类,分别是 @PostConstruct 和 @PreDestroy,这两个注释只能应用于方法上。标注了 @PostConstruct 注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁之前调用。例如:

package com.baobaotao;

import javax.annotation.Resource;

import javax.annotation.PostConstruct;

import javax.annotation.PreDestroy;

public class Boss {

    @Resource

    private Car car;

    @Resource(name = "office")

    private Office office;

    @PostConstruct

    public void postConstruct1(){

        System.out.println("postConstruct1");

    }

    @PreDestroy

    public void preDestroy1(){

        System.out.println("preDestroy1"); 

    }

    …

}

使用< context:annotation-config />简化配置

Spring2.1添加了一个新的context的Schema命名空间,该命名空间对注释驱动、属性文件引入、加载期织入等功能提供了便捷的配置。我们知道注释本身是不会做任何事情的,它仅提供元数据信息。要使元数据信息真正起作用,必须让负责处理这些元数据的处理器工作起来。

AutowiredAnnotationBeanPostProcessor和 CommonAnnotationBeanPostProcessor就是处理这些注释元数据的处理器。但是直接在Spring配置文件中定义这些 Bean显得比较笨拙。Spring为我们提供了一种方便的注册这些BeanPostProcessor的方式,这就是< context:annotation-config />:

<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" 

xsi:schemaLocation="http://www.springframework.org/schema/beans  
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
http://www.springframework.org/schema/context  
http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 
<context:annotation-config /> 

</beans>   

<context:annotation-config />将隐式地向Spring容器注册AutowiredAnnotationBeanPostProcessor、 CommonAnnotationBeanPostProcessor、 PersistenceAnnotationBeanPostProcessor以及 RequiredAnnotationBeanPostProcessor这4个BeanPostProcessor。

在配置文件中使用context命名空间之前,必须在 <beans> 元素中声明 context 命名空间

<context:annotation-config />主要是代替我们可以通过 @Autowired 或 @Resource 在 Bean 类中使用自动注入功能。

使用 @Component

虽然我们可以通过 @Autowired 或 @Resource 在 Bean 类中使用自动注入功能,但是 Bean 还是在 XML 文件中通过 <bean> 进行定义 —— 也就是说,在 XML 配置文件中定义 Bean,通过 @Autowired 或 @Resource 为 Bean 的成员变量、方法入参或构造函数入参提供自动注入的功能。能否也通过注释定义 Bean,从 XML 配置文件中完全移除 Bean 定义的配置呢?答案是肯定的,我们通过 Spring 2.5 提供的 @Component 注释就可以达到这个目标了。

@Component,标注一个普通的Spring Bean类。当我们不知道这个类是哪一层的就使用它来注释。

@Controller,标注一个控制器组件类。

@Service,标注一个业务逻辑组件类。

@Repository,标注一个DAO组件类。

被上面标注的类在Spring中它们对应的<bean>元素的id是类名的第一个字母小写。

下面,我们完全使用注释定义 Bean 并完成 Bean 之间装配:

使用 @Component 注释的 Car.java               

package com.baobaotao;

import org.springframework.stereotype.Component;

@Component

public class Car {

    …

}

仅需要在类定义处,使用 @Component 注释就可以将一个类定义了 Spring 容器中的 Bean。下面的代码将 Office 定义为一个Bean:

使用 @Component 注释的 Office.java

package com.baobaotao;

import org.springframework.stereotype.Component;

@Component

public class Office {

    private String officeNo = "001";

    …

}

这样,我们就可以在 Boss 类中通过 @Autowired 注入前面定义的 Car 和 Office Bean 了,如果我们在spring的配置文件中使用了声明了注释装配,就不用再使用@Autowired了,spring会自动对类的属性进行注入。

使用 @Component 注释的 Boss.java          

package com.baobaotao;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Required;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.stereotype.Component;

@Component("boss")

public class Boss {

    @Autowired

    private Car car;

    @Autowired

    private Office office;

    …

}

@Component 有一个可选的入参,用于指定 Bean 的名称,在 Boss 中,我们就将 Bean 名称定义为“boss”。一般情况下,Bean 都是 singleton 的,需要注入 Bean 的地方仅需要通过 byType 策略就可以自动注入了,所以大可不必指定 Bean 的名称。

注意在使用 @Component 注释后,Spring 容器必须启用类扫描机制(通过<context:component-scan ../>配置)以启用注释驱动Bean 定义和注释驱动Bean自动注入的策略。Spring 2.5 对 context 命名空间进行了扩展,提供了这一功能,请看下面的配置:

清单 23. 简化版的 beans.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: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-2.5.xsd
           http://www.springframework.org/schema/aop

           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

           http://www.springframework.org/schema/tx          

           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

           http://www.springframework.org/schema/context

           http://www.springframework.org/schema/context/spring-context-2.5.xsd"
default-autowire="byType">

    <!--下面这句是声明使用注释配置,这样Spring会自动对属性按照byType的方式进行注入-->

    <context:annotation-config />

    <!--下面启动Spring 容器必须启用类扫描机制-->

    <context:component-scan base-package="com.baobaotao,com.baofacade"/>

</beans>

这里,所有通过 <bean> 元素定义 Bean 的配置内容已经被移除,仅需要添加一行 <context:component-scan/> 配置就解决所有问题了——Spring XML 配置文件得到了极致的简化(当然配置元数据还是需要的,只不过以注释形式存在罢了)。<context:component-scan/> 的base-package属性指定了需要扫描的类包,类包及其递归子包中所有的类都会被处理。

<context:component-scan/> 还允许定义过滤器将基包下的某些类纳入或排除。Spring 支持以下 4 种类型的过滤方式,通过下表说明:

扫描过滤方式

注释, 假如 com.baobaotao.SomeAnnotation 是一个注释类,我们可以将使用该注释的类过滤出来。

类名指定, 通过全限定类名进行过滤,如您可以指定将 com.baobaotao.Boss纳入扫描,而将 com.baobaotao.Car 排除在外。

正则表达式,通过正则表达式定义过滤的类,如下所示: com\.baobaotao\.Default.*

AspectJ 表达式,通过 AspectJ 表达式定义过滤的类,如下所示: com. baobaotao..*Service+

下面是一个简单的例子:

<context:component-scan base-package="com.baobaotao">

    <context:include-filter type="regex" 

        expression="com\.baobaotao\.service\..*"/>

    <context:exclude-filter type="aspectj" 

        expression="com.baobaotao.util..*"/>

</context:component-scan>

值得注意的是 <context:component-scan/> 配置项不但启用了对类包进行扫描以实施注释驱动 Bean 定义的功能,同时还启用了注释驱动自动注入的功能(即还隐式地在内部注册了 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor),因此当使用 <context:component-scan/> 后,就可以将 <context:annotation-config/> 移除了。

使用<context:component-scan/>自动注入时,我们在类中要使用相应的set/get方法,否则注入不进去,比如UserService中需要自动注入UserDao类,那么需要给出UserDao对应的set/get方法。而使用@Resource,@AutoWire注解注入则不需要给出相应的set/get方法。

默认情况下通过 @Component 定义的 Bean 都是 singleton 的,如果需要使用其它作用范围的 Bean,可以通过 @Scope 注释来达到目标,如以下代码所示:

 通过 @Scope 指定 Bean 的作用范围                

package com.baobaotao;

import org.springframework.context.annotation.Scope;



@Scope("prototype")

@Component("boss")

public class Boss {

    …

}

这样,当从 Spring 容器中获取 boss Bean 时,每次返回的都是新的实例了。

采用具有特殊语义的注释

Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service 和 @Controller。在目前的 Spring 版本中,这 3 个注释和 @Component 是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别和持久层、业务层和控制层(Web 层)相对应。虽然目前这 3 个注释和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用
@Repository、@Service 和 @Controller 对分层中的类进行注释,而用 @Component 对那些比较中立的类进行注释。

*********注意Struts的业务逻辑控制器类(Action类)配置在Spring自动注入或配置注入时,必须将业务逻辑控制器类配置为@Scope("prototype")*******

简单的说,Spring的自动注解,首先是使用@Component,@Controller,@Service或@Repository来简化的在Spring配置文件配置<bean>,接下来再使用

<?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: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-2.5.xsd
           http://www.springframework.org/schema/aop

           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

           http://www.springframework.org/schema/tx          

           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

           http://www.springframework.org/schema/context

           http://www.springframework.org/schema/context/spring-context-2.5.xsd"
default-autowire="byType">

    <!--下面这句是声明使用注释配置,这样Spring会自动对属性按照byType的方式进行注入-->

    <context:annotation-config />

    <context:component-scan base-package="com.baobaotao,com.baofacade"/>

将那些有属性需要注入的类扫描进来,然后由Spring进行自动注入。这样就完成了Spring自动注入。

************

Spring2.5.6和struts2,log4j整合后的web.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Struts 2.0 Hello World</display-name>

<!-- spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- struts2 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/* </url-pattern>
</filter-mapping>

<!-- log4j -->

    <context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>

<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/conf/log/log4j.xml</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

<!-- end log4j -->

<!-- CharacterEncoding Filter -->
<filter>
<filter-name>SetCharacterEncoding</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>SetCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>

<!--// End CharacterEncoding Filter -->

</web-app>

***********************

在SSH,SSI应用中,action相关的bean往往设置成“prototype”(多例模式)。

 

为什么要设置成多例模式(prototype)?不设置成多例模式有什么问题?

这是由struts2的特性决定的。struts2的action集成了MVC中的M(model)和C(control)两层,它的变量可以直接从

页面获得数据,但这些变量都不是线程安全的变量 。如果不设置成多例模式,这个action就是线程不安全的,在多线程请求

时,就有可能出现一些不可预知的错误。

首先要搞清楚的是线程的共享资源,共享资源是多线程中每个线程都要访问的类变量或实例变量,共享资源可以是单个

类变量或实例变量,也可以是一组类变量或实例变量。多线程程序可以有多个共享资源 

什么是线程安全

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

************************

在Spring中提供了字符编码过滤器,可以将我们的请求转换为统一的字符编码,这样不用自己在去编写一个字符编码过滤器了。如:

<!-- CharacterEncoding Filter -->
<filter>
<filter-name>SetCharacterEncoding</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>SetCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>

<!--// End CharacterEncoding Filter -->

encoding----->用来指定一个具体的字符集

forceEncoding------->Spring的早期版本这个参数作用很单一,当request中已经被指定了一个字符集的时候是否再将用endcoding对应的字符集设置到request中去。举个例子来说明,假如说过滤器就像上面那样被配置到web.xml了,当请求被提交之后,过滤器会判断request.getCharacterEncoding()是否为null,如果是null那么就会进行request.setCharacterEncoding("UTF-8")的操作,如果不是null那么过滤器什么也不会做。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring