1:主页面

<a href="emp-list">emp-list</a> <br>

然后到struts.xml文件中找到对应的emp-list

<action name="emp-list" class="com.emp.app.EmployeeAction" method="List">
<result name="list">/pages/emp-list.jsp</result>
</action>

然后在Action处理业务层处理。class="com.emp.app.EmployeeAction"

package com.emp.app;

import java.util.Map;

import org.apache.struts2.interceptor.RequestAware;

public class EmployeeAction implements RequestAware{

    private Dao dao = new Dao();
private Employee employee;
private Map<String, Object> request;
  public void setRequest(Map<String, Object> arg0) { this.request = arg0; }
public String List(){
System.out.println(dao.getEmployees());
request.put("emps", dao.getEmployees());
System.out.println(request.size());
return "list";
}   private Integer employeeId;
    
    public void setEmployeeId(Integer employeeId) {
        this.employeeId = employeeId;
    }
    public String delete(){
        dao.deleteEmployees(employeeId);
        return "success";
    } }

到DAO层处理数据:

package com.emp.app;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack; public class Dao {
ValueStack vs=ActionContext.getContext().getValueStack();
private static Map<Integer, Employee> emps = new LinkedHashMap<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> getEmployees(){
return new ArrayList<Employee>(emps.values());
}
public Employee deleteEmployees(Integer empId){
return emps.remove(empId);
} }

处理完后 result到对应的页面展示数据。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<h1>显示全部</h1>
</head> <body>
<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>
<s:debug></s:debug>
</body>
</html>

二:保存

1):struts2的运行流程。

拦截器中有个parameters拦截器。它的用处是:把表单字段映射到ValueStack栈的栈顶对象的各个属性中。如果某个字段在模型里没有匹配的属性。Param拦截器将尝试把字段压入到ValueStack栈中的下一个对象。

把表单的值赋给栈顶对象的属性。此时栈顶对象是Action。

拦截器的顺序是从第一个到最后一个依次进行。

2):ModelDriven拦截器:

作用:将ModelDriven拦截器接口的getModel()方法返回的对象置于栈顶。

1. Action 实现 ModelDriven 接口后的运行流程

1). 先会执行 ModelDrivenInterceptor 的 intercept 方法.

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();
    }
   
2). 执行 ParametersInterceptor 的 intercept 方法: 把请求参数的值赋给栈顶对象对应的属性. 若栈顶对象没有对应的属性, 则查询
值栈中下一个对象对应的属性...

3). 注意: getModel 方法不能提供以下实现. 的确会返回一个 Employee 对象到值栈的栈顶. 但当前 Action
的 employee 成员变量却是 null.

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

代码实现:

package com.emp.app;

import java.util.Map;

import org.apache.struts2.interceptor.RequestAware;

import com.opensymphony.xwork2.ModelDriven;

public class EmployeeAction implements RequestAware,ModelDriven<Employee>{
private Dao dao = new Dao();
private Employee employee;
public Employee getModel() {
employee=new Employee();
return employee;
}
public String save(){
dao.save(employee);
return "success";
} }

DAO层:

public void save(Employee employee){
long time=System.currentTimeMillis();
employee.setEmployeeId((int)time);
emps.put(employee.getEmployeeId(), employee);
}

页面:emp-save.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<h1>添加一个</h1>
</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>
<s:debug></s:debug>
</body>
</html>

四:修改

页面:

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

DAO层:

public Employee get(Integer empId){
System.out.println(empId+"aaa");
return emps.get(empId);
} public void update(Employee emp){
emps.put(emp.getEmployeeId(), emp);
}

先得到ID,然后修改Employee对象

package com.emp.app;

import java.util.Map;

import org.apache.struts2.interceptor.RequestAware;

import com.opensymphony.xwork2.ModelDriven;

