今天來看一下Struts1的相關知識,其實Struts如今是出名的,每一個Web開發者都會知道的,也是如今比較流行的框架,下面就來看一下咱們爲何要用Struts框架呢?javascript
1.創建在mvc這種好的模式上的,Struts在m,v,c上都有涉及,但主要的是提供一個好的控制器和一套定製的標籤庫上也就是說它在這裏體如今c和v上,有mvc的一系列的優勢,如:結構井井有條,高重用性,增長了程序的健壯性和可伸縮性,便於開發與設計分工,提供集中統一的權限的控制,校驗,國際化,日誌等等
2.開源項目,獲得了包括它的發明者Craig R.McClanahan在內的一些程序大師和高手持續而細心的呵護,而且經受了實戰的檢驗,使其功能愈來愈強大。
3.其餘技術和框架具備很好的融合性,如與Spring,hibernate等框架的整合
4.大大提升了開發速度
html
1.新建web工程前端
2.加入必要的jar包java
固然還可能須要其餘的jar,這個在實際應用用遇到問題或者報錯,咱們能夠添加相應的jar,而不必刻意的去記住哪些jar程序員
3.在WEB-INF下加入配置文件struts-config.xmlweb
主要在這裏咱們須要配置咱們定義的ActionForm,和Actionredis
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"> <struts-config> <form-beans> </form-beans> <action-mappings> <action path=""></action> </action-mappings> </struts-config>
4.配置web.xmlsql
配置Struts中的總控制器ActionServlet,把配置文件做爲一個實例化參數的值傳進來的(這裏能夠傳遞多個配置文件的,中間使用逗號進行分割的,具體能夠查看源碼ActionServlet),並且咱們還看到這個servlet的啓動優先級是0,也就是最高的優先級,這個只是咱們在以前JavaWeb學習篇中的Servlet中說過,還有就是要配置訪問的映射url,這裏是只要後綴名是.do的就能夠apache
<?xml version="1.0" encoding="UTF-8"?> <web-app 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"> <display-name></display-name> <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> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
<form-beans> <form-bean name="loginForm" type="cn.com.hewei.bean.LoginForm"/> </form-beans>
2) 註冊,修改strutrs-config.xml編程
Path:指明調用者(jsp)能經過中心控制器ActionServlt找到該Action
Type:指明該Action的類名Name:該Action應用的Form名稱
package cn.com.hewei.Bean; import org.apache.struts.action.ActionForm; public class LoginForm extends ActionForm { 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; } }
package cn.com.hewei.Action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import cn.com.hewei.Bean.LoginForm; public class LoginAction extends Action { @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 轉換成LoginForm LoginForm login = (LoginForm) form; if (login.getUserName().equals("admin")) { return mapping.findForward("loginSuccess"); } else { return mapping.findForward("loginFail"); } } }
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"> <struts-config> <form-beans> <form-bean name="loginForm" type="cn.com.hewei.Bean.LoginForm"> </form-bean> </form-beans> <action-mappings> <action path="/Login" type="cn.com.hewei.Action.LoginAction" name="loginForm"> <forward name="loginSuccess" path="/loginSuccess.jsp"></forward> <forward name="loginFail" path="/loginFail.jsp"></forward> </action> </action-mappings> </struts-config>咱們要注意一點全部的path=都要以「/」開頭
Login.jsp
<body> <form action="<%=request.getContextPath()%>/Login.do" method="post"> <!--這裏的uerName和passWord要和bean中的如出一轍--> username: <input type="text" name="userName">用戶名</input> password: <input type="text" name="passWord">密碼</input></br> <input type="submit" value="提交"> <form> </body>
<body> Login Success <br> </body>
<body> Login Fail <br> </body>
1)在瀏覽器的地址欄中輸入index.jsp
2)輸入用戶名密碼後點擊提交,跳轉到Login.do、
3)由於是.do結尾的因此會被web.xml的ActionServlet解析到,ActionServlet會查看struts-config.xml文件,根據action標籤的path和跳 轉到LoginAction這個Servlet目錄
4)跳轉時,會根據action的name屬性帶着ActionForm中的內容交給LoginAction處理
5)LoginAction處理好後根據findForward將跳轉的關鍵字帶給ActionServlet處理,ActionServlet會查看Struts-config.xml文件根據forward標籤,和name屬性(那麼屬性判斷帶來的關鍵字)跳轉到path指定的路徑
1.讀取配置(初始化ModuleConfig對象)
Struts框架總控制器(ActionServlet)是一個Servelt,在web.xml中配置成自動啓動的Servlet,在Web.xml中配置成自動啓動的Servlet。讀取配置文件(Struts-config.xml)的配置文件信息,爲不一樣的Struts模塊初始化響應的ModuleCofig對象:ActionConfig,ControlConfig,FormBeanConfig,ForwardConfig,MessageResourcesConfig(必定要記得看源碼)
2.發送請求
用戶提交表單或調用URL向web應用的程序器提交一個請求,請求的數據用HTTP協議上傳給Web服務器
3.填充Form(實例化,復位,填充數據,校驗,保存)
(*.do請求)從ActionConfig中找到對應該請求的Action的子類,如沒有對應的Action,控制器直接轉化給Jsp或靜態的頁面。若有對應的Action且這個Action有一個對應的ActionForm,ActionForm被實例化並用HTTP請求的數據填充其屬性,而且保存在ServletConfig中(request或session中),這樣他們就能夠被其餘的Action對象或者Jsp調用了。這個後面會說到如何保存這個form到各個域中
4.派發請求
控制器根據配置信息ActionConfig將請求派發到具體的Action,相應的FormBean一併傳給這個Action的execute()方法
5.處理業務
Action通常只包含一個execute()方法,它負責執行相應的業務邏輯(調用其餘業務模塊)。完畢返回一個ActionFoward對象,控制器經過這個AcationForward對象進行轉發工做。
6.返回響應
Action根據業務邏輯處理的不一樣結果返回一個目標響應對象總控制器,該目標響應對象給總控制器,該目標響應對象對應一個具體的Jsp頁面或另外一Action
7.查找響應(翻譯響應)
總控制器根據業務功能Action返回的目標響應對象,找到對應的資源對象,一般是一個具體的jsp頁面.
8.響應客戶
目標響應對象結果展示給用戶目標響應對象(JSP)將結果頁面展示給用戶。
ActionServlet
Acation Classes,
Action Mapping(此包括ActionForward)
ActionForm Bean。
定義:繼承自javax.servelt.http.HttpServlet類,是中心控制器(總控制器)。它提供了一箇中心位置來處理所有的終端請求
1)做用:接受請求,填充數據,派發請求,響應用戶
2)配置:在web配置文件(web.xml)聲明:
<servlet> <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> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
實例:設計一個實例變量count,統計訪問的次數
package cn.com.hewei.Action; import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; public class CountAction extends Action{ int count=0; @Override //每一個訪問一個execute方法 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { response.setCharacterEncoding("gbk"); request.setCharacterEncoding("gbk"); synchronized (this) { count++; } PrintWriter out=response.getWriter(); out.print("訪問的次數"+count); return null; } }
<action path="/countAction" type="cn.com.hewei.Action.CountAction"/>
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 得到Action的name String name=mapping.getName(); // 得到Action的type String type=mapping.getType(); // 得到Action的path String path=mapping.getPath(); String []forwardNames=mapping.findForwards(); System.out.println("name "+name); System.out.println("path "+path); System.out.println("type "+type); for(String forwardName:forwardNames ){ ActionForward forward=mapping.findForward(forwardName); String forwardPath=forward.getPath(); System.out.println("forwardName "+forwardName); System.out.println("forwardPath "+forwardPath); } }
<action path="/addStudent" type="cn.com.hewei.Action.AddStudentAction" name="AddStudentForm"> <forward name="addSuccess" path="/loginSuccess.jsp"></forward> <forward name="addFail" path="/loginFail.jsp"></forward> </action>
redirect:控制轉發仍是重定向
<forward name="addFail" path="/loginFail.jsp" redirect="true"/>
注意:
1.無參構造函數必需要有(經過讀取配置文件中的信息進行實例化)
2.Scope缺省值爲session
咱們怎麼查看是否往scope中添加了元素了呢?咱們可使用監聽器來作(這個咱們在前面說到Servlet中的監聽器和過濾器)
1)監聽HttpSessionAttributeListener,
ServletRequestAttributeListener接口
package cn.com.hewei.listener; import javax.servlet.ServletRequestAttributeEvent; import javax.servlet.ServletRequestAttributeListener; import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionBindingEvent; import org.apache.struts.action.ActionForm; public class ActionListener implements HttpSessionAttributeListener,ServletRequestAttributeListener { public void attributeAdded(HttpSessionBindingEvent event) { //獲得session中的name String attributeName=event.getName(); //獲得session中的value,判斷是不是struts的類 if(event.getValue() instanceof ActionForm){ System.out.println("Add a Session Attribute"); System.out.println("name="+attributeName+",value="+event.getValue()); } } public void attributeReplaced(HttpSessionBindingEvent event) { String attributeName=event.getName(); if(event.getValue() instanceof ActionForm){ System.out.println("Replace a Session Attribute"); System.out.println("name="+attributeName+",value="+event.getValue()); } } public void attributeAdded(ServletRequestAttributeEvent event) { String attributeName=event.getName(); if(event.getValue() instanceof ActionForm){ System.out.println("Add a Request Attribute"); System.out.println("name="+attributeName+",value="+event.getValue()); } } public void attributeReplaced(ServletRequestAttributeEvent event) { String attributeName=event.getName(); if(event.getValue() instanceof ActionForm){ System.out.println("Replace a Request Attribute"); System.out.println("name="+attributeName+",value="+event.getValue()); } } }
2)註冊監聽器
<listener> <listener-class> cn.com.hewei.listener.ActionListener </listener-class> </listener>
3.reset方法,是讓表當中的數據恢復默認值
4.調用setter方法,其實是調用對應的標準set方法,好比username有setUsername()
5.<action validate=「false」>關閉校驗,默認自動校驗
6.配置文件中的屬性
1)<action-mappings>元素
<action-mappings>元素幫助進行擴建內部的流程控制,可將請求的URL映射到Action類,將Action對象與ActionForm對象想相互聯,<action-mappings>元素內能夠定義多個<action>子元素
2)<action>元素
所描述的是將特定的請求路徑和一個相應的Action類之間的映射關係,有如下的屬性
attribute:設置和Action關聯的formbean在request/session內的屬性key,經過request/session的getAttribute(attribute)方法返回該formbean實例(用來存取form的關鍵字,缺省值和formbean標籤中的name同樣的)
validate:用來控制是否校驗表單,(校驗表單時,當返回null或者ActionErrors沒有帶ActionMessage信息時,校驗成功)
input:當表單驗證失敗時請求轉發的URL,通常結合validate=「true「使用
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors=new ActionErrors(); ActionMessage m=new ActionMessage("ss"); errors.add("error",m); return errors; }
咱們在jsp中能夠經過<bean:errors property=」error」>得到錯誤信息
<global-forwards> <forward name=」error」 path=」/error.jsp」> </global-fowards>
查找響應
set()/get()
reset()validate()
Execute(ActionMapping,ActionForm,HttpServletRequest,HttpServletResponse)
屬性:path,type,name,validate,forwards(HashMap)
name,path
分析:
1)建立AddstudentForm對象----根據類的全名進行反射(Class.forName)
2)須要把頁面的參數提取出來(request.getParameterNames()----Enumeration)
3)把參數名與bean的屬性名進行匹配:若是能匹配就把取出來的值填充到bean中(藉助BeanUtils)
4)保存form
設計一個FormUtil完成以上描述的功能
package cn.com.hewei.util; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.commons.beanutils.BeanUtils; import org.apache.struts.action.ActionForm; public class FormUtil { public static void fillForm(HttpServletRequest request, String formClassFullName, String ClassName) throws InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException {// 實例化實體 ActionForm form = (ActionForm) Class.forName(formClassFullName).newInstance(); // 獲得全部從網頁傳來的參數 Map parameters = request.getParameterMap(); // 獲得全部bean中的參數 Field[] fields = Class.forName(formClassFullName).getDeclaredFields(); // 填充bean BeanUtils.populate(ClassName, parameters); // 往session中傳數 request.getSession().setAttribute(ClassName, form); } }
1)Bean標記:用來在Jsp頁中管理bean
2)邏輯標記:用來在Jsp頁中控制流程3)Html標記:用來生成HTML標記,在表單中顯示數據,使用會話的ID對URL進行編程
Struts提供了不少表單相關的自定義標籤,如:
<html:text>
<html:radio>
<html:select>
<html:option>
<html:checkbox>
<html:multibox>
<html:textarea>
這些標籤除用於生成相應的html標籤外,最大的好處在於它在產生html標籤時,會自動檢索相應formbean的數據予以顯示,這樣,當表單校驗失敗時,表單數據的回顯struts幫咱們幹了,開發人員就不須要再編碼去取了。
使用Struts的html標籤完成數據回顯時注意的問題:
html標籤回顯數據時,會以org.apache.struts.taglib.html.BEAN爲關鍵字,從各個域中查找bean,找不到則拋空指針異常。因此使用html標籤時域中須有以org.apache.struts.taglib.html.BEAN爲關鍵字的對象。
這個工做能夠交給html:form標籤作,html:form標籤在執行時,會查找域中已有的formbean,並以org.apache.struts.taglib.html.BEAN爲關鍵字把formbean存在域中。若是html:form標籤在域中找不到formbean,則html:form標籤會實例化一個空bean,而後存儲到域中。所以,爲了在頁面中使用struts的html標籤回顯數據,這些標籤須要配合html:form標籤使用。(查看html:form標籤的源文件能夠看到這點)。
對於複選框中的數據,Html:checkbox標籤不能完成數據回顯,複選框的數據回顯須要使用html:multibox。
Struts中的html:password標籤也會回顯數據,若是不想password回顯,須要把其redisplay屬性置爲false。
4)tiles標記:使用動態模塊構造普通格式的的頁
<%@ page language="java" import="java.util.*" pageEncoding="gbk"%> <!--taglib能夠從struts-taglib.bean包中META-INF中的tld中找到--> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="b"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'BeanUtil.jsp' starting page</title> </head> <body> <%String userName="ss";request.setAttribute("userName",userName);%> <!--id是新定義的名稱,name是scope中的key值,toScope是將存到的域的值。若是是複合類型的值,定義property得到是哪一個參數的值--> <b:define id="name" name="userName" scope="request" toScope="session"/> ${sessionScope.name} </body> </html>
這裏注意的是scope是從哪一個域中進行取值,toScope是將取出來的值放到哪一個域中
<b:write name="name" scope="session"/>
com.itcast.AlliacationRescources.properties
com.itcast. AlliacationRescources_zh-CN.properties
下面是AlliacationRescources_zh-CN.properties的內容:
這個是UTF-8編碼以後的內容了
在struts-config中添加
<message-resources paremeter="com.itcast.ApplicationResources"key="myKey"/>
這裏的填寫的就是資源文件的全稱地址,可是要注意不須要後綴名的,並且這裏能夠配置多個資源文件的
頁面中使用
<bean:message bundle=」myKey」 key=」userName」> <bean:message bundle=」myKey」 key=」password’>注意:上面配置的key=」myKey」和這裏的bundle=」myKey」能夠不寫
<form-bean name="dynStudentForm" type="org.apache.struts.action.DynaActionForm"> <!-- 這裏的type必須是完整的 --> <form-property name="sname" type="java.lang.String" /> <form-property name="birthday" type="java.sql.Date" /> <form-property name="major" type="java.lang.String" /> <form-property name="score" type="java.lang.Float" /> </form-bean> <action path="/dynAddStudent" type="cn.com.hewei.Action.DynAddStudentAction" name="dynStudentForm"> <forward name="addSuccess" path="/loginSuccess.jsp"></forward> <forward name="addFail" path="/loginFail.jsp"></forward> </action>
package cn.com.hewei.Action; import java.sql.Date; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.DynaActionForm; public class DynAddStudentAction extends Action { @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { DynaActionForm dynform = (DynaActionForm) form; // 得到信息 String name = (String) dynform.get("sname"); Date birthday = (Date) dynform.get("birthday"); String major = (String) dynform.get("major"); Float score = (Float) dynform.get("score"); System.out.println("name=" + name + "birthday=" + birthday + "score=" + score); return null; } }
<exception type="java.lang.Exception" path="/index.jsp" key="ss"></exception>這裏的path是要跳轉的頁面,type是異常的類型,key是異常的關鍵字,相應action中execute拋出異常就會跳到這裏處理
2.全局異常的配置
<global-exceptions> <exception type="java.lang.Exception" path="/index.jsp" key="ss"></exception> </global-exceptions>
<message-resources parameter="cn.com.hewei.bean. ApplicationResource"> </message-resources>
<%@taglib uri="http://struts.apache.org/tags-html" prefix="html"%>調用
<html:errors/> 輸出全部的異常信息
package cn.com.hewei.plugin; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class SessionFactoryManager { private static String hibernateConfigFile = null; public static String getHibernateConfigFile() { return hibernateConfigFile; } public static void setHibernateConfigFile(String hibernateConfigFile) { SessionFactoryManager.hibernateConfigFile = hibernateConfigFile; } private static Configuration con = null; private static SessionFactory sessionFactory = null; public static SessionFactory getSessionFactory() { con = new Configuration().configure(hibernateConfigFile); sessionFactory = con.buildSessionFactory(); return sessionFactory; } public static void closeSessionFactory() { if (sessionFactory != null && sessionFactory.isClosed() == false) sessionFactory.close(); } }
package cn.com.hewei.plugin; import javax.servlet.ServletException; import org.apache.struts.action.ActionServlet; import org.apache.struts.action.PlugIn; import org.apache.struts.config.ModuleConfig; public class HibernatePlugin implements PlugIn { private String hibernateConfigFile; public String getHibernateConfigFile() { return hibernateConfigFile; } public void setHibernateConfigFile(String hibernateConfigFile) { this.hibernateConfigFile = hibernateConfigFile; } public void destroy() { // 關閉sessionFactory System.out.println("closeSessionFactory"); SessionFactoryManager.closeSessionFactory(); } public void init(ActionServlet arg0, ModuleConfig arg1) throws ServletException { System.out.println("openSessionFactory"); // 1.讀取hibernate配置文件 SessionFactoryManager.setHibernateConfigFile(hibernateConfigFile); // 2.打開sessionFactory SessionFactoryManager.getSessionFactory(); } }
<plug-in className="cn.com.hewei.plugin.HibernatePlugin"> <set-property property="hibernateConfigFile" value="/WEB-INF/hibernate.cfg.xml"/> </plug-in>
在action標籤中使用parameter屬性:<action parameter=」method」>
調用:http://localhost:8081/Mystruts/SrudentAction?method=update
實例:
1,繼承DispathAction
package cn.com.hewei.Action; import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.actions.DispatchAction; public class StudentAction extends DispatchAction{ public ActionForward addStudent(ActionMapping arg0, ActionForm arg1, HttpServletRequest arg2, HttpServletResponse arg3) throws Exception { PrintWriter out=arg3.getWriter(); out.println("addStudent"); return null; } public ActionForward deleteStudent(ActionMapping arg0, ActionForm arg1, HttpServletRequest arg2, HttpServletResponse arg3) throws Exception { PrintWriter out=arg3.getWriter(); out.println("deleteStudent"); return null; } public ActionForward updateStudent(ActionMapping arg0, ActionForm arg1, HttpServletRequest arg2, HttpServletResponse arg3) throws Exception { PrintWriter out=arg3.getWriter(); out.println("updateStudent"); return null; } }
<action path="/StudentAction" type="cn.com.hewei.Action.StudentAction" name="dynStudentForm" parameter="method"> <forward name="addSuccess" path="/loginSuccess.jsp"></forward> <forward name="addFail" path="/loginFail.jsp"></forward> </action>
輸出:updateStudent
public class StudentAction extends MappingDispatchAction{ public ActionForward addStudent(ActionMapping arg0, ActionForm arg1, HttpServletRequest arg2, HttpServletResponse arg3) throws Exception { PrintWriter out=arg3.getWriter(); out.println("addStudent"); return null; } public ActionForward deleteStudent(ActionMapping arg0, ActionForm arg1, HttpServletRequest arg2, HttpServletResponse arg3) throws Exception { PrintWriter out=arg3.getWriter(); out.println("deleteStudent"); return null; } public ActionForward updateStudent(ActionMapping arg0, ActionForm arg1, HttpServletRequest arg2, HttpServletResponse arg3) throws Exception { PrintWriter out=arg3.getWriter(); out.println("updateStudent"); return null; } }
<action path="/addStudent" type="cn.com.hewei.Action.StudentAction" name="dynStudentForm" parameter="addStudent"> </action> <action path="/deleteStudent" type="cn.com.hewei.Action.StudentAction" name="dynStudentForm" parameter="deleteStudent"> </action> <action path="/updateStudent" type="cn.com.hewei.Action.StudentAction" name="dynStudentForm" parameter="updateStudent"> </action>
http://localhost:8080/Mystruts/updateStudent.do
Struts的<html:form>標籤除了能夠生成<form>標籤、協助其它html標籤完成數據回顯外,它還提供了防止表單重複提交的功能。
<html:form>標籤在生成表單時,會檢查session域中是否存在token,若是存在則自動使用token生成隱藏字段。
Struts爲方便開發人員生成token,在action中提供了saveToken方法,調用這個方法就能夠在session域中保存一個token。
Struts爲方便開發人員在action中校驗用戶是否爲重複提交,所以它在action中也提供了isTokenValid方法,該方法會自動判斷表單是否爲重複提交。
防表單重複提交在struts中的作法:
一、用戶先訪問Action,Action中調用saveToken方法,而後派發到表單頁面。
二、在表單頁面中使用<html:form>標籤, <html:form>標籤會自動爲表單生成一個帶隨機值的隱藏字段。
三、在表單提交的Action中調用isTokenValid方法,就能夠判斷出表單是否爲重複提交,從而能夠根據狀況決定如何處理。 isTokenValid方法返回true,則爲容許提交,處理提交後,要記得調用reset清除token。
代碼以下:
package cn.com.ambow.struts.day3; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.actions.MappingDispatchAction; public class TokenAction extends MappingDispatchAction { public ActionForward toLogin(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ActionForward forward = null; // 生成隨機數 saveToken(request); return mapping.findForward("login"); } public ActionForward login(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ActionForward forward = null; try { String name = request.getParameter("userName"); String password = request.getParameter("password"); IUserDao dao = new UserDaoImpl(); // 比較token if (!isTokenValid(request, true)) { request.setAttribute("message", "Token Error!!"); forward = mapping.findForward("error"); } else { User user = dao.findByNameAndPassword(name, password); if (user != null) { request.setAttribute("user", user); forward = mapping.findForward("success"); } else { request.setAttribute("message", "Login Error!!"); forward = mapping.findForward("error"); } } } catch (Exception e) { e.printStackTrace(); request.setAttribute("message", "Login Error!!"); forward = mapping.findForward("error"); } return forward; } }
<action path="/struts1/token/toLogin" type="cn.com.ambow.struts.day3.TokenAction" parameter="toLogin"> <forward name="login" path="/struts/day3/token/login.jsp"></forward> </action> <action path="/struts1/token/login" type="cn.com.ambow.struts.day3.TokenAction" parameter="login" name="loginForm"> <forward name="success" path="/struts/day3/token/success.jsp"></forward> <forward name="error" path="/struts/day3/token/error.jsp"></forward> </action>
<%@ page language="java" import="java.util.*" pageEncoding="gbk"%> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%> <html> <head> <title>My JSP 'login.jsp' starting page</title> </head> <body> <h2 align="center">測試Srtuts1 Token</h2> <hr/> <html:errors/> <html:form action="/struts1/token/login.do" method="post"> userName:<input type="text" name="userName"> password:<input type="password" name="password"> <input type="submit" value="loginsss"> </html:form> </body> </html>
訪問toLogin.do會帶來jsessionid,跳到登陸頁面,登陸頁面跳轉到login.do執行,isTokenValid(request, true)判斷是否重複提交。
Validator(驗證器)框架是一個 Struts 插件,它支持採用聲明式的方式對錶單進行校驗,而不須要用戶編寫一行Java代碼。集成validate框架 ,Struts那哥們他幫你校驗了表單,並且客戶端也校驗,好比javascript校驗他也幫你校驗了使用 Validator 框架的好處:
更好的可維護性
校驗實現標準化
正確的實現
更少的代碼重複
自動客戶端驗證
解壓Struts的例子struts-cookbook-1.3.8,部署到web服務器中,查看例子體驗。
在工程中集成validate框架,你須要查看org.apache.struts.validator包下的validator-rules.xml文件,它是validate框架的校驗規則文件,這個文件說明了如何在struts工程中集成validate框架:
一、在struts-config.xml文件中配置validate插件。
二、建立資源文件,並複製validate框架工做須要的信息。
三、把struts-cookbook-1.3.8例程自帶的、validate框架的配置文件validation.xml,複製到當前web工程的WEB-INF目錄下。
validate框架環境搭建好後,就能夠採用配置的方式對formbean的屬性進行校驗,但須要注意:
一、formbean要想使用validate框架校驗,不能直接繼承 ActionForm, 而要繼承其子類 ValidatorForm。
二、若是是DynaActionForm,就必需要繼承DynaValidatorForm
Validation.xml文件詳解
<form>元素:爲表單配置驗證規則,它的 name 屬性指定了表單的名字.<form>元素能夠包含一個或多個<field>子元素
<field>元素:配置表單中字段的驗證規則
property:指定 ActionForm Bean 中須要進行驗證的字段的名字
depends:指定字段的驗證規則,多個驗證規則之間以逗號隔開
<msg>元素:指定驗證規則對應的消息文本。該消息文本將替代在 validator-rules.xml 文件中爲驗證規則配置的默認的消息文本
name:指定驗證規則的名字
key:當 resource 爲 true 時,該屬性指定消息 key,該消息 key 應該在 Resource Bundle 中存在,當 resource爲 false 時,該屬性直接指定消息文本
resource:當該屬性爲true時,代表使用來自於 Resource Bundle 的消息;若是爲 false,代表 直接在 key 屬性中設置消息文本,默認爲 true
arg 元素:替換符合消息中的參數
name,key,resource 元素同上
position 元素:指定替換符合消息中的參數的位置
var 元素:向驗證規則傳遞參數
<arg> 元素:也能夠訪問<var>元素,語法爲${var:var-name}
Struts-Validate客戶端驗證
Validator 框架也能夠進行瀏覽器客戶端驗證,示例:
注意:<html:javascript>的formName指定表單的名稱。onsubmit事件的值也必須爲return validate表單名(this)
具體步驟:
1)在src下導入validation.xml和validator-rules.xml
validattion.xml文件能夠從Struts1源代碼目錄中的apps目錄中的例子中找到<plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" /> </plug-in>
package cn.com.hewei.Bean; import org.apache.struts.action.ActionForm; public class LoginForm extends ActionForm { 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; } }
package cn.com.hewei.Action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.actions.MappingDispatchAction; public class LoginAction extends MappingDispatchAction{ public ActionForward login(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ActionForward forward = null; try{ String name = request.getParameter("name"); String password = request.getParameter("password"); if("admin".equals(name) && "admin".equals(password)){ request.setAttribute("name", name); forward = mapping.findForward("success"); }else{ request.setAttribute("message", "Login Error!!!!"); forward = mapping.findForward("error"); } }catch(Exception e){ e.printStackTrace(); request.setAttribute("message", "Login Error!!!!"); forward = mapping.findForward("error"); } return forward; } }
<body> <h2 align="center">測試struts的驗證框架</h2> <hr /> <font color="red"> <html:errors /> </font> <! —必須使用struts標籤提交-- <html:form action="/login.do" method="post" onsubmit="return vloginForm(this)"> userName:<input name="name" type="text" /> password:<input name="password" type="password" /> <input type="submit" value="login"/> <html:javascript formName="vloginForm"/> </html:form> </body>
<form-validation> <formset> <!—這裏的name和表單的formName要一致--> <form name="vloginForm"> <!—depends是驗證器,key是輸出的信息--> <field property="name" depends="required"> <arg key="validate.name"/> </field> <field property="password" depends="required"> <arg key="validate.password"/> </field> </form> </formset> </form-validation>
validate.name=userName
validate.password=password
errors.required={0} is required
這裏使用了佔位符操做
8) 寫配置文件
<!—這裏的name和表單的name以及 validation中form的name一致--> <form-bean name="vloginForm" type="cn.com.hewei.Bean.ValidateLoginForm"></form-bean> <action path="/login" type="cn.com.hewei.Action.LoginAction" parameter="login" name="vloginForm" validate="true" input="/login.jsp"> <forward name="success" path="/loginSuccess.jsp"></forward> <forward name="error" path="/loginFail.jsp"></forward> </action> <!—加入資源文件--> <message-resources parameter="cn.com.hewei.Bean.Login" ></message-resources>
總結:Struts1自己的內容不少的,一篇文章是講不完的,只有在使用的時候遇到具體的問題的時候,採起解決,固然這裏還須要說明的一點就是必定要記得看源碼,由於Struts1的源碼不是很難的,看的也不費勁,有不少問題都是能夠在源碼中找到答案的,大綱以下:
Struts的控制器組件主要包括
ActionServlet對象:Struts 的核心類
RequestProcessor對象:由ActionServlet調用,負責處理用戶請求
Action對象:用戶本身編寫的類
Struts處理請求的流程:
當 ActionServlet 接收到 HTTP 請求後,在 doGet 或 doPost 方法中都會調用process()方法處理請求
在 ActionServlet 的 process() 方法中一旦選擇了正確的子應用模塊,就會調用RequestProcessor實例的process()方法來處理請求。在ActionServlet調用這個方法時,會把當前的request和response對象傳給它
RequestProcessor實例的process()方法調用ProcessActionCreate()方法,先判斷是否在 Action 緩存中存在Action實例,若是不存在,就建立一個Action實例,把它保存在 Action 緩存中
RequestProcessor實例的process()方法調用Action實例的execute()方法
本文所使用的案例項目工程下載地址: