最近我一直在考虑一个问题,华为的BME框架与裸奔的Struts2集成Spring到底差别在哪里呢?这两者在使用方式上基本相同,由于多次直接使用BME框架来开发MTV Portal系列项目,觉得BME框架整合集成Spring和Struts2做得相当好,使用比较方便,由于无法直接看到BME的源代码,遂决定对比一下在具体使用上BME框架与直接使用Struts2集成Spring的异同点,借此来加深一下对Struts2框架和 Spring的学习与理解。
Struts2中对于Action的创建已经已经由Struts1中线程安全调整为非线程安全了。简单的说,就是Struts1中对于同一个Action中的不同的请求,使用的是同一个Action对象来处理的,现在的Struts2中则变更为对于同一个Action中的不同的请求,都是用相同的Action类的不同对象来处理的,每一次请求都会创建一个对应的Action的对象。
Struts2集成Spring的要解决的主要问题在于创建Action对象的时候要使用Spring来创建,并且把Action依赖的业务对象(由Spring来管理)注入到创建Action对象中来。
在网上找了一些例子,参照着实验了一下,但是很多例子都是貌似完整,实则语嫣不祥的,我也失败了不少。如下为我将Struts2集成Spring2.5的详细过程。
首先利用eclipse建立一个Web Project,名称为SSH2,该工程的主要功能为展示登录页面,并且在用户填写用户名和密码之后进行登录,在登录LoginAction中调用LoginService业务接口来取得用户信息,如果输入的登录帐号信息与LoginServiceImpl业务实现类中返回的用户信息一致则跳转到登录成功提示页面;如果输入的登录帐号信息为与业务层中的用户信息不一致跳转到错误页面;
整个工程的目录如下图:
注意:lib目录中的包,最初我是直接将struts-2.0.11.2-all.zip压缩包中的lib目录中的所有的jar包复制过去,并且也将spring-framework-2.5.5.zip包中全部的lib包复制过去的。当然这样做让我吃了很多苦头,虽然代码以及配置信息看来没有什么问题,但是导致最终将SSH2项目发布到Tomcat后却怎么也无法正常启动,甚至还报了莫名其妙的错误,让人云里雾里的。
web.xml文件如下: <?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_9" 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 Blank</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <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> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> </web-app>
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.5.xsd"> <bean id="loginService" class="com.ssh2.web.login.service.LoginServiceImpl"/> <bean id="loginAction" class="com.ssh2.web.login.LoginAction"> <property name="loginService" ref="loginService" ></property> </bean> </beans>
Struts2使用了如下两个配置文件struts.xml和ssh.xml ,本来可以直接将ssh.xml文件的内容直接合并到struts.xml中去的,为了表示更一般的情况这里分开成两个文件了。
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> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="false" /> <constant name= "struts.objectFactory" value="spring" /> <include file="ssh2.xml"/> <!-- Add packages here --> </struts>
ssh.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> <package name="ssh2" namespace="/ssh2" extends="struts-default"> <action name="login" class="loginAction" method="login"> <result name="success">/login.jsp</result> <result name="error">/login.jsp</result> </action> <action name="doLogin" class="loginAction" method="doLogin"> <result name="success">/main.jsp</result> <result name="error">/error.jsp</result> </action> </package> </struts>
至此Struts2集成Spring的配置文件就完成了,其它就是具体实现代码了,源代码包含如下几个文件:SSHAction.java是所有Action类的基类,它继承自ActionSupport,并且实现SessionAware, ServletRequestAware, ServletResponseAware这三个接口来完成对Response、Request、Session的自动注入;com.ssh2.web.login.bean.UserInfo.java是登录用户的用户信息,包含用户名、密码、验证码三个字段;com.ssh2.web.login.service.LoginService.java是一个业务接口,定义了如何取得用户信息;com.ssh2.web.login.service.LoginServiceImpl.java则为业务接口LoginService的实现,返回一个用户名和密码都为"zhangzk"的UserInfo对象;com.ssh2.web.login.LoginAction.java则为登录用到的Action,主要有login()方法来实现跳转到登录页面和doLogin()方法来验证用户从登录页面提交的用户名称和密码信息是否与我们的LoginServiceImpl业务接口返回的用户信息的名称和密码是否一致,一致则跳转到成功提示页面,不一致则跳转到失败提示页面。
com.ssh2.web.common.SSHAction.java文件如下:package com.ssh2.web.common; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; import org.apache.struts2.interceptor.SessionAware; import com.opensymphony.xwork2.ActionSupport; public class SSHAction extends ActionSupport implements SessionAware, ServletRequestAware, ServletResponseAware { private String message; private Map att; private HttpServletRequest request; private HttpServletResponse response; public void setSession(Map arg0) { this.att = arg0; } public void setServletRequest(HttpServletRequest arg0) { this.request = arg0; } public void setServletResponse(HttpServletResponse arg0) { this.response = arg0; } }
com.ssh2.web.login.bean.UserInfo.java文件如下:package com.ssh2.web.login.bean; public class UserInfo { private String userName; private String password; private String validateCode; 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; } public String getValidateCode() { return validateCode; } public void setValidateCode(String validateCode) { this.validateCode = validateCode; } }
com.ssh2.web.login.service.LoginService.java文件如下:
package com.ssh2.web.login.service; import com.ssh2.web.login.bean.UserInfo; public interface LoginService { UserInfo getUserInfo(UserInfo userInfo); }
com.ssh2.web.login.service.LoginServiceImpl.java文件如下:package com.ssh2.web.login.service; import com.ssh2.web.login.bean.UserInfo; public class LoginServiceImpl implements LoginService{ public UserInfo getUserInfo(UserInfo userInfo) { UserInfo info = new UserInfo(); info.setUserName("zhangzk"); info.setPassword("zhangzk"); info.setValidateCode("111111"); return info; } }