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", "aa@atguigu.com"));
emps.put(1002, new Employee(1002, "BB", "bb", "bb@atguigu.com"));
emps.put(1003, new Employee(1003, "CC", "cc", "cc@atguigu.com"));
emps.put(1004, new Employee(1004, "DD", "dd", "dd@atguigu.com"));
emps.put(1005, new Employee(1005, "EE", "ee", "ee@atguigu.com"));
}
//获取全部信息
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)