spring結(jié)合struts的代碼詳解
Struts調(diào)用流程如下圖所示。

看到這幅圖一下子就能了解了struts的原理。Spring的核心就是IOC容器和AOP,所以我們用spring主要是管理業(yè)務(wù)對(duì)象和事務(wù)的管理,所以主要是Model層來(lái)讓spring管理,這是我們的一種方案。
第一種集成方案在Action中取得beanFactory
還記的在上篇文章中,測(cè)試的時(shí)候是在單元測(cè)試中拿到的BeanFactory,與struts結(jié)合就是在Action中取得beanFactory。步驟如下。
1、 建立一個(gè)web項(xiàng)目。
2、 建立相關(guān)頁(yè)面,代碼如下所示。
Login.jsp代碼入下所示。
<%@ pagelanguage="Java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"%>
<!DOCTYPE html PUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type" content="text/html;charset=GB18030">
<title>Insert titlehere</title>
</head>
<body>
<formaction="login.do" method="post">
用戶:<input type="text"name="username"><br>
密碼:<input type="password"name="password"><br>
<inputtype="submit" value="登錄">
</form>
</body>
</html>
Login_success.jsp
<%@ pagelanguage="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"%>
<!DOCTYPE html PUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type" content="text/html;charset=GB18030">
<title>Insert titlehere</title>
</head>
<body>
xx,用戶登錄成功!
</body>
</html>
3、 配置struts環(huán)境,關(guān)于struts的配置,拷貝struts和jstl的依賴包;在web.xml中配置ActionServlet,提供struts-config.xml文件。前篇文中有說(shuō)明,在此就不贅述了。
struts-config.xml代碼如下所示。
<struts-config>
<form-beans>
<form-beanname="loginForm"type="com.bjpowernode.usermgr.web.forms.LoginActionForm"></form-bean>
</form-beans>
<action-mappings>
<actionpath="/login"
type="com.bjpowernode.usermgr.web.actions.LoginAction"
name="loginForm"
scope="request"
>
<forwardname="success" path="/login_success.jsp"/>
</action>
</action-mappings>
<message-resourcesparameter="resources.MessageResources" />
</struts-config>
4、 配置spring環(huán)境,拷貝spring相關(guān)jar包,建立spring配置文件applicationContext-beans.xml。
applicationContext-beans.xml代碼如下所示。
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<beanid="userManager"class="com.bjpowernode.usermgr.manager.UserManagerImpl"/>
</beans>
5、 建立相關(guān)的Action和ActionForm。代碼如下所示。
LoginAction.java代碼如下所示。
public class LoginAction extendsAction {
@Override
publicActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequestrequest, HttpServletResponse response)
throwsException {
LoginActionFormlaf = (LoginActionForm)form;
Stringusername = laf.getUsername();
Stringpassword = laf.getPassword();
//但是我們每次都要去調(diào)用,去創(chuàng)建太麻煩了.
//我們?cè)谶@里只需要去配置Listener就可以了,spring給實(shí)現(xiàn)好了.
BeanFactoryfactory = newClassPathXmlApplicationContext("applicationContext.xml");
UserManageruserManager = (UserManager)factory.getBean("userManager");
userManager.login(username,password);
}
}
LoginActionForm.java代碼如下所示。
public class LoginActionFormextends ActionForm {
//表單上有什么提供什么屬性.
//名字一定要與表單中的一樣.
privateString username;
publicString getUsername() {
returnusername;
}
publicvoid setUsername(String username) {
this.username= username;
}
privateString password;
publicString getPassword() {
returnpassword;
}
publicvoid setPassword(String password) {
this.password= password;
}
}
6、 建立業(yè)務(wù)邏輯層,代碼如下所示。
UserManager代碼如下所示。
public interface UserManager {
publicvoid login(String username, String password);
}
UserManagerImpl.java代碼如下所示。
public class UserManagerImplimplements UserManager {
publicvoid login(String username, String password) {
System.out.println("UserManagerImpl"+"username="+ username);
}
}
7、 web.xml配置文件代碼如下所示。
<servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet>
就這樣我們?cè)贚oginAction中,使用beanFactory讀取spring配置文件,找到UserManagerImpl實(shí)例。如果每次在Action中讀取application-beans.xml文件,我們是否可以在服務(wù)器啟動(dòng)的時(shí)候就就創(chuàng)建BeanFactory呢?在這里我們可以使用spirng的工具WebApplicationContextUtils.getRequiredWebApplicationContext()從 ServletContext中 取得BeanFactory,然后再web.xml中配置Spring的Listener。
修改后,LoginAction代碼如下所示。
public class LoginAction extendsAction {
@Override
publicActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequestrequest, HttpServletResponse response)
throwsException {
LoginActionFormlaf = (LoginActionForm)form;
Stringusername = laf.getUsername();
Stringpassword = laf.getPassword();
//用工具包直接拿出來(lái)就可以了。
BeanFactoryfactory =WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext());
UserManageruserManager = (UserManager)factory.getBean("userManager");
userManager.login(username,password);
returnmapping.findForward("success");
}
}
加入相關(guān)配置,web.xml代碼如下所示。
<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>
這種方案缺點(diǎn):
我們?cè)谠贏ction中仍然看到Spring相關(guān)東西,看到Spring相關(guān)類,要是程序只看到的是接口,那要怎么做呢?
第二種方案,將struts的Aciton交給Spring來(lái)創(chuàng)建,讓代理Action負(fù)責(zé)拿到beanFactory,根據(jù)Path名稱到IOC中把對(duì)應(yīng)的Action取出來(lái)。
我們是在Model層應(yīng)用spring,在Action中取得BeanFactory,然后通過(guò)SpringIOC來(lái)找到Model層的bean。但是這這樣存在一些問題,我們?cè)贏ction中使用的是Spring相關(guān)的靜態(tài)類,這就說(shuō)明我們依賴的是Spring的靜態(tài)類,我們希望所依賴的是接口而不是類,符合設(shè)計(jì)原則,面向接口編程,這樣也容易擴(kuò)展和維護(hù)。于是在此基礎(chǔ)上進(jìn)行改進(jìn)。
第二種方案是將Struts的Action交給Spring創(chuàng)建,這樣業(yè)務(wù)邏輯對(duì)象將被注入,這樣就避免了依賴查找,而Spring中會(huì)有一個(gè)代理Action,通過(guò)代理ActionProxy取得banFactory。方案一和方案二的對(duì)比圖如下圖所示。
這樣就不用Spring的Listener了,所以我們的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"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet>
同時(shí)再struts的配置文件,struts-config.xml中,在<action-mappings>標(biāo)簽中配置Action,也不再配置我們自己建立的Action,而是配置Spring自己的代理Action。代碼如下所示。
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
<form-beans>
<form-bean name="loginForm" type="com.bjpowernode.usermgr.web.forms.LoginActionForm"></form-bean>
</form-beans>
<action-mappings>
<action path="/login"
type="org.springframework.web.struts.DelegatingActionProxy"
name="loginForm"
scope="request"
>
<forward name="success" path="/login_success.jsp"/>
</action>
</action-mappings>
<message-resources parameter="resources.MessageResources" />
</struts-config>
Spring對(duì)Aciton的配置文件如下所示。applicationContext-actions.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean name="/login" class="com.bjpowernode.usermgr.web.actions.LoginAction" scope="prototype">
<property name="userManager" ref="userManager"/>
</bean>
</beans>
在這里配置對(duì)應(yīng)的本系統(tǒng)實(shí)際的Action,注意名字一定要和struts中代理Action一致!并且設(shè)置每次創(chuàng)建一個(gè)新的Action,而不是共用一個(gè)Action,scope="prototype"。
這樣在LoginAction中,我們不用再看到創(chuàng)建Model和工廠的細(xì)節(jié),使用SpringIOC,創(chuàng)建Model,UserManager,并且配置文件中注入LoginAction,這樣LoginAction代碼如下所示。
public class LoginAction extends Action {
private UserManager userManager;
// 讓spring注入,LoginAction讓Spring管理, 不是讓strus創(chuàng)建而是由spring創(chuàng)建.
public void setUserManager(UserManager userManager) {
this.userManager = userManager;
}
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
LoginActionForm laf = (LoginActionForm) form;
String username = laf.getUsername();
String password = laf.getPassword();
userManager.login(username, password);
return mapping.findForward("success");
}
}
小結(jié):
Spring框架就相當(dāng)于我們的工具,我們把工具挖掘和使用的淋漓盡致才好,這可能就是人和工具的區(qū)別,人利用創(chuàng)造和利用工具,工具被創(chuàng)造和被利用。這中間的過(guò)程就是磨合了。
相關(guān)文章
Spring中Bean創(chuàng)建完后打印語(yǔ)句的兩種方法
這篇文章主要介紹了Spring中Bean創(chuàng)建完后打印語(yǔ)句的兩種方法,一個(gè)是實(shí)現(xiàn)InitializingBean接口,另一個(gè)使用@Bean注解和initMethod屬性,通過(guò)代碼示例介紹的非常詳細(xì),感興趣的小伙伴可以參考閱讀2023-07-07
一文教你學(xué)會(huì)搭建SpringBoot分布式項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了搭建SpringBoot分布式項(xiàng)目的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01
Java如何替換RequestBody和RequestParam參數(shù)的屬性
近期由于接手的老項(xiàng)目中存在所有接口中新增一個(gè)加密串來(lái)給接口做一個(gè)加密效果,所以就研究了一下Http請(qǐng)求鏈路,發(fā)現(xiàn)可以通過(guò)?javax.servlet.Filter去實(shí)現(xiàn),這篇文章主要介紹了Java替換RequestBody和RequestParam參數(shù)的屬性,需要的朋友可以參考下2023-10-10
springboot實(shí)現(xiàn)全局異常捕獲的使用示例
任何系統(tǒng),我們不會(huì)傻傻的在每一個(gè)地方進(jìn)行異常捕獲和處理,整個(gè)系統(tǒng)一般我們會(huì)在一個(gè)的地方統(tǒng)一進(jìn)行異常處理,本文主要介紹了springboot實(shí)現(xiàn)全局異常捕獲的使用示例,感興趣的可以了解一下2023-11-11

