Struts2整合Spring
您目前处于:技术核心竞争力  2013-06-28

1. Struts2 插件

Struts2通过提供各种插件,用于与大部分流程的J2EE框架进行整合。

插件概述

Struts2的插件是一个JAR文件,这个JAR文件可以用于扩展、改变或者添加Struts2的功能。每个Struts2的插件JAR都包含一个名为struts-plugin.xml的配置文件,struts-plugin.xml文件的内容与普通的struts.xml文件内容完全相同。

当把这个包含struts-plugin.xml文件的JAR文件复制到Web应用中时,Struts2会自动加载该JAR文件的struts-plugin.xml文件。

Struts2应用包含3种类型的配置文件:struts-default.xml(包含在struts2-core.xml文件中),struts-plugin.xml(包含在各插件JAR文件中)和struts.xml文件。

启动一个struts2应用时,加载顺序: struts-default.xml、struts-plugin.xml和struts.xml。

2.集成Spring

和Spring集成的目标:是希望Struts2的Action定义直接使用Spring IoC的功能,将业务层的Bean注入到Struts的Action中。

将Struts类包添加到lib路径下

struts2-core.2.jar

xwork-2.jar

ognl-2.jar

struts2-spring-plugin-2.jar

freemarker-2.jar

其中struts2-spring-plugin-2.jar就是将Struts2集成到Spring中的类包,该类包有一个struts-plugin.xml配置文件,定义了一个名为spring的StrutsSpringObjectFactory的Bean,以便将Action类的管理工作委托给Spring容器进行。

编写Struts配置文件struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <!-- 通过这个配置指定使用struts-plugin.xml中的StrutsSpringObjectFacotry作为创建Action的工具类 -->
    <constant name="struts.objectFactory" value="spring" />
</struts>

配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <!-- spring config -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:ApplicationContext*.xml</param-value>
    </context-param>
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- 定义Struts2的核心控制器FilterDispathcer的Filter -->
    <filter>
        <!-- 定义核心Filter的名字 -->
        <filter-name>struts2</filter-name>
        <!-- 定义核心Filter的实现类 -->
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
    <!-- FilterDispatcher用来初始化struts2并且处理所有的HTTP请求。 -->
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>*.action</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    <!-- 定义struts2.0 end.  -->
</web-app>

通过contextConfigLocation指定Spring配置文件,并配置ContextLoaderListener启动Spring容器。

整合流程

Struts2的核心控制器是拦截用户请求,然后将请求转发给对应Action处理,这个过程是固定的。但实际上,Action实例是由Spring容器产生,而不是Struts2容器,Spring通过提供一种伪Action,当在struts.xml文件配置Action时,通常需要指定class属性,不是指向Action的实际类,而是指向Spring容器的Bean ID。

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

3.注册用户实例

创建Action对象

public class User {
    private String userName;
    private String password;
    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;
    }
}
import cms.com.system.domain.User;
import com.opensymphony.xwork2.ActionSupport;
public class UserRegisterAction extends ActionSupport {
    private User user;
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public String execute() throws Exception {
        if(user == null) {
            user = new User();
            return "input";
        } else {
            return "success";
        }
    }
}

配置Action

在ApplicationContext.xml的Spring配置文件中配置UserRegisterAction Bean:

<bean id="registerUserAction" class="cms.com.system.action.UserRegisterAction" scope="prototype" />

在Spring中配置好Struts2的Action,在Struts配置文件中引用这个Bean:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <!-- 通过这个配置指定使用struts-plugin.xml中的StrutsSpringObjectFacotry作为创建Action的工具类 -->
    <constant name="struts.objectFactory" value="spring" />
    <!-- struts2的Action都必须配置在package里 -->
    <package name="user" extends="struts-default">
        <action name="registerUserAction" class="registerUserAction">
            <result name="input">/jsp/registerUser.jsp</result>
            <result name="success">/jsp/success.jsp</result>
        </action>
    </package>
</struts>

其中class="registerUserAciton",在正常情况下,struts通过class属性指定Action给的实现类:

<action name="registeruserAction" class="cms.com.system.action.UserRegisterAction">

但此时却是一个类似于Bean名的字符串,事实上class属性的值正是指向Spring容器中的Bean名称,在后台通过StrutsSpringObjectFactory获得真实的Action实例。

当使用Spring容器管理系统的Action,在struts.xml文件中配置该Action时,class属性并不是指向Action实体类,而是指向了Spring容器中Action的实例的ID。

表单页面和成功页面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
  <head>
    <title>My JSP 'MyJsp.jsp' starting page</title>
  </head>
  <body>
    <s:form>
        <s:textfield key="user.userName" label="用户名" />
        <s:textfield key="user.password" label="密码" />
        <s:submit/>
    </s:form>
  </body>
</html>

表单标签<s:form>通过简单地标签声明,无需通过action属性指定表单提交地址,表单组件标签也通过级联属性的方式绑定表单对象。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
  <head>
    <title>My JSP 'MyJsp.jsp' starting page</title>
  </head>
  <body>
    <s:form>
        <s:textfield key="user.userName" label="用户名" />
        <s:textfield key="user.password" label="密码" />
        <s:submit/>
    </s:form>
  </body>
</html>

测试用户注册界面

在点击Submit提交表单后,RegisterUserAction负责处理表单提交,处理后将重定向到success.jsp页面上。

完成Spring和Struts2的整合主要作用,是能让Struts2的Action实例利用Spring容器的IoC特性。

整合的不足

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

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


转载请并标注: “本文转载自 linkedkeeper.com ”  ©著作权归作者所有