public class EmployeeAction implements RequestAware,ModelDriven<Employee>{
private Dao dao = new Dao(); private Employee employee;
public Employee getModel() {
    /*判断是创建还是修改。若是创建。employee=new Employee();
      修改:employee=dao.get(employeeId);
    判断标准就是有没有employeeId这个参数。
    若通过employeeId来判断。需要在modelDriven拦截器先执行一个params拦截器。因为params拦截器是把表单的值赋予栈顶的对象。
  需要在struts.xml中配置默认的 paramsPrepareParamsStack拦截器
<default-interceptor-ref name="paramsPrepareParamsStack"></default-interceptor-ref>
    */
  目的就是从栈顶中得到employee对象。然后修改的时候回显到emp-edit.jsp页面。
if(employeeId==null)
employee=new Employee();
else
employee=dao.get(employeeId);
return employee;
}
private Integer employeeId;
public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
}
public String edit(){ return "edit";
}
public String update(){
dao.update(employee);
return "success";
}
}
5):存在的问题:

getModel 方法

public Employee getModel() {
if(employeeId == null)
employee = new Employee();
else
employee = dao.get(employeeId); return employee;
} I. 在执行删除的时候, employeeId 不为 null, 但 getModel 方法却从数据库加载了一个对象. 不该加载!
II. 指向查询全部信息时, 也 new Employee() 对象. 浪费! . 解决方案: 使用 PrepareInterceptor 和 Preparable 接口. 7). 关于 PrepareInterceptor [分析后得到的结论] 若 Action 实现了 Preparable 接口, 则 Struts 将尝试执行 prepare[ActionMethodName] 方法,
若 prepare[ActionMethodName] 不存在, 则将尝试执行 prepareDo[ActionMethodName] 方法.
若都不存在, 就都不执行. 若 PrepareInterceptor 的 alwaysInvokePrepare 属性为 false,
则 Struts2 将不会调用实现了 Preparable 接口的 Action 的 prepare() 方法 [能解决 5) 的问题的方案] 可以为每一个 ActionMethod 准备 prepare[ActionMethdName] 方法, 而抛弃掉原来的 prepare() 方法
将 PrepareInterceptor 的 alwaysInvokePrepare 属性置为 false, 以避免 Struts2 框架再调用 prepare() 方法. 如何在配置文件中为拦截器栈的属性赋值: 参看 /struts-2.3.15.3/docs/WW/docs/interceptors.html <interceptors>
<interceptor-stack name="parentStack">
<interceptor-ref name="defaultStack">
<param name="params.excludeParams">token</param>
</interceptor-ref>
</interceptor-stack>
</interceptors> <default-interceptor-ref name="parentStack"/> ----------------------------------源代码解析--------------------------------- public String doIntercept(ActionInvocation invocation) throws Exception {
//获取 Action 实例
Object action = invocation.getAction(); //判断 Action 是否实现了 Preparable 接口
if (action instanceof Preparable) {
try {
String[] prefixes;
//根据当前拦截器的 firstCallPrepareDo(默认为 false) 属性确定 prefixes
if (firstCallPrepareDo) {
prefixes = new String[] {ALT_PREPARE_PREFIX, PREPARE_PREFIX};
} else {
prefixes = new String[] {PREPARE_PREFIX, ALT_PREPARE_PREFIX};
}
//若为 false, 则 prefixes: prepare, prepareDo
//调用前缀方法.
PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes);
}
catch (InvocationTargetException e) { Throwable cause = e.getCause();
if (cause instanceof Exception) {
throw (Exception) cause;
} else if(cause instanceof Error) {
throw (Error) cause;
} else {
throw e;
}
} //根据当前拦截器的 alwaysInvokePrepare(默认是 true) 决定是否调用 Action 的 prepare 方法
if (alwaysInvokePrepare) {
((Preparable) action).prepare();
}
} return invocation.invoke();
} PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes) 方法: public static void invokePrefixMethod(ActionInvocation actionInvocation, String[] prefixes) throws InvocationTargetException, IllegalAccessException {
//获取 Action 实例
Object action = actionInvocation.getAction();
//获取要调用的 Action 方法的名字(update)
String methodName = actionInvocation.getProxy().getMethod(); if (methodName == null) {
// if null returns (possible according to the docs), use the default execute
methodName = DEFAULT_INVOCATION_METHODNAME;
} //获取前缀方法
Method method = getPrefixedMethod(prefixes, methodName, action); //若方法不为 null, 则通过反射调用前缀方法
if (method != null) {
method.invoke(action, new Object[0]);
}
} PrefixMethodInvocationUtil.getPrefixedMethod 方法: public static Method getPrefixedMethod(String[] prefixes, String methodName, Object action) {
assert(prefixes != null);
//把方法的首字母变为大写
String capitalizedMethodName = capitalizeMethodName(methodName); //遍历前缀数组
for (String prefixe : prefixes) {
//通过拼接的方式, 得到前缀方法名: 第一次 prepareUpdate, 第二次 prepareDoUpdate
String prefixedMethodName = prefixe + capitalizedMethodName;
try {
//利用反射获从 action 中获取对应的方法, 若有直接返回. 并结束循环.
return action.getClass().getMethod(prefixedMethodName, EMPTY_CLASS_ARRAY);
}
catch (NoSuchMethodException e) {
// hmm -- OK, try next prefix
if (LOG.isDebugEnabled()) {
LOG.debug("cannot find method [#0] in action [#1]", prefixedMethodName, action.toString());
}
}
}
return null;
}

