IoC(Inversion of Control,以下译为控制反转)随着Java社区中轻量级容器(Lightweight Contianer)的推广而越来越为大家耳熟能详。在此,我不想再多费唇舌来解释“什么是控制反转”和“为什么需要控制反转”。因为互联网上已经有非常多的文章对诸如此类的问题作了精彩而准确的回答。大家可以去读一下Rod Johnson和Juergen Hoeller合著的《Expert one-on-one J2EE Development without EJB》或Martin Fowler所写的《Inversion of Control Containers and the Dependency Injection pattern》。

言归正传,本文的目的主要是介绍在Struts 2中实现控制反转。

历史背景

众所周知,Struts 2是以Webwork 2作为基础发展出来。而在Webwork 2.2之前的Webwork版本,其自身有一套控制反转的实现,Webwork 2.2在Spring 框架的如火如荼发展的背景下,决定放弃控制反转功能的开发,转由Spring实现。值得一提的是,Spring确实是一个值得学习的框架,因为有越来越多的开源组件(如iBATIS等)都放弃与Spring重叠的功能的开发。因此,Struts 2推荐大家通过Spring实现控制反转。

具体实现

首先,在开发环境中配置好Struts 2的工程。对这部分仍然有问题的朋友,请参考我的早前的文章。

然后,将所需的Spring的jar包加入到工程的构建环境(Build Path)中,如下图1所示:


图1 所依赖的Spring的jar包

本文使用的是Spring 2.0,Spring强烈建议大家在使用其jar包时,只引用需要的包,原因是Spring是一个功能非常强大的框架,其中有些功能是您不需要的;而且Spring提倡的是“按需所取”,而不是EJB的“爱我就要爱我的一切”。当然,如果你怕麻烦或者是不清楚每个包的作用,引用一个Spring的总包也未尝不可。

接下来,就要修改WEB-INF\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 IoC Demo </ display-name >

< filter >
        < filter-name > struts-cleanup </ filter-name >
        < filter-class >
            org.apache.struts2.dispatcher.ActionContextCleanUp
        </ filter-class >
    </ filter >

< filter >
        < filter-name > struts2 </ filter-name >
        < filter-class >
            org.apache.struts2.dispatcher.FilterDispatcher
        </ filter-class >
    </ filter >

< filter-mapping >
        < filter-name > struts-cleanup </ filter-name >
        < url-pattern > /* </ url-pattern >
    </ filter-mapping >

< filter-mapping >
        < filter-name > struts2 </ filter-name >
        < url-pattern > /* </ url-pattern >
    </ filter-mapping >

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

< welcome-file-list >
        < welcome-file > index.html </ welcome-file >
    </ welcome-file-list >
</ web-app >

清单1 WEB-INF\web.xml

大家一看便知道,主要是加入Spring的ContextLoaderListener监听器,方便Spring与Web容器交互。

紧接着,修改Struts.properties文件,告知Struts 2运行时使用Spring来创建对象(如Action等),内容如下:

struts.objectFactory = spring

清单2 classes\struts.properties

再下来,遵循Spring的原则——面向接口编程,创建接口ChatService,代码如下:

package tutorial;

import java.util.Set;

public interface ChatService {
   Set < String > getUserNames();
}

清单3 tutorial.ChatService.java

然后,再创建一个默认实现ChatServiceImpl,代码如下:

package tutorial;

import java.util.HashSet;
import java.util.Set;

public class ChatServiceImpl implements ChatService {

    public Set < String > getUserNames() {
       Set < String > users = new HashSet < String > ();
       users.add( " Max " );
       users.add( " Scott " );
       users.add( " Bob " );
        return users;
   }

}

清单4 tutorial.ChatServiceImpl.java

接下来,就该新建Action了。tutorial.ChatAction.java的代码如下:

package tutorial;

import java.util.Set;

import com.opensymphony.xwork2.ActionSupport;

public class ChatAction extends ActionSupport {
    private static final long serialVersionUID = 8445871212065L ; 
   
    private ChatService chatService;
    private Set < String > userNames;

    public void setChatService(ChatService chatService) {
        this .chatService = chatService;
   }
   
    public Set < String > getUserNames() {
        return userNames;
   }
   
   @Override
    public String execute() {
       userNames = chatService.getUserNames();
        return SUCCESS;
   }
   
}

清单5 tutorial.ChatAction.java

ChatAction类使用属性(Getter/Setter)注入法取得ChatService对象。

然后,配置Spring的applicationContext.xml(位于WEB-INF下)文件,内容如下:

<? 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 ="chatService" class ="tutorial.ChatServiceImpl" />
    < bean id ="chatAction" class ="tutorial.ChatAction" scope ="prototype" >
        < property name ="chatService" >
            < ref local ="chatService" />
        </ property >
    </ bean >
</ beans >

清单6 WEB-INF\applicationContext.xml

上述代码有二点值得大家注意的:

  1. Struts 2会为每一个请求创建一个Action对象,所以在定义chatAction时,使用scope="prototype"。这样Spring就会每次都返回一个新的ChatAction对象了;
  2. 因为ChatServiceImpl被配置为默认的scope(也即是singleton,唯一的),所以在实现时应保证其线程安全(关于编写线程安全的代码的讨论已经超出本文的范围,更超出了本人的能力范围,大家可以参考Addison Wesley Professional出版的《Java Concurrency in Practice》)。

接下来,在classes/struts.xml中配置Action,内容如下:

<! DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd" >
< struts >
    < include file ="struts-default.xml" />    
    
    < package name ="Struts2_IoC" extends ="struts-default" >
        < action name ="Chat" class ="chatAction" >
            < result > /UserList.jsp </ result >
        </ action >
    </ package >    
</ struts >

清单7 classes\struts.xml

这里的Action和平常不同的就是class属性,它对应于Spring所定义的bean的id,而不是它的类全名。

最后,让我们看看/UserList.jsp,内容如下:

<% @ page contentType = " text/html; charset=UTF-8 " %>
<% @ taglib prefix = " s " uri = " /struts-tags " %>
< html >
< head >
    < title > User List </ title >
</ head >

< body >
    < h2 > User List </ h2 >
    < ol >
    < s:iterator value ="userNames" >
        < li >< s:property /></ li >
    </ s:iterator >
    </ ol >
</ body >
</ html >

清单8 /UserList.jsp

大功告成,分布运行应用程序,在浏览器中键入http://localhost:8080/Struts2_IoC/Chat.action,出现如图2所示页面:


图2 /ListUser.jsp

总结

通过Spring在Struts 2上实现控制反转是强烈推荐的做法,当然您也可以组合其它的实现(如Pico等)。

在Struts 2中实现IoC的更多相关文章

  1. Android 进阶 Android 中的 IOC 框架 【ViewInject】 (下)

    上一篇博客我们已经带大家简单的吹了一下IoC,实现了Activity中View的布局以及控件的注入,如果你不了解,请参考:Android 进阶 教你打造 Android 中的 IOC 框架 [View ...

  2. struts.xml中出现Package struts2 extends undefined package struts-default解决办法

    在struts.xml中出现extends undefined package struts-default,经过查阅资料原来是因为没有联网的缘故.这样解决:在myeclipse中关联本地的dtd文件 ...

  3. spring.net中的IOC和DI-初使用

    前面准备:下载spring.net并解压 下载地址:spring.net下载地址 Ioc:控制反转         DI:依赖注入 一.IOC(控制反转) 1.新建一个控制台程序springTest, ...

  4. 关于struts 2中的日期问题

    struts 2中引入了大量的jquery的内容 其中日期问题总结一下: 步骤: 1.当然不用说,先建一个web项目 2.导入struts2所需要的jar包,以及此插件的包(当然你也可以用:strut ...

  5. Castle框架中的IOC和AOP机制

    反转控制(IOC)和面向切面编程(AOP)技术作为当前比较流行的技术,其优势已受到广泛关注,但是这两项新技术在实际项目上的应用研究却很落后,而且在.NET平台下实现这两项技术没有形成可以广泛套用的框架 ...

  6. Struts 2中的constant详解

    通过对这些属性的配置,可以改变Struts 2 框架的一些默认行为,这些配置可以在struts.xml文件中完成,也可以在struts.properties文件中完成. 1.<constant ...

  7. Spring——Web应用中的IoC容器创建(WebApplicationContext根应用上下文的创建过程)

    基于Spring-4.3.7.RELEASE Spring的配置不仅仅局限在XML文件,同样也可以使用Java代码来配置.在这里我使用XML配置文件的方式来粗略地讲讲WebApplicationCon ...

  8. ASP.NET Core中使用IOC三部曲(一.使用ASP.NET Core自带的IOC容器)

    前言 本文主要是详解一下在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期. 这里就不详细的赘述IOC是什么 以及DI是什么了.. emm..不懂的可以自行百度. 目录 ...

  9. ASP.NET Core中使用IOC三部曲(二.采用Autofac来替换IOC容器,并实现属性注入)

    前言 本文主要是详解一下在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期. 这里就不详细的赘述IOC是什么 以及DI是什么了.. emm..不懂的可以自行百度. 目录 ...

随机推荐

  1. .net mvc RazorEngine 字符串razor参数替换

    在.net中有一个比较好的字符串参数替换的方案RazorEngine推荐大家看看原网站,然后做个小联系然后你就懂啦 首先呢得下载一个吧, vs中tools-> Library Paging Ma ...

  2. javascript学习笔记(window .alert 是什么)

    <script language="javascript"> var abc="25"; window .alert(abc); </scri ...

  3. Mobile上的viewport及各种概念澄清贴

    device Pixel & CSS Pixel 物理像素指显示设备上的物理像素点,比如HTC G11宽是480px,这的480是用物理像素衡量的. CSS像素的话则指我们写页面时理解的那个像 ...

  4. java面试题系列11

    华为的JAVA面试题 QUESTION NO: 1 publicclass Test1 {       publicstaticvoid changeStr(String str){         ...

  5. STL之priority_queue为复合结构排序

    priority_queue为复合结构排序: #include <iostream> #include <queue> using namespace std; struct ...

  6. IntelliJ IDEA 14 注册码生成器

    IntelliJ IDEA 14 注册码生成器 文件为Java代码 自己编译运行里面的程序输入名称然后就生成注册码了工具:http://yun.baidu.com/s/1cZKsA部分工具生成的注册码 ...

  7. wpf将表中数据显示到datagrid示例(转)

    原文:http://www.jb51.net/article/47120.htm 这篇文章主要介绍了wpf将表中数据显示到datagrid示例,需要的朋友可以参考下 a.在.xaml文件中拖入一个da ...

  8. IOS开发:UIAlertView使用

    链接地址:http://www.2cto.com/kf/201307/231841.html UIAlertView是什么就不介绍了 1.基本用法 1 UIAlertView *view = [[UI ...

  9. [置顶] 关于CSDN2013博客之星的一些看法

    最近一个周,最火的话题当然要数CSDN2013博客之星拉票了. 实话实说,从12月14日开始,我连续5天拉票. 通过QQ群.QQ好友.CSDN文章.给CSDN粉丝发私信等多种方式拉票,真是累死我了. ...

  10. linux安装LNMP的资源

    wget http://nginx.org/download/nginx-0.7.69.tar.gz wget http://museum.php.net/php5/php-5.2.10.tar.gz ...