天天看點

Struts2 Action學習

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="java">
           

學習了Struts2 中的Action,把常用到的地方記錄下來。Struts2的Action在MVC的設計模式中充當了controller的角色,用于接受參數,處理部分邏輯等,相當于Servlet。其部分使用講解如下:

一、Action的配置在struts.xml中進行Action的配置,具體可參看here。

二、Action的三種寫法(Action都要在struts中配置映射)

1、自己編寫普通的Java類來作為Action。

這裡在類中隻需要聲明一個傳回類型為String的public方法。

public void actionMethod(){
    System.out.println("Action ActionMethod called!");
    return success;
}
           

              要注意的是,如果方法的名字不為execute,那麼要在struts.xml中的action節點配置method屬性(Action預設調用的方法)才可以調用到本方法,否則struts報找不到execute錯誤。

<action name="first" class="com.tas.strutslearn.Action1" method="<span style="font-family: Arial, Helvetica, sans-serif;">actionMethod</span>">
    		<result>/index.jsp</result>
    	</action>
           

2、編寫Java類并實作com.opensymphony.xwork2.Action接口,然後重寫execute方法。

package com.tas.strutslearn;

import com.opensymphony.xwork2.Action;

public class Action2 implements Action{

	@Override
	public String execute() throws Exception {
		System.out.println("Action2 execute called!");
		return SUCCESS;
	}
}
           

3、編寫Java類并繼承com.opensymphony.xwork2.ActionSupport類,檢視ActionSupport源碼可知,本類實作了Action接口,并實作了一些其他的方法,是以在通常的使用中,會采取這種方法來編寫Action。

package com.tas.strutslearn;

import com.opensymphony.xwork2.ActionSupport;

public class Action3 extends ActionSupport{
	
	@Override
	public String execute() throws Exception {
		System.out.print("Action3 execute called!!");
		return SUCCESS;
	}
}
           

三、 Action的動态方法調用

如果一個Action中有多個方法,如下:

package com.tas.strutslearn;

import com.opensymphony.xwork2.ActionSupport;

public class Action3 extends ActionSupport{
	
	@Override
	public String execute() throws Exception {
		System.out.print("Action3 execute called!!");
		return SUCCESS;
	}
	
	public String delete(){
		System.out.print("Action3 delete called!!");
		return SUCCESS;
	}
	
	public String add(){
		System.out.print("Action3 add called!!");
		return SUCCESS;
	}
}
           

那麼如果指定調用哪個方法呢?以前我都是采用的在struts.xml中配置多個Action,用method區分的方法來實作:

<!-- 調用Action3的delete方法 -->
    <action name="thirddelete" class="com.tas.strutslearn.Action3" method="delete">
    	<result>/index.jsp</result>
    </action>
    <!-- 調用Action3的add方法 -->
    <action name="thirdadd" class="com.tas.strutslearn.Action3" method="add">
   	<result>/index.jsp</result>
    </action>
           

在struts2中,還有一種方法可以實作,那就是“動态方法調用”,解決了一個Action有多個請求需要配置太多的問題。使用如下:

(1)在struts中配置常量

<constant name="struts.enable.DynamicMethodInvocation" value="true" /> 
           

這個常量在struts2-core-2.3.4.jar/org.apache.struts2/default.properties中可以找到,發現其預設為true,是以這個常量一般不用配置(為false則關閉了動态方法調用)

Struts2 Action學習

(2)通路時隻需要在通路路徑後+“!方法名”即可,如下:

如我這裡通路http://localhost:8080/002_struts2.3.4_ActionUse/third!add就可以看到方法add被調用。

注意:我們知道,早package節點配置namespace屬性的時候,如果配置成“/”或“”,則在通路的路徑中action前加上什麼都可以通路到如http://localhost:8080/002_struts2.3.4_ActionUse/sdfsdf/dsdf//third。可是如果在這些東西中有!的話,那麼struts2會認為這是動态方法調用,就會報錯。是以官網上邊還是不推薦使用動态方法調用這種辦法。好在2.3.4版本及以後版本修複了本bug,是以,如果你使用的是2.3.4版本以前的版本,請盡量不要使用動态方法調用。

四、Action使用通配符的通路方式

通過第三部分我們發現,方法太多的時候,使用單個method屬性配置麻煩,使用動态方法調用的方式又可能不安全,struts2提供了第三種方法--通配符比對通路。通配方式不用多說,就是按照順序出現的*和後面的按順序的數字相比對。

(1)struts.xml如下

<action name="third_*" class="com.tas.strutslearn.Action3" method="{1}">
    		<result>/index.jsp</result>
    	</action>
           

通路時輸入http://localhost:8080/002_struts2.3.4_ActionUse/third_delete。則通路了delete方法。

(2)struts.xml如下

<action name="*_*" class="com.tas.strutslearn.{1}" method="{2}">
    		<result>/index.jsp</result>
    	</action> 
           

通路時輸入http://localhost:8080/002_struts2.3.4_ActionUse/Action3_add則通路了add方法。

其他的比對方式自己想想就可以寫出來。

五、預設的Action

如果在浏覽器上亂輸入位址,如http://localhost:8080/002_struts2.3.4_ActionUse/sdfsfdsd/dfsdf,struts肯定會找不到“Action dfsdf的,這時,如果配置了預設的action,則不會報出錯誤,頁面會跳轉到預設的Action上邊去。預設的action節點屬性為<default-action-ref> 

struts.xml

<default-action-ref name="error"></default-action-ref>
    	 <action name="error">
    		<result>/error.jsp</result>
    	</action>
           

