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)