使用:ModelDriven<Employee>, Preparable

package com.atguigu.struts2.app;

import java.util.Map;

import org.apache.struts2.interceptor.RequestAware;

import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable; public class EmployeeAction implements RequestAware, ModelDriven<Employee>, Preparable{ private Dao dao = new Dao(); private Employee employee; public String update(){
dao.update(employee);
return "success";
} public void prepareUpdate(){
employee = new Employee();
} public String edit(){
return "edit";
} public void prepareEdit(){
employee = dao.get(employeeId);
} public String save(){
dao.save(employee);
return "success";
} public void prepareSave(){
employee = new Employee();
} public String delete(){
dao.delete(employeeId);
return "success";
} public String list(){
request.put("emps", dao.getEmployees());
return "list";
} private Map<String, Object> request; @Override
public void setRequest(Map<String, Object> arg0) {
this.request = arg0;
} private Integer employeeId; public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
} @Override
public Employee getModel() {
return employee;
} @Override
public void prepare() throws Exception {
System.out.println("prepare...");
} }

在struts.xml中修改 PrepareInterceptor 拦截器的 alwaysInvokePrepare 属性值为 false

<!-- 配置使用 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"/>

Struts2 简单的增删改查的更多相关文章

  1. salesforce 零基础学习(五十一)使用 Salesforce.com SOAP API 实现用户登录以及简单的增删改查(JAVA访问salesforce)

    此篇请参看:https://resources.docs.salesforce.com/202/latest/en-us/sfdc/pdf/salesforce_developer_environme ...

  2. MyBatis学习--简单的增删改查

    jdbc程序 在学习MyBatis的时候先简单了解下JDBC编程的方式,我们以一个简单的查询为例,使用JDBC编程,如下: Public static void main(String[] args) ...

  3. 通过JDBC进行简单的增删改查

    通过JDBC进行简单的增删改查(以MySQL为例) 目录 前言:什么是JDBC 一.准备工作(一):MySQL安装配置和基础学习 二.准备工作(二):下载数据库对应的jar包并导入 三.JDBC基本操 ...

  4. MyBatis简单的增删改查以及简单的分页查询实现

    MyBatis简单的增删改查以及简单的分页查询实现 <? xml version="1.0" encoding="UTF-8"? > <!DO ...

  5. 初试KONCKOUT+WEBAPI简单实现增删改查

    初试KONCKOUT+WEBAPI简单实现增删改查 前言 konckout.js本人也是刚刚接触,也是初学,本文的目的是使用ko和asp.net mvc4 webapi来实现一个简单增删改查操作.Kn ...

  6. MVC3.0+knockout.js+Ajax 实现简单的增删改查

    MVC3.0+knockout.js+Ajax 实现简单的增删改查 自从到北京入职以来就再也没有接触MVC,很多都已经淡忘了,最近一直在看knockout.js 和webAPI,本来打算采用MVC+k ...

  7. SpringMVC之简单的增删改查示例(SSM整合)

    本篇文章主要介绍了SpringMVC之简单的增删改查示例(SSM整合),这个例子是基于SpringMVC+Spring+Mybatis实现的.有兴趣的可以了解一下. 虽然已经在做关于SpringMVC ...

  8. python3.6 使用 pymysql 连接 Mysql 数据库及 简单的增删改查操作

    1.通过 pip 安装 pymysql 进入 cmd  输入  pip install pymysql   回车等待安装完成: 安装完成后出现如图相关信息,表示安装成功. 2.测试连接 import ...

  9. 通过flask实现web页面简单的增删改查bootstrap美化版

    通过flask实现web页面简单的增删改查bootstrap美化版 项目目录结构 [root@node1 python]# tree -L 2 . ├── animate.css ├── fileut ...

