1. 程式人生 > >Struts2學習總結(十一):Struts2的CRUD

Struts2學習總結(十一):Struts2的CRUD

CRUD是Create(建立)、Read(讀取)、Update(更新)和Delete(刪除)的縮寫。

如果你熟練的掌握了CRUD,就可以應用某個框架來建立普通的應用程式

示例:建立,讀取全部資訊,刪除,更新

(1)建立一個Employee物件:並實現物件屬性的set和get方法。建立這個物件的有參和無參的構造方法

package com

public class Employee {
    private Integer id;
    private String firstName;
    private String lastName;
    private String email;

    public void setId(Integer id) {
        this.id = id;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Integer getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getEmail() {
        return email;
    }

    public String getLastName() {
        return lastName;
    }
    public Employee(Integer id,String firstName,String lastName,String email)
    {
        super();
        this.email=email;
        this.firstName=firstName;
        this.lastName=lastName;
        this.id=id;
    }
    public Employee()
    {

    }
    public String toString() {
        return "Employee [employeeId=" + id + ", firstName="
                + firstName + ", lastName=" + lastName + ", email=" + email
                + "]";
    }
}

(2)建立一個 關資料的基本操作的類:實現獲取資訊,刪除,儲存等方法。並沒有資料庫連線,所以只是用容器儲存了資料。

將資訊存放在一個Map容器裡。因為request是一個Map型別的,將資訊就可以存放在request中,以方便讀取。

package com;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class Dao {
    /*
    * 對資料進行操作
    *
    * */
    private static Map<Integer ,Employee> emps=new HashMap<Integer,Employee>();
    static {
        emps.put(1001, new Employee(1001, "AA", "aa", "
[email protected]
")); emps.put(1002, new Employee(1002, "BB", "bb", "[email protected]")); emps.put(1003, new Employee(1003, "CC", "cc", "[email protected]")); emps.put(1004, new Employee(1004, "DD", "dd", "[email protected]")); emps.put(1005, new Employee(1005, "EE", "ee", "
[email protected]
")); } //獲取全部資訊 public List<Employee> getEmps() { return new ArrayList<>(emps.values()); } //刪除 public void delete(int id) { emps.remove(id); } //儲存 public void save(Employee employee) { long time=System.currentTimeMillis(); employee.setId((int)time); emps.put(employee.getId(),employee); } //獲取 public Employee get(Integer id) { return emps.get(id); } //更新 public void update(Employee emp) { emps.put(emp.getId(),emp); } }

(3)建立Action並實現RequestAware介面 :呼叫dao層的方法進行操作。

思路一:(較為麻煩),在當前的Action類中定義Employee物件的屬性,用於接收引數

package com;

import org.apache.struts2.interceptor.RequestAware;

import java.util.Map;
public class EmpAction implements RequestAware{
    private Dao dao=new Dao();
    private Map<String,Object> request;
    //獲得所有資訊
    public String list()
    {
        request.put("emps",dao.getEmps());
        return "list";
    }
    //對request進行初始化
    @Override
    public void setRequest(Map<String, Object> arg0) {
        this.request = arg0;
    }

    //定義employee的id屬性,以便接受引數
    private Integer id;
    private String firstName;
    private String lastName;
    private String email;

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setId(Integer id) {
        this.id = id;
    }

 

//    private Employee employee;


    //會把請求引數給棧頂的屬性。刪除後要顯示刪除後的資訊,所以可以跳轉到action
    public String delete()
    {
        //返回型別為:redirectAction
        //也可以是chain, 實際上可以不需要用chain
        // 因為:不需要在下一個Action時保留當前Action狀態
        //若使擁chain,則達到目標頁面後,位址列顯示的依然是刪除的頁面,重新整理時會重複提交
        dao.delete(id);

        return "success";
    }

    public String save()
    {
        //1.獲取請求引數:通過定義對應屬性的方式
        //2.呼叫Dao的save方法
       Employee employee=new Employee(null,firstName,lastName,email);
        dao.save(employee);
        //3.通過redirectAction的方式相應給emp-list
        return "success";
    }
}

思路二:

上面的程式碼因為Action再次編寫了Employee屬性的set方法,使程式碼較為冗長。為了程式的簡潔性,Struts2框架會將Action和Model分隔開。

 沒使用struts-default.xml預設的攔截器棧,而是使用了paramsPrepareParams攔截器棧(params->prepare->modelDriven->params)。

  • 採用了ModelDriven: Action 類實現了 ModelDriven 介面,該攔截器將把 ModelDriven 介面的 getModel() 方法返回的物件置於棧頂。
  • 採用params:把請求引數的值賦給棧頂物件對應的屬性.
  • 實現了Prepare介面:執行PrepareInterceptor攔截器。在執行execute()方法前加入一些其他業務邏輯。為ModelDriven的getModel()方法準備model

處理流程:     

  a:  執行ParametersInteceptors的Intecept()方法(params)。把請求引數的值賦給棧頂物件對應的屬性. 若棧頂物件沒有對應的屬性, 則查詢
值棧中下一個物件對應的屬性...

注意:getModel方法不能提供以下的實現,的確會返回一個Employee物件到值棧的棧頂,但是返回的Emplyoee的成員變數為空

public Employee getModel() {
	return new Employee();
}    

b:實現Prepareable介面,在為Action的方法編寫prepareXxx()方法。為ModelDriven準備model

c:先回執行ModelDrivenInterceptor的intecept方法,對這個方法進行解釋:

 public String intercept(ActionInvocation invocation) throws Exception {
    	//獲取 Action 物件: EmployeeAction 物件, 此時該 Action 已經實現了 ModelDriven 介面
    	//public class EmployeeAction implements RequestAware, ModelDriven<Employee>
        Object action = invocation.getAction();

		//判斷 action 是否是 ModelDriven 的例項
        if (action instanceof ModelDriven) {
        	//強制轉換為 ModelDriven 型別
            ModelDriven modelDriven = (ModelDriven) action;
            //獲取值棧
            ValueStack stack = invocation.getStack();
            //呼叫 ModelDriven 介面的 getModel() 方法
            //即呼叫 EmployeeAction 的 getModel() 方法
            /*
            public Employee getModel() {
				employee = new Employee();
				return employee;
			}
            */
            Object model = modelDriven.getModel();
            if (model !=  null) {
            	//把 getModel() 方法的返回值壓入到值棧的棧頂. 實際壓入的是 EmployeeAction 的 employee 成員變數
            	stack.push(model);
            }
            if (refreshModelBeforeResult) {
                invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
            }
        }
        return invocation.invoke();
    }
   

程式碼示例:

import java.util.Map;

import org.apache.struts2.interceptor.RequestAware;

import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;
import com.qiaobc.crud.dao.Dao;
import com.qiaobc.crud.domin.Employee;

public class EmployeeAction implements RequestAware, ModelDriven<Employee>, Preparable {

    private Dao dao = new Dao();

    /**
     * 1. 查詢所有員工資訊
     * @return
     */
    public String list() {
        // 獲取所有員工資訊,並儲存在request請求域中
        request.put("emps", dao.getAll());
        return "list";
    }

    // 獲取request請求域所對應的Map物件
    private Map<String, Object> request;

    @Override
    public void setRequest(Map<String, Object> arg0) {
        this.request = arg0;
    }

    /**
     * 2. 刪除一條員工資訊
     * 方法:在當前Action類中定義employeeId屬性,用於接收請求引數
     * 注意:返回結果的型別應為redirectAction,即重定向到action:struts.xml檔案配置
     *  若使用chain,則到達目標頁面後,位址列顯示的仍為emp-delete.do,會重複提交,不需要在下一個Action時保留上一個Action的狀態
     * @return
     */

    public String delete() {
        // 獲取請求引數employeeId
        dao.delete(employeeId);
        return "success";
    }

  

    // 定義成員變數employee,利用ModelDriven的getModel()方法為其建立物件並壓入值棧

    private Employee employee;
  @Override
    public Employee getModel() {
//      if(employeeId == null) {    
//          // 注意:不能直接使用return new Employee();
//          employee = new Employee();
//      } else {
//          employee = dao.get(employeeId);
//      }
        return employee;
    }
 public String save() {  
// 獲取請求引數並封裝為Employee物件,新增到資料庫中 
dao.add(employee); 
// 返回結果型別仍為redirectAction 
    return "success"; 
   } 
     public void prepareSave() {
         employee = new Employee(); 
     } 



private Integer employeeId; 
public void setEmployeeId(Integer employeeId) 
   { this.employeeId = employeeId; } 
     public String edit() {
     /*************************思路1:*************************/
      // 此時棧頂物件即為employee,其除employeeId屬性外均為null
      // 1. 根據請求引數employeeId獲取對應的Employee物件
     // Employee emp = dao.get(employee.getEmployeeId());// 
     // 2. 封裝棧頂物件employee的屬性資訊
    // employee.setFirstName(emp.getFirstName());
    // employee.setLastName(emp.getLastName());
   // employee.setEmail(emp.getEmail()); 
/*************************思路2:失敗**************************/ 
   // // 經過重新賦值的employee物件不再是棧頂物件
   // employee = dao.get(employee.getEmployeeId()); 
/*************************思路3:**************************/ 
// // 將獲取的emp物件直接壓入值棧,但有浪費之嫌(此時值棧中有兩個Employee物件)
// ActionContext.getContext().getValueStack().push(dao.get(employee.getEmployeeId())); 
/*************************解決方案******************************/ 
// 方案:在genModel()方法中根據請求引數employeeId獲取Employee物件並返回 
// 判斷是Add還是Edit(判定標準:是否有employeeId引數),Add新建而Edit從資料庫中獲取 
// 注意:若通過employeeId來判斷,則需要在modelDriven攔截器執行前先執行一個params攔截器!
 // 此時可以通過使用paramsPrepareParams攔截器棧來實現,在struts.xml檔案中配置即可。 
        return "edit";
} 
public void prepareEdit() 
{ 
      employee = dao.get(employeeId); 
} 
public String update() 
{ 
      dao.update(employee); 
      return "success"; 
 } 
public void prepareUpdate() 
{ 
    employee = new Employee(); 
}
 // 配置PrepareInterceptor的alwaysInvokePrepare屬性為false,使當前方法不執行
 @Override 
public void prepare() throws Exception { 
     System.out.println("prepare..."); 
}
}


struts.xml:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <package name="default" namespace="/" extends="struts-default">

        <!-- 配置使用 paramsPrepareParamsStack 作為預設的攔截器棧 -->
        <!-- 修改 PrepareInterceptor 攔截器的 alwaysInvokePrepare 屬性值為 false -->
        <interceptors>
            <interceptor-stack name="atguigustack">
                <interceptor-ref name="paramsPrepareParamsStack">
                    <param name="prepare.alwaysInvokePrepare">false</param>
                </interceptor-ref>
            </interceptor-stack>
        </interceptors>

        <default-interceptor-ref name="atguigustack"/>

        <action name="emp-*"
                class="com.EmpAction"
                method="{1}">
            <result name="{1}">emp-{1}.jsp</result>
            <result name="success" type="redirectAction">emp-*</result>
        </action>

        <action name="emp-list"
                class="com.EmpAction"
                method="list">
            <result name="list">/emp-list.jsp</result>
        </action>
    </package>


</struts>
jsp:
emp-edit.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	
	<s:debug></s:debug>
	
	<br>
	<br>
	
	<s:form action="emp-update">
		
		<s:hidden name="employeeId"></s:hidden>
		
		<s:textfield name="firstName" label="FirstName"></s:textfield>
		<s:textfield name="lastName" label="LastName"></s:textfield>
		<s:textfield name="email" label="Email"></s:textfield>
		
		<s:submit></s:submit>		
	</s:form>
	
</body>
</html>
emp-list.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>    
    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

	<s:form action="emp-save">
		
		<s:textfield name="firstName" label="FirstName"></s:textfield>
		<s:textfield name="lastName" label="LastName"></s:textfield>
		<s:textfield name="email" label="Email"></s:textfield>
		
		<s:submit></s:submit>		
	</s:form>

	<br>
	<hr>
	<br>
	
	<table cellpadding="10" cellspacing="0" border="1">
		<thead>
			<tr>
				<td>ID</td>
				<td>FirstName</td>
				<td>LastName</td>
				<td>Email</td>
				<td>Edit</td>
				<td>Delete</td>
			</tr>
		</thead>
		
		<tbody>
			<s:iterator value="#request.emps">
				<tr>
					<td>${employeeId }</td>
					<td>${firstName }</td>
					<td>${lastName }</td>
					<td>${email }</td>
					<td><a href="emp-edit?employeeId=${employeeId }">Edit</a></td>
					<td><a href="emp-delete?employeeId=${employeeId }">Delete</a></td>
				</tr>
			</s:iterator>
		</tbody>
		
	</table>

</body>
</html>

<%
	System.out.println("now: " + new java.util.Date());
%>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	
	<a href="emp-list">List All Employees</a>
	
</body>
</html>




總結:
    通過這個增添改查瞭解到了Struts2的CRUD。實現CRUD時,注意:
保證Action和Model分割開,使用ModelDriven
 為向ModelDriven的getModel()方法準備Model,實現了params攔截器和prepare攔截器。前一個向棧頂物件賦值,後一個獲取物件
 在struts.xml不再使用預設攔截器棧,改為paramsPrepareParams攔截器棧(提供了params,prepare,modelDriven)