這樣,當找不到action的時候就會跳轉到error.jsp中去。 需要注意的是<default-action-ref> 節點必須放在error的前面(直接就作為namespace下的第一個節點吧),否則會報錯。

六、Action的參數傳遞

這部分是struts2的重點。

(1)第一種方式是通過屬性的驅動。

action寫法如下:

package com.tas.strutslearn;

import java.util.Date;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport{

	private String username;
	
	private String password;
	
	private int age;
	
	private Date birthday;
	
	public void setUsername(String username) {
		System.out.println("UserAction setUsername called!!");
		this.username = username;
	}

	public void setPassword(String password) {
		System.out.println("UserAction setPassword called!!");
		this.password = password;
	}

	public void setAge(int age) {
		System.out.println("UserAction setAge called!!");
		this.age = age;
	}

	public void setBirthday(Date birthday) {
		System.out.println("UserAction setBirthday called!!");
		this.birthday = birthday;
	}

	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		return super.execute();
	}
	
	public String getUser(){
		System.out.println("username:"+username);
		System.out.println("password:"+password);
		System.out.println("age:"+age);
		System.out.println("birthday:"+birthday);
		return SUCCESS;
	}
}
           

表單的寫法如下:

<form action="/002_struts2.3.4_ActionUse/user_getUser" method="post">
    	使用者名:<input type="text" name="username"><br>
    	密 碼:<input type="password" name="password"><br>
    	年 齡:<input type="text" name="age"><br>
    	生 日:<input type="text" name="birthday"><br> 
    	<input type="submit" value="送出">
    </form>
           

表單的元素的name屬性一定要和Action中的屬性名稱一緻。運作過程如下

Struts2 Action學習

可以看到其中的屬性都是通過屬性對應的set方法設定上去的,是以在Action中必須要寫上屬性的set方法。

(2)模型驅動

第一種通過屬性驅動的方式,我們可以看到這種方式不利于軟體項目的分層,面向對象的設計應該是盡量地将屬性封裝起來。

這種方式需要實作接口ModelDriven<User>,UserAction1.java(User類的建立省略):

package com.tas.strutslearn;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.tas.strutslean.entity.User;

public class UserAction1 extends ActionSupport implements ModelDriven<User>{

	private User user;
	
	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		return super.execute();
	}

	public String getUserInf(){
		System.out.println("username:"+user.getUsername());
		System.out.println("password:"+user.getPassword());
		System.out.println("age:"+user.getAge());
		System.out.println("birthday:"+user.getBirthday());
		return SUCCESS;
	}
	@Override
	public User getModel() {
		if(user==null){
			user = new User();
		}
		return user;
	}
}
           

user.jsp:

<form action="/002_struts2.3.4_ActionUse/user_getUserInf" method="post">
    	使用者名:<input type="text" name="username"><br>
    	密 碼:<input type="password" name="password"><br>
    	年 齡:<input type="text" name="age"><br>
    	生 日:<input type="text" name="birthday"><br> 
    	<input type="submit" value="送出">
    </form>
           

由此可以發現,User對象的建立已交由getModel方法執行。

(3)現在問題來了,屬性驅動麻煩,這種ModelDriver由隻能實作一個對象的資料傳遞,所有都還是有缺陷,是以需要第三種方法:

UserBookAction.java:

package com.tas.strutslearn;

import com.opensymphony.xwork2.ActionSupport;
import com.tas.strutslean.entity.Book;
import com.tas.strutslean.entity.User;

public class UserBookAction extends ActionSupport{
	
	private User user;
	
	private Book book;

	public User getUser() {
		System.out.println("UserBookAction getUser called!!");
		return user;
	}

	public void setUser(User user) {
		System.out.println("UserBookAction setUser called!!");
		this.user = user;
	}

	public Book getBook() {
		System.out.println("UserBookAction getBook called!!");
		return book;
	}

	public void setBook(Book book) {
		System.out.println("UserBookAction setBook called!!");
		this.book = book;
	}
	
	public String getUserBookInf(){
		System.out.println("username:"+user.getUsername());
		System.out.println("password:"+user.getPassword());
		System.out.println("age:"+user.getAge());
		System.out.println("birthday:"+user.getBirthday());
		System.out.println("author:"+book.getAuthor());
		System.out.println("bookname:"+book.getBookname());
		return SUCCESS;
	}
	
}
           

表單:

<form action="/002_struts2.3.4_ActionUse/userbook" method="post">
    	使用者名:<input type="text" name="user.username"><br>
    	密 碼:<input type="password" name="user.password"><br>
    	年 齡:<input type="text" name="user.age"><br>
    	生 日:<input type="text" name="user.birthday"><br> 
    	作 者:<input type="text" name="book.author"><br>
    	書 名:<input type="text" name="book.bookname"><br>
    	<input type="submit" value="送出">
    </form>
           

運作程式如下:

Struts2 Action學習

通過結果我們可以發現struts給傳遞對象并封裝的過程:是否存在對象--》不存在new一個--》指派一個屬性--》擷取對象--》指派第二個屬性--》擷取對象。。。。

補充:(1)我們并沒有設定程式的編碼為中文,可是我們表單送出上來的資料沒有亂碼,這個是怎麼做到的呢?這個也是struts已經設定好了的,在default.properties(目錄上面有圖)中可以看到有常量struts.i18n.encoding=UTF-8。

           (2)我們傳遞過來的參數隻是String,可是到了背景卻變成了int,Date等,這個也是由struts處理好了的。再也不用像Servlet裡的那樣,要request.getParameter()擷取屬性,然後再轉換類型。

寫完了,我現在好開心。

繼續閱讀