實現Struts登錄
1、jar包拷貝
首先是建立java web項目,之后打開我們我們下載好strtus框架,Struts-1.2.9-bin文件夾和struts-1.2.9.src源文件文件夾。在bin文件夾中的lib文件中拷貝struts的jar包,拷貝到我們自己項目struts_login –>lib文件夾下。
2、web.xml文件配置
找到Struts-1.2.9-bin中Struts-1.2.9-bin-->webapps下的struts實例struts-blank中的struts-1.2.9-bin\webapps\struts-blank\WEB-INF下的web.xml文件,復制配置對ActionServlet的配置,粘貼到我們的項目struts_login的WEB-INF下的web.xml中,代碼如下所示。主要是對struts自帶的ActionServlet進行配置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
< 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 > <!--Standard Action Servlet Mapping --> < servlet-mapping > < servlet-name >action</ servlet-name > < url-pattern >*.do</ url-pattern > </ servlet-mapping > |
3、在項目中建立自己的ActionForm
在項目中建立自己的ActionForm,繼承struts框架中已經寫好的ActionForm,在ActionForm設置用到的數據,并且要和我們界面上設置的名稱一致。因為我們在提交表單的時候,所有的請求都會放到ActionForm中。建立登錄的ActionForm,LoginActionForm.java代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
package com.bjpowernode.struts; import org.apache.struts.action.ActionForm; /** * 登錄ActionForm,負責表單收集數據. * 表單的屬性必須和ActionForm中的get和set的屬性一致. * @author summer * */ public classLoginActionForm extends ActionForm { //用戶名。 private Stringusername; //密碼。 private String password; //設置密碼。 public voidsetPassword(Stringpassword) { this .password = password; } //得到用戶名。 public StringgetUsername() { return username; } //設置用戶名。 public voidsetUsername(Stringusername) { this .username = username; } //得到密碼。 public StringgetPassword() { return password; } } |
4、建立自己的Action
建立自己的Action,同時繼承struts框架中的org.apache.struts.action.Action,重載父類的execute方法。在這里完成取出表單中的數據。通過CalActionFormcalForm= (CalActionForm)(CalActionForm)form;(struts框架中已經幫我們封裝好了,我們去使用就可以了)來取得表單中的值。經過判斷后,進行相應的操作,跳轉到相應的頁面。Action的功能是負責拿到表單數據和調用業務邏輯后進行頁面跳轉。建立登陸的Action類,LoginAction.java類,調用業務邏輯類UserManager的login方法。代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
packagecom.bjpowernode.struts; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importorg.apache.struts.action.Action; importorg.apache.struts.action.ActionForm; importorg.apache.struts.action.ActionForward; importorg.apache.struts.action.ActionMapping; /** *登錄Action *負責取得表單數據,調用業務邏輯,返回轉向信息. * * @author summer * */ public classLoginAction extendsAction { @Override public ActionForward execute(ActionMappingmapping,ActionForm form, HttpServletRequest request, HttpServletResponseresponse) throws Exception { LoginActionForm laf = (LoginActionForm)form; Stringusername = laf.getUsername(); Stringpassword = laf.getPassword(); UserManager userManager = newUserManager(); //傳遞用戶名和密碼 try { userManager.login(username, password); request.setAttribute( "username" , username); return mapping.findForward( "success" ); } catch (UserNotFoundException e) { e.printStackTrace(); request.setAttribute( "msg" , "用戶不能找到,用戶名稱=[" +username + "+]" ); } catch (PasswordErrorException e) { e.printStackTrace(); request.setAttribute( "msg" , "密碼錯誤" ); } return mapping.findForward( "error" ); } } |
5、 建立struts-config.xml
作為Struts框架的核心描述,struts-config.xml可以說“一切盡在掌握”。它不但描述了MVC模型,定義所有視圖層和控制層之間的接口(ActionForm),與控制層和模型層的接口(Action)進行結合,而且可以定義一些附加組件,如國際化信息資源排至文件,標簽庫信息等。
仍然是站在巨人的肩膀上,將我們下載的struts bin文件夾中的struts-config.xml文件復制到我們的項目的WEB-INF中,刪除struts-config.xml中的注釋部分。把Action和ActionForm配置起來。ActionForm放到<form-beans></form-beans>中,Action配置放到<action-mappings></action-mappings>中,struts-config.xml配置代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<? xml version = "1.0" encoding = "ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration1.2//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"> < struts-config > < form-beans > < form-bean name = "loginForm" type = "com.bjpowernode.struts.LoginActionForm" /> </ form-beans > < action-mappings > < action path = "/login" type = "com.bjpowernode.struts.LoginAction" name = "loginForm" scope = "request" > < forward name = "success" path = "/login_success.jsp" /> < forward name = "error" path = "/login_error.jsp" /> </ action > </ action-mappings > </ struts-config > |
其中form-beans元素中可以定義0個或1個以上的form-bean元素,每個form-bean被認為是一個ActionForm對象,name屬性表示form-bean元素的名稱,type屬性指定其類名和路徑。
Action-mappings元素用來包含零到多個action,其子元素action負責具體映射的詳細信息。在action-mapping元素中可以定義0個或1個以上的action元素。每個action元素接受path屬性定義的請求,并映射到type屬性所定義的具體action對象。在映射過程中,將name屬性定義的actionform一并傳過去,它有如下屬性:
Parameter,scope兩個屬性指定了傳送方式和范圍,scope常用的值有兩個“session”和“request”。
Validate屬性指定了是否需要actionform的驗證。
Forward元素,將請求success轉發到”/login_success.jsp”頁面。
6、業務邏輯類UserManager和自定義異常類
代碼如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
packagecom.bjpowernode.struts; publicclassUserManager { publicvoid login(Stringusername,Stringpassword) { if (! "admin" .equals(username)) { thrownewUserNotFoundException(); } if (! "admin" .equals(password)) { thrownewPasswordErrorException(); } } } |
自定義異常類UserNotFoundException和PasswordErrorException代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
packagecom.bjpowernode.struts; public class UserNotFoundExceptionextends RuntimeException { public UserNotFoundException() { } public UserNotFoundException(Stringmessage) { super (message); } public UserNotFoundException(Throwable cause) { super (cause); } public UserNotFoundException(Stringmessage,Throwable cause) { super (message, cause); } } packagecom.bjpowernode.struts; public class PasswordErrorExceptionextends RuntimeException { public PasswordErrorException() { } public PasswordErrorException(Stringmessage) { super (message); } public PasswordErrorException(Throwable cause) { super (cause); } public PasswordErrorException(Stringmessage,Throwable cause) { super (message, cause); } } |
7、視圖jsp頁面調用。
登錄界面login.jsp,錯誤顯示界面login_error.jsp,登錄成功界面login_success.jsp。代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<% @pagelanguage = "java" contentType= "text/html; charset=GB18030" pageEncoding= "GB18030" %> <!DOCTYPEhtml PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" > <html> <head> <meta http-equiv= "Content-Type" content= "text/html; charset=GB18030" > <title>Inserttitle here</title> </head> <body> <form action= "login.do" method= "post" > 用戶:<inputtypeinputtype= "text" name= "username" ><Br> 密碼:<inputtypeinputtype= "password" name= "password" ></br> <input type= "submit" value= "登錄" > </form> </body> </html> |
Login_success.jsp.
1
2
3
4
5
6
7
8
9
10
11
12
|
<% @page language= "java" contentType= "text/html;charset=GB18030" pageEncoding= "GB18030" %> <!DOCTYPE html PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" > <html> <head> <meta http-equiv= "Content-Type" content= "text/html; charset=GB18030" > <title>Insert title here</title> </head> <body> ${username},登錄成功! </body> </html> |
Login_error.jsp界面。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<% @page language= "java" contentType= "text/html; charset=GB18030" pageEncoding= "GB18030" %> <!DOCTYPE html PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" > <html> <head> <meta http-equiv= "Content-Type" content= "text/html; charset=GB18030" > <title>Insert title here</title> </head> <body> <%-- <%=request.getAttribute( "msg" ) %> --%> ${msg } </body> </html> |
就這樣我們實現了運用struts框架完成用戶登錄。就這樣從初步學習到簡單應用,隨著應用的次數增多,我們會對struts理解越來越深刻,并且感受struts框架給我們帶來的便捷。
表單處理器ActionForm(靜態動態)
上面講解了struts配置,實現了使用struts框架進行登錄的示例。一些名詞已經在腦海中飄蕩了。
ActionServlet:struts的控制器,負責截取URL或分發。提供Model(模型層)和View(視圖層)使用,因此可將它看作是模型和視圖之間的中介。
ActionForm:用于封裝用戶的請求參數,而請求參數是通過JSP頁面的表單域傳遞過來的。
Action:用戶請求和和業務邏輯的橋梁,每個Action作為業務邏輯的代理,可以調用業務邏輯。
一些問題是有必要再次提起的。
使用基本的MVC和使用struts框架區別,使用struts好處在哪里?
我們知道我們不適用框架的時候,在MVC中典型的控制器是servlet,servlet可以獲取參數和邏輯模型的調用和轉向功能。而struts對它做了封裝,為什么要進行封裝?當我們請求到一個servlet,我們在這個servlet中取得參數、調用業務邏輯、轉向,我們在servlet中寫死了轉向頁面,當我們想要換一個轉向頁面的時候就需要改動代碼了,改動代碼后還要重新進行編譯。
而且從表單中傳遞過來的數據全是字符串形式,我們還需要根據實際的需求把字符串轉換為我們需要的類型,如果很多地方需要轉換,并且每次使用每次都要進行轉換,有沒有一種機制,把表單中的字符串拿過來自動轉換為相應的類型呢?不需要我們再進行手動轉換呢?
基于上述的不便,轉向不靈活,表單中的字符串每次都要進行轉換等一系列的原因,struts把這些做了封裝。提取出重復的操作,轉向信息放到了配置文件中,這樣更加靈活了。
在上述問題中,闡述了struts對表單的封裝,在web應用程序開發過程中,開發人員需要大量的時間來處理表單問題,有的時候是通過表單提交一些新的問題,有的是通過表單修改數據,所有這些表單在處的處理在傳統web開發中是非常復雜的。本篇重點說說struts中的表單處理器ActionForm。
ActionForm
問題的提出
在傳統的web應用程序開發中,繁雜的表單處理給開發工作人員帶來了巨大的困難,在傳統的開發語言中,沒有組建可以自動收集用戶輸入的表單內容,開發人員不得不在程序中手動提取表單的值。例如在表單中有這樣的一個文本輸入域:<inputtype=”text” name=”password”> 要在程序中取得這個文本輸入域的值,只能用這樣的方法:request.getParameter(“password”);這樣的處理方法在表單比較小的時候是可以使用的,但是當表單輸入項較多的時候就不得不大量重復類似上面的處理。
問題的解決
在Struts中就是使用ActionForm來解決這個問題,對于每一個用戶的表單,需要提供一個ActionForm,這個ActionForm自動把客戶提交的表單保存在這個ActionForm中,然后把這個ActionForm傳遞給Action,從而在Action中可以通過這個ActionForm取出用戶信息,然后根據這些信息完成對應的業務邏輯處理。
例如在Struts中用struts的html標簽表述成下述形式:
1
|
< html:text property=”password”/> |
在這種情況下表單提交后,struts框架會自動把表單中的這個輸入項賦值到ActionForm中的password屬性中,從而把表單中的內容保存在ActionForm中,整個過程由struts自動完成,不需要開發人員干涉。我們在創建ActionForm時要遵循以下規范:
(1)每個ActionForm都要繼承org.apache.struts.action.ActionForm類,而且需要為每一個表單提供一個ActionForm。
(2)ActionForm中每個屬性要與表單中的輸入項一一對應。
(3)AcitonForm每個屬性都要提供的getter方法和setter方法。Struts框架就是通過這些方法來保存表單的值,然后在Action中通過這些方法取得表單的值。
(4)如果表單需要驗證,就需要在ActionForm中提供validate方法,這個方法中提供對表單的具體驗證邏輯。這個方法不僅實現了數據驗證同時實現了數據緩沖的作用,在validate方法中驗證用戶提交表單的有效性,當表單驗證失敗時會自動返回用戶輸入頁面,這時候用戶輸入的值都保存在ActionForm中,返回頁面時struts框架會取出AcitonForm中的數據并輸出到對應的用戶輸入項中,保證了用戶開始輸入的表單信息。
問題的提出
以上所說的是靜態ActionForm,當我們為每個表單都創建一個AcitonForm的時候,會導致ActionForm數量過多。每個ActionForm過強的聚合性也會使代碼難以維護和重用。怎么樣不用去創建過多的ActionForm?而且當提交表單的屬性名字相同時,不用再重復創建AcitonForm(例如登錄和注冊)?
問題的解決
Struts中可以使用動態ActionForm來解決上述問題。動態ActionForm不需要創建自己的ActionForm,需要在創建自己Action的時候直接把execute方法中傳遞過來的form對象轉化為DynaActionForm。
我們需要更改struts-config.xml中form-beans配置:
1
2
3
4
5
6
|
< form-beans > < form-bean name = "dynaForm" type = "org.apache.struts.action.DynaActionForm" > < form-property name = "username" type = "java.lang.String" /> < form-property name = "age" type = "java.lang.Integer" /> </ form-bean > </ form-beans > |
Action中使用get方法取得表單中的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/** * 測試動態ActionForm. * @author summer * */ public classDynaActionFormTestAction extends Action { @Override publicActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequestrequest, HttpServletResponse response) throwsException { DynaActionFormdaf = (DynaActionForm)form; //取出map中key值為name,value為類名. Stringusername = (String)daf.get( "username" ); Integerage = (Integer)daf.get( "age" ); System.out.println( "username" +username); System.out.println( "username" +age); returnmapping.findForward( "success" ); } } |
靜態ActionForm方式,使用get/set方法,而動態ActionForm方式,使用map的getkey方式,其中key就是標簽name的值。
使用動態ActionForm優點:若更改表單和ActionForm時不需要重新編譯,而靜態的需要更改靜態的ActionForm.java文件,必須重新編譯。缺點:靜態返回的是對應的值,動態ActionForm返回的是對象,我們還要把這個對象進行強制轉換。