8.7.3 让Spring管理控制器

        让Spring容器来管理应用中的控制器,可以充分利用Spring的IoC特性,但需要将配置Struts 2 的控制器部署在Spring容器中,因此导致配置文件冗余。

        Struts 2 的核心控制器首先拦截到用户请求,然后将请求转发给对应的Action处理,在此过程中,Struts 2 将负责创建Action实例,并调用其execute()方法。这个过程是固定的(除非改写Struts 2 的核心控制器)。现在的情形是:如果把Action实例交由Spring容器来管理,而不是由Struts 2 产生的,那么核心控制器如何知道调用Spring容器中的Action,而不是自行创建Action实例呢?

        进入Struts 2 项目的lib目录下,可以找到一个struts2-spring-plugin-x.x.x.x.jar文件,这个JAR包就是Struts 2 整合Spring 的插件,简称Spring插件。为了将Struts 2、Spring进行整合开发,首先应该将JAR包复制Web应用的WEB-INF\lib目录下。

        Spring插件提供了一种为Action,在struts.xml文件中配置Action时,通常需要指定class属性,该属性就是用于创建Action实例的实现类。但Struts 2 提供的Spring 插件允许指定class 属性时,不再指定Action的实际实现类,而是指定为Spring 容器中的Bean ID,这样Struts 2 不在自己负责创建Action实例,而是直接通过Spring容器去获取Action对象。

        通过上面的方式,不难发现这种整合策略的关键:当Struts 2 将请求转发给指定的Action时,Struts 2 中的该Action只是一个“傀儡”,它只是一个代号,并没有指定实际的实现类,当然也不可能创建Action实例,而隐藏在该Action下的是Spring容器中的Action实例 ------- 它才是真正处理用户请求的控制器。

        Struts 2 只是配置一个伪控制器,这个伪控制器的功能实际由Spring容器中的控制器来完成,这就实现了让核心控制器调用Spring 容器中的Action来处理用户请求。

        在这种整合策略下,处理用户请求的Action有Spring插件负责创建,但Spring插件创建Action实例时,并不是利用配置Action时指定的class 属性来创建Action实例,而是从Spring容器中取出对应的Bean实例完成创建的。

        登录页面:--------------------------------------------------

        为了处理用户请求,必须提供处理用户请求的Action类,该Action需要调用业务逻辑组件的业务逻辑方法来处理用户请求。在实际的Java EE项目中,Action只是系统的控制器,也不应该处理用户请求,处理用户请求是业务逻辑实现,理应有业务逻辑组件来提供实现。

        Class : LoginAction

package edu.pri.lime.account.act;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport; public class LoginAction extends ActionSupport{ /**
*
*/
private static final long serialVersionUID = 1L; // 封装用户请求参数的两个成员变量
private String username;
private String password; // 系统所用的业务逻辑组件
private MyService ms;
// 设置注入业务逻辑组件所必需的setter方法
public void setMs(MyService ms){
this.ms = ms;
}
// 处理用户请求的execute方法
public String execute() throws Exception{
// 调用业务逻辑组件的validLogin()方法
// 验证用户名和密码
if(ms.validLogin(getUsername(),getPassword()) > 0){
addActionMessage("Congratulation!,Integer Succeed !");
return Action.SUCCESS;
}
return Action.ERROR;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
} }

        提示:

          Spring 容器为控制器注入业务逻辑组件,这也是Spring 和Struts 2 整合的关键所在。

        XML : Struts

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 指定Struts 2 配置文件的DTD信息 -->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd"> <!-- Struts 2 配置文件的根元素 -->
<struts>
<!-- 配置了一系列常量 -->
<constant name="struts.i18n.encoding" value="UTF-8"/>
<constant name="struts.devMode" value="true"/>
<constant name="struts.enable.DynamicMethodInvocation" value="false"/> <package name="lime" extends="struts-default">
<!-- 定义处理用户请求的Action,该Action的class属性不是实际处理类,而是Spring容器中的Bean实例的ID -->
<action name="login" class="loginAction">
<!-- 为两个逻辑视图配置页面 -->
<result name="error">/WEB-INF/content/error.jsp</result>
<result name="success">/WEB-INF/content/welcome.jsp</result>
</action>
<!-- 让用户直接访问该应用时列出所有的视图页面 -->
<action name="*">
<result>/WEB-INF/content/{1}.jsp</result>
</action>
</package>
</struts>

          Class : Service

package edu.pri.lime.account.service.impl;

import edu.pri.lime.account.service.MyService;

public class MyServiceImpl implements MyService{

    public int validLogin(String username, String password) {
if(username.equals("lime") && password.equals("oracle")){
return 99;
}
return -1;
} }

        XML : Spring

<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 部署一个业务逻辑组件 -->
<bean id="myService" class="edu.pri.lime.account.service.impl.MyServiceImpl"/> <!-- 让Spring管理Action实例,并依赖注入业务逻辑组件 -->
<bean id="loginAction" class="edu.pri.lime.account.act.LoginAction" scope="protytype">
<property name="ms" ref="myService"/>
</bean> </beans>

        注意:

          当使用Spring容器管理Struts 2 的Action时,由于每个Action对应一次用户请求,且封装了该次请求的状态信息,所以不应该Action配置成单例模式,因此必须指定scope属性,该属性值可制定为portotype或request。

        这种策略充分利用了Spring 的IoC特性,是一种较为优秀的解耦策略。这种策略也有一些不足之处,归纳起来,主要有如下不足之处:

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

          ⊙ Action的业务逻辑组件接收容器注入,将导致代码的可读性降低。