随机推荐

  1. Unity编程标准导引-3.4 Unity中的对象池

    本文为博主原创文章,欢迎转载.请保留博主链接http://blog.csdn.net/andrewfan Unity编程标准导引-3.4 Unity中的对象池 本节通过一个简单的射击子弹的示例来介绍T ...

  2. [HDU2604]Queuing

    题目:Queuing 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2604 分析: 1)将当前格和上一格合并当作一个状态,考虑下一个格子放0(m)还是1( ...

  3. VS2010提示error TRK0002: Failed to execute command

    转自VC错误:http://www.vcerror.com/?p=277 问题描述: windows8自动更新Microsoft .NET Framework 3.5和4.5.1安全更新程序,今天用V ...

  4. spark sql correlated scalar subqueries must be aggregated 错误解决

    最近在客户中使用spark sql 做一些表报处理,但是在做数据关联时,老是遇到 “correlated scalar subqueries must be aggregated” 错误 举一个例子, ...

  5. spring cloud stream集成rabbitmq

    pom添加依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId&g ...

  6. 【python3】装饰器

    参考文章: 理解Python装饰器(Decorator) 关键点: 写装饰器一定要搞定楚函数名后面带小括号和不带小括号的含义.带小括号,表示调用这个函数,而不带小括号,则表示的是该函数引用地址 简单装 ...

  7. 把 MongoDB 当成是纯内存数据库来使用(Redis 风格)

    基本思想 将MongoDB用作内存数据库(in-memory database),也即,根本就不让MongoDB把数据保存到磁盘中的这种用法,引起了越来越多的人的兴趣.这种用法对于以下应用场合来讲,超 ...

  8. 第一次刷Leetcode,为什么耗费很多时间

    Leetcode第2题思考过程分析:耗费的时间与思考过程 1. 审题耗费了很长时间,英文看不懂.两个单链表代表了两个整数,整数逆序,(2 -> 4 -> 3) + (5 -> 6 - ...

  9. 正则sub的使用

    import re # unicode 编码匹配范围[u4e00-u9fa5] pattern = re.compile('(\w+) (\w+)') s = 'hello 123,hello 456 ...

  10. javaIO流(四)--输入与输出支持

    一.打印流 如果现在要想通过程序实现内容的输出,核心的本质一定要依靠OutputStream类来支持但是OutputStream类有一个最大的缺点,这个类的数据输出操作功能有限,所有的数据一定要转为字 ...