J2EE學習篇之--Struts1詳解

今天來看一下Struts1的相關知識,其實Struts如今是出名的,每一個Web開發者都會知道的,也是如今比較流行的框架,下面就來看一下咱們爲何要用Struts框架呢?javascript


摘要

1.創建在mvc這種好的模式上的,Struts在m,v,c上都有涉及,但主要的是提供一個好的控制器和一套定製的標籤庫上也就是說它在這裏體如今c和v上,有mvc的一系列的優勢,如:結構井井有條,高重用性,增長了程序的健壯性和可伸縮性,便於開發與設計分工,提供集中統一的權限的控制,校驗,國際化,日誌等等
2.開源項目,獲得了包括它的發明者Craig R.McClanahan在內的一些程序大師和高手持續而細心的呵護,而且經受了實戰的檢驗,使其功能愈來愈強大。
3.其餘技術和框架具備很好的融合性,如與Spring,hibernate等框架的整合
4.大大提升了開發速度
html


框架的概念和struts的概念和體系結構

1.Framework概念

人們用於解決相同或者類似類型問題的方案。
特色:可重用性,可擴展性,可收縮性。基於請求響應(Request-response)模式的應用Framework的邏輯結構
控制器(Controller)
業務邏輯層(Business Logic)
數據邏輯層(Data Logic)


2.Struts的概念和體系結構

struts是Apache組織的一個開源的項目,主要是採用Servlet和Jsp技術來實現的,Struts是一個基於Sun JavaEE 平臺大的MVC框架,它採用了MVC模式,將MVC模式「分離顯示邏輯和業務邏輯」的能力發揮的淋漓盡致

Struts工做原理結構

WebBroser——>UserAction———>Front end Controller ActionServlet——>Back End Controller Action——>Model JavaBean



搭建配置環境

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>


開發第一個struts程序

1.開發form

1)創建一個類,繼承ActionForm
2)註冊,修改struts-config.xml
Name:變量名
Type:類的全名
例如:

<form-beans>
	<form-bean name="loginForm" type="cn.com.hewei.bean.LoginForm"/>
</form-beans>


2.開發Action

1) 創建一個類,繼承Action覆蓋execute方法

2) 註冊,修改strutrs-config.xml編程

Path:指明調用者(jsp)能經過中心控制器ActionServlt找到該Action

Type:指明該Action的類名

Name:該Action應用的Form名稱


3.實例:模擬用戶的登陸,第一個用戶程序

1)寫bean程序,繼承ActionForm
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;
	}
}

編寫Action程序

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");
		}
	}
}

配置struts-config.xml文件

<?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>

登陸成功頁面loginSuccess.jsp

<body>
   Login Success <br>
</body>

登陸失敗頁面loginFail.jsp
<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指定的路徑


Struts的基本原理


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)將結果頁面展示給用戶。


Struts的原理詳細分析

1.Struts組件

ActionServlet 

Acation Classes,

Action Mapping(此包括ActionForward)

ActionForm Bean。

2.Struts的Mvc

1.模型(Model):本質上來講在Struts中Model是一個商業邏輯類,開發者實現商業邏輯
2.視圖(View):View是與控制器Servelt配合工做的一整套Jsp定製標籤構成,利用他們能夠快速創建應用系統的界面
3.控制器(Controller):前端控制器(總控制器)是一個Servlet,它將客戶端的請求轉發到響應的後端控制器Action類


3.ActionServlet(中心控制器)

定義:繼承自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>


Action圖解


1.Action:一個請求和業務邏輯的適配器

1)初始化時間:第一次請求的時候初始化,不是在讀取配置時初始化,
2)初始化次數:每一個Action只被初始化一次(多個請求共享一個Action)
3)安全問題:Action是線程不安全的,由於全部的請求共享一個action實例
4)怎樣實現Action的安全性問題:
主要不要用實例變量或者類變量共享只是針對某個請求的數據
注意資源操做的同步性


實例:設計一個實例變量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"/>

訪問鏈接
http://localhost:8081/Mystruts/countAction.do


2.ActionMapping和ActionForward

1).每一個<action>元素都是類org.apache.struts.action.AcationMapping
2).ActionMapping中的方法(使用ActtionStudent實例)

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>