啦啦啦

啦啦啦

啦啦啦

8 -- 深入使用Spring -- 7...3 让Spring管理控制器的更多相关文章

  1. Spring基于AOP的事务管理

                                  Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...

  2. spring boot(五):spring data jpa的使用

    在上篇文章springboot(二):web综合开发中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data jpa 常见用法以及注意事项 使用spr ...

  3. spring boot(三):Spring Boot中Redis的使用

    spring boot对常用的数据库支持外,对nosql 数据库也进行了封装自动化. redis介绍 Redis是目前业界使用最广泛的内存数据存储.相比memcached,Redis支持更丰富的数据结 ...

  4. [Spring]支持注解的Spring调度器

    概述 如果想在Spring中使用任务调度功能,除了集成调度框架Quartz这种方式,也可以使用Spring自己的调度任务框架. 使用Spring的调度框架,优点是:支持注解(@Scheduler),可 ...

  5. Spring注入JPA+JPA事务管理

    本例实现的是Spring注入JPA 和 使用JPA事务管理.JPA是sun公司开发的一项新的规范标准.在本质上来说,JPA可以看作是Hibernate的一个子集:然而从功能上来说,Hibernate是 ...

  6. 使用 Spring Boot 快速构建 Spring 框架应用--转

    原文地址:https://www.ibm.com/developerworks/cn/java/j-lo-spring-boot/ Spring 框架对于很多 Java 开发人员来说都不陌生.自从 2 ...

  7. 全面分析 Spring 的编程式事务管理及声明式事务管理

    开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本 ...

  8. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->Spring Framework中的spring web MVC模块

    spring framework中的spring web MVC模块 1.概述 spring web mvc是spring框架中的一个模块 spring web mvc实现了web的MVC架构模式,可 ...

  9. Spring学习1-初识Spring

    一.简介   1.Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目得是简化企业开发.  2.为何要使用Spring?   ...

  10. Spring第12篇—— Spring对Hibernate的SessionFactory的集成功能

    由于Spring和Hibernate处于不同的层次,Spring关心的是业务逻辑之间的组合关系,Spring提供了对他们的强大的管理能力, 而Hibernate完成了OR的映射,使开发人员不用再去关心 ...

随机推荐

  1. WebRTC 源码分析(五):安卓 P2P 连接过程和 DataChannel 使用

    从本篇起,我们将迈入新的领域:网络传输.首先我们看看 P2P 连接的建立过程,以及 DataChannel 的使用,最终我们会利用 DataChannel 实现一个 P2P 的文字聊天功能. P2P ...

  2. python 语法最佳实践

    1. 列表推倒 我们知道, 列表类似于数组, 列表里存储的都是对象, 所以列表中可以存储"数字","字符串" 等对象. 列表用中括号扩起, 然后逗号分隔 列表内 ...

  3. linux 解压压缩大全

    eoiioe   linux下解压命令大全 .tar 解包:tar xvf FileName.tar打包:tar cvf FileName.tar DirName(注:tar是打包,不是压缩!)——— ...

  4. PHP经纬度 测距

    /** *求两个已知经纬度之间的距离,单位为米 *@param lng1,lng2 经度 *@param lat1,lat2 纬度 *@return float 距离,单位米 **/ function ...

  5. 经典ajax 状态响应图

  6. (笔记)Linux下的CGI和BOA使用期间遇到的问题汇总

    前段时间在做C/S模式下的视频监控,这段时间是B/S模式下的.期间遇到了不少问题,有些问题一卡就是几天,有些问题的解决办法在办法在网上也不是很好找,所以还有些问题虽然得到了临时解决,但是其原理现在我本 ...

  7. 建议大家使用Java 8 的日期、时间,而非java.util.Date

    建议大家使用Java 8 的日期.时间,而非java.util.Date. 详细原因见:如何在Java 8中愉快地处理日期和时间 总结一下就是, java.util.Date 太乱,如 月份从0开始. ...

  8. python 判断一个对象的变量类型

    isinstance   语法: isinstance(object, classinfo) 如果参数object是classinfo的实例,或者object是classinfo类的子类的一个实例, ...

  9. 初步了解学习将传统单机应用改造成Dubbo服务的过程

    Dubbo作为RPC框架,实现的效果就是调用远程的方法就像在本地调用一样.如何做到呢?就是本地有对远程方法的描述,包括方法名.参数.返回值,在Dubbo中是远程和本地使用同样的接口:然后呢,要有对网络 ...

  10. 【转】C# 异常处理 throw和throw ex的区别 try catch finally的执行顺序(return)

    [转]throw和throw ex的区别 之前,在使用异常捕获语句try...catch...throw语句时,一直没太留意几种用法的区别,前几天调试程序时无意中了解到几种使用方法是有区别的,网上一查 ...