十七、Spring整合Struts2
Spring整合Struts2
1.启动Spring容器
(1)对于使用Spring的web应用,无须手动创建Spring容器,而是通过配置文件声明式的创建Spring容器。在web应用中创建Spring容器的方式有两种:
1)直接在web.xml中用配置的方式创建Spring容器;
2)利用第三方MVC框架的拓展点,创建Spring容器;(如Struts1)
(2)Spring提供了ContextLoaderListener,该监听器类实现了ServletContextListener监听器接口,在web.xml中配置了ContextLoaderListener监听器之后,在创建时会自动查找/WEB-INF目录下的applicationContext.xml文件,如需要为其添加多个配置文件,则需要借助<context-param>标签,使用ContextLoaderListener的示例如下:(web.xml中配置)
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <!-- 指定多个配置文件 --> <context-param> <!-- 设置参数名为contextConfigLocation --> <param-name>contextConfigLocation</param-name> <!-- 多个配置文件之间使用“,”隔开 --> <param-value> /WEB-INF/test1.xml, /WEB-INF/test2.xml, /WEB-INF/test3.xml </param-value> </context-param> <!-- 使用ContextLoaderListener初始化Spring容器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
(3)Spring根据指定的配置文件创建WebApplicationContext对象,并将其保存在ServletConetxt中;
2.Spring管理控制器
(1)Struts2提供了一个Spring插件,该插件提供了一个伪Action,在struts.xml文件中配置Action时,通常需要指定class属性,该属性就是用于创建Action实例的实现类,但Spring插件允许指定class属性时,不再指定Action的实际实现类,而是指定为Spring容器中的Bean id,这样Struts2不再自己负责创建Action实例,而是直接通过Spring容器去获取Action对象。
(2)处理用户请求的Action由Spring插件负责创建,但Spring插件创建Action实例时,并不是利用配置Action时指定的class属性来创建该Action实例,而是从Spring容器中取出对应的Bean实例完成创建;
(3)简单示例:
JSP:
1)登陆页面:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>登陆</title> </head> <body> <s:form action="login"> <s:textfield name="username" key="user"/> <s:password name="password" key="pass"/> <s:submit key="login"/> </s:form> </body> </html>
2)成功登陆页面:略
3)登陆失败页面:略
Action实现类:
import com.opensymphony.xwork2.ActionSupport; public class LoginAction extends ActionSupport{ //封装用户请求的两个成员变量 private String username; private String password; //所需要的业务逻辑组件 private MyService ms; //设置注入业务逻辑组件所必须的setter方法 public void setMyService(MyService ms){ this.ms = ms; } //用户请求的setter、getter方法 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; } //处理用户请求的execute方法 public String execute()throws Exception{ //调用业务逻辑组件的validLogin()方法 //验证用户输入的用户名密码是否正确 if(ms.validLogin(getUsername(), getPassword())>0){ return SUCCESS; }else{ return ERROR; } } }
MyService接口:
//登陆业务逻辑组件接口 public interface MyService { public int validLogin(String username,String password); }
MyService实现类:
public class MyServiceImpl implements MyService{ @Override public int validLogin(String username, String password) { // TODO Auto-generated method stub if(username.equals("test")&&password.equals("test")){ return 99; } return -1; } }
web.xml配置:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <!-- 使用ContextLoaderListener初始化Spring容器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 定义Struts2的核心Filter --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <!-- 让Struts2的核心Filter拦截所有请求 --> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
applicationContext.xml配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd" > <!-- 部署一个业务逻辑组件 --> <bean id="myService" class="test1.MyServiceImpl"/> <!-- 让Spring管理Action实例并依赖注入一个业务逻辑组件 --> <bean id="loginAction" class="test1.LoginAction" scope="prototype"> <property name="myService" ref="myService"/> </bean> </beans>
struts.xml配置:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="true" /> <!-- 设置OGNL表达式可以访问静态方法 --> <constant name="struts.ognl.allowStaticMethodAccess" value="true"/> <package name="test_1" extends="struts-default"> <action name="welcome"> <result>/WEB-INF/test1/login.jsp</result> </action> <!-- 定义处理用户请求的Action,该Action的class属性不是实际处理类而是 Spring容器中的Bean ID --> <action name="login" class="loginAction"> <!-- 逻辑视图配置视图页面 --> <result name="success">/WEB-INF/test1/success.jsp</result> <result name="error">/WEB-INF/test1/error.jsp</result> </action> </package> </struts>
3.使用自动装配
(1)在自动装配策略下,Action还是由Spring插件创建,Spring插件在创建Action实例时,利用Spring的自动装配策略将对应的业务逻辑组件注入Action实例中。
(2)如果不指定自动装配,系统默认使用byName自动装配;
(3)使用自动装配的示例:
JSP页面:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>登陆</title> </head> <body> <s:form action="login2"> <s:textfield name="username" key="user"/> <s:password name="password" key="pass"/> <s:submit key="login"/> </s:form> </body> </html>
Action实现类:
import com.opensymphony.xwork2.Action; public class Login2Action implements Action{ private String username; private String password; //业务逻辑组件 private MyService2 ms2; //提供所需注入的setter方法 public void setMyService2(MyService2 ms2){ this.ms2 = ms2; } //封装了请求的成员变量的setter、getter方法 public void setUsername(String username){ this.username = username; } public String getUsername(){ return this.username; } public void setPassword(String password){ this.password = password; } public String getPassword(){ return this.password; } //处理请求的execute()方法 public String execute(){ //调用业务逻辑组件的validLogin()方法 System.out.println(getUsername()); System.out.println(getPassword()); if(ms2.validLogin(getUsername(), getPassword())>0){ return SUCCESS; }else{ return ERROR; } } }
业务逻辑组件接口:
public interface MyService2 { public int validLogin(String username,String password); }
业务逻辑组件实现类:
public class MyService2Impl implements MyService2{ @Override public int validLogin(String username, String password) { // TODO Auto-generated method stub if(username.equals("test")&&password.equals("test")){ return 99; }else{ return -1; } } }
struts.xml片段:
<action name="welcome2"> <result>/WEB-INF/test2/login.jsp</result> </action> <!-- 使用byName自动装配时,action的配置与未与Spring整合时相同 class属性就是Action的实现类 --> <action name="login2" class="test2.Login2Action"> <result name="success">/WEB-INF/test2/success.jsp</result> <result name="error">/WEB-INF/test2/error.jsp</result> </action>
applicationContext.xml片段:
<!-- 使用byName自动装配注入业务逻辑组件 --> <!-- 此处id必须与setter方法名对应 --> <bean id="myService2" class="test2.MyService2Impl"/>