輸出:
name  AddStudentForm
path  /addStudent
type  cn.com.hewei.Action.AddStudentAction
forwardName  addSuccess
forwardPath  /loginSuccess.jsp
forwardName  addFail
forwardPath  /loginFail.jsp


3. ActionForward(導航器)

ActionForWard對象是配置對象,這些配置對象擁有獨一無二的標識容許按照name屬性等檢索,ActionForward對象封裝了向前進的Url路徑且被請求處理器用於識別目標視圖
name:邏輯名稱
path:頁面或者模塊的訪問路徑

redirect:控制轉發仍是重定向

<forward name="addFail" path="/loginFail.jsp" redirect="true"/>

redirect=false 轉發(默認值)
redirect=false:RequestDispatch.forward
redirect=true  重定向
redirect=true:HttpServletResponse.sendRedirects


4.ActionForm

ActionForm工做原理
處理anctionForm的通常步驟
1)檢查Action的映射,肯定Action中已經配置了對ActionForm的映射
2)根據name屬性,查找formbean的配置信息
3)檢查Action的formbean的使用範圍肯定在此範圍下(request,session),是否已經有此formbean的實例<action scope=」request」>,默認是session
4)假如當前範圍下,已經存在了此form bean的實例,並且對於當請求來講,是同一種類型的話,那麼就重用
5)不然,就從新構建一個formbean的實例(調用構造方法),而且保存在必定的做用範圍
6)form bean的reset()方法被調用
7)調用對應的setter方法,對狀態屬性賦值
(相似<jsp:setProperty name=」person」 property=」*」 >)
8)若是validate的屬性設置爲true,那麼就調用form bean的validate()方法
<action validate=」true」>
9)若是validate()方法沒有返回任何的錯誤,控制器將ActionForm做爲參數,傳給Action實例的execute()方法並執行
注意:直接從ActionForm類繼承的reset()和validate()方法,並不能實現什麼處理功能,因此有必要本身從新覆蓋

圖例:


注意:
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>


在Action中加入Scope=request,輸出
Add a Session Attribute
name=AddStudentForm,value=cn.com.hewei.Bean.AddStudentForm@3bce70


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」>得到錯誤信息


3)<global-forwards>全局跳轉
<global-forwards>元素用於定義在整個應用程序內的全局轉發,在該元素內可定義多個<forward>子元素
<global-forwards>
	<forward name=」error」 path=」/error.jsp」>
</global-fowards>


本身開發Struts思路

1.ActionServlet

讀取配置dom4j
填充form
派發請求:調用對應的Action的execute方法。

查找響應


2.ActionForm

set()/get()

reset()

validate()


3.Action

Execute(ActionMapping,ActionForm,HttpServletRequest,HttpServletResponse)


4.ActionMapping

屬性:path,type,name,validate,forwards(HashMap)


5.ActionForward

name,path


6.配置文件

實例:模仿struts填充formbean


分析:
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);
	}
}


struts高級部分

1.Struts的標籤

1.1 struts標記庫

Jsp視窗組件所使用的struts標記庫由四類標記組成:

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標記:使用動態模塊構造普通格式的的頁


1. 2 Bean標記:

在標籤庫中包含用於定義新的bean,訪問bean及其屬性的標記,Bean標記庫將標記定義在四個子類別中:
建立和複製bean的標記
腳本變量定義標記
bean翻譯標記
消息國際化標記

1)Bean:define 從已有的變量或者變量的屬性定義一個新的變量
Serach:fromwhere---scope,who----name,which property---property
Define: 新定義的變量名是id屬性
Save:towhere---toScope
實例:從request中獲得userName將其放到session中去

<%@ 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是將取出來的值放到哪一個域中


Bean:write ,輸出域中的值
<b:write name="name" scope="session"/>

3)message 和jstl的<fmt:message>相似,國際化信息
定義資源文件:

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」能夠不寫


1.3 邏輯標記

邏輯庫的標記可以用來處理外觀邏輯而不須要使用scriptlet(這個屬性在咱們以前說到的自定義標籤庫的時候用到了)。Struts邏輯標籤庫包含的標記可以有條件的產生輸出文本,在對象集合中循環從而重複的產生輸出文本,應用程序流程控制,它也提供了一組在Jsp頁中處理流程控制的標記。這些標記封裝在文件名struts-logic.tld的標記 包中,邏輯標記庫定義的標記可以執行下列三個功能
條件邏輯,重複,轉發/重定向響應
1.循環 iterate(至關於forEach標籤)
1)name:所指代的bean必須是一個集合類型
2)property:bean中的屬性
<logic:iterator id=」username’ scope=」request’  name=」userNames」>
   ${username}
</logic:iterator>
3)   offset 設置循環的起始值
4)indexId 當前循環的下標
5)length 長度


2.動態表單和異常處理

2.1 動態表單

它讓程序員不須要書寫formbean,只須要在配置文件中配置便可
1)配置struts-config.xml

<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;
	}
}

2.2 struts中異常的處理

一.配置異常(在struts-config.xml文件中定義)
定製異常有兩種:「全局異常(Global Exceptions)」和局部異常(Local Exception)
1.局部異常定義以下:(寫在action的內部第一個)

<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>

2.3.獲得異常的信息

咱們能夠經過exception中的key關鍵字到配置文件中找到配置文件的信息
1)寫異常文件
 ApplicationResource.properties
在其中輸入信息:<exception>標籤中key的值 = 異常的描述
例:ss=it is a validare user

2)註冊異常文件(文件的末尾不要加.properties)
<message-resources parameter="cn.com.hewei.bean. ApplicationResource">
</message-resources>

3)在頁面輸出異常的信息
在頁面註冊taglib
<%@taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
調用
<html:errors/>  輸出全部的異常信息

2.4 struts中插件的使用

1.接口爲Plugin,生命週期方法:init和destroy
2.用戶提供setter方法,告訴ActionServlet中心控制器設置屬性
應用:在struts啓動的時候把hibernate加載進來(讀取hibernate配置文件和打開hibernate的sessionfactory)。
1)struts 的jar包+hibernate的jar包
2)設計一個類:HibernatePlugin實現plugin接口 
屬性:String  hibernateConfigFile
讀取hibernate配置文件
打開SessionFactory
釋放資源
3)在struts-config配置文件中填上一對<plugin>,在plugin中加上子標籤
實例:
工具類:
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>

能夠在中心控制器ActionServlet的init方法對plugin初始化在destroy方法中銷燬
插件的生命週期:


DispatchAction

3.1 DispatchAction

派發Action的使用:實現多個方法會有多個Action這樣太複雜了,可使用DispatchAction
如圖:

在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>

3.訪問
http://localhost:8080/Mystruts/StudentAction.do?method=addStudent
輸出:addStudent
http://localhost:8080/Mystruts/StudentAction.do?method=deleteStudent
輸出:deleteStudent
http://localhost:8080/Mystruts/StudentAction.do?method=updateStudent

輸出:updateStudent


注意:
1)能夠開發一個DispatherAction’的子類
這裏的方法注意必須與原來的execute方法同參同返回值
2)配置parameter屬性

3.2 MappingDispatchAction

使用DispatchAction轉發,每次使用的是同一個Action,這樣很容易錯誤,爲了解決這個問題咱們使用MappingDispatchAction
實例:

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;
	}

}

配置文件:這裏的parameter不能夠隨便寫,必須和action中的方法名相同
<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>

訪問:(這樣就能夠訪問不一樣的路徑轉到不一樣的action了)
http://localhost:8080/Mystruts/addStudent.do
http://localhost:8080/Mystruts/deleteStudent.do

http://localhost:8080/Mystruts/updateStudent.do


3.3.Struts防止表單的重複提交

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>

login.jsp

<%@ 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)判斷是否重複提交。


3.4 struts的驗證框架

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目錄中的例子中找到
validator-rules.xml
2)在配置文件中加入對以上兩個文件的插件

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
	<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" />
</plug-in>

bean類
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;
	}
}

Action類
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>

寫validation.xml
<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>

7) 寫顯示錯誤的資源文件(Login.properties)

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()方法

本文所使用的案例項目工程下載地址:

http://download.csdn.net/detail/jiangwei0910410003/7398529

相關文章
相關標籤/搜索