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. Aptana jQuery自动提示

    参考 http://www.ghugo.com/aptana-studio-3-jquery-autocomplete/ 对于第一种方案 是每个项目都能生效的  不过有时候网络不好时就无法顺利获取提示 ...

  2. 安装VMware vSphere 的目的就是在一台物理服务器上安装很多很多的虚拟机

    版权声明:本文为博主原创文章,未经博主允许不得转载. 我们安装VMware vSphere 的目的就是在一台物理服务器上安装很多很多的虚拟机,我们可以通过VMware vSphere Client直接 ...

  3. 在systemd(CentOS7)自启动zookeeper

    zookeeper的自启动脚本,如果是 sysV 模式(CeontOS6或以下版本),可以直接使用下载版本中的 src 目录下对应的 sysV 自启动包,再chkconfig即可.老方法,简单,就不说 ...

  4. Installing on CentOS/RHEL / KB forum / Ajenti

    Installing on CentOS/RHEL / KB forum / Ajenti Ajenti → KB → Installation Is it?: Inappropriate Spam ...

  5. Gimp制作圆角透明图片

    用蒙版制作圆角透明图片,步骤如下: 1,用Gimp(2.8版本)打开图片 2,在图层窗口右键当前图层创建蒙版 3,选择蒙版类型黑色(全透明) 4,结果如下 5,用圆角矩形选择工具选择图片,设置圆角半径 ...

  6. openstack之cinder

    一.cinder概述: 1.F版之前,并没有cinder,对应的组件为nova-volume:以Rest API的形式提供服务 2.cinder目标: 减少nova的复杂性,降低nova的负载,支持多 ...

  7. Jquery调用webService的四种方法 转载-记录

    我总结几个关键点 1. 服务必须声明为ScriptService(否则会出现下面的问题) 2.服务的方法不需要任何更改,保持原状 3.客户端用jquery的.ajax方法来调用 3.1 type必须是 ...

  8. C++之类与对象(1)

    下个阶段,我将讲解C++中面向对象的部分,也是C++对C语言改进的最重要的部分.以前C++也被叫做是"带类的C".今天主要讲类的构成,成员函数以及对象的定义和使用. 1.其实这一节 ...

  9. BZOJ 3907: 网格( 组合数 + 高精度 )

    (0,0)->(n,m)方案数为C(n,n+m), 然后减去不合法的方案. 作(n,m)关于y=x+1的对称点(m-1,n+1), 则(0,0)->(m-1,n+1)的任意一条路径都对应( ...

  10. ThinkPHP 常用配置项列表

    //数据库配置 DB_HOST 主机名 DB_USER 用户名 DB_PWD 密码 DB_NAME 数据库名 DB_PREFIX 表前缀 LOAD_EXT_FILE=>'function lis ...