Struts2 简单的增删改查
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 简单的增删改查的更多相关文章
- salesforce 零基础学习(五十一)使用 Salesforce.com SOAP API 实现用户登录以及简单的增删改查(JAVA访问salesforce)
此篇请参看:https://resources.docs.salesforce.com/202/latest/en-us/sfdc/pdf/salesforce_developer_environme ...
- MyBatis学习--简单的增删改查
jdbc程序 在学习MyBatis的时候先简单了解下JDBC编程的方式,我们以一个简单的查询为例,使用JDBC编程,如下: Public static void main(String[] args) ...
- 通过JDBC进行简单的增删改查
通过JDBC进行简单的增删改查(以MySQL为例) 目录 前言:什么是JDBC 一.准备工作(一):MySQL安装配置和基础学习 二.准备工作(二):下载数据库对应的jar包并导入 三.JDBC基本操 ...
- MyBatis简单的增删改查以及简单的分页查询实现
MyBatis简单的增删改查以及简单的分页查询实现 <? xml version="1.0" encoding="UTF-8"? > <!DO ...
- 初试KONCKOUT+WEBAPI简单实现增删改查
初试KONCKOUT+WEBAPI简单实现增删改查 前言 konckout.js本人也是刚刚接触,也是初学,本文的目的是使用ko和asp.net mvc4 webapi来实现一个简单增删改查操作.Kn ...
- MVC3.0+knockout.js+Ajax 实现简单的增删改查
MVC3.0+knockout.js+Ajax 实现简单的增删改查 自从到北京入职以来就再也没有接触MVC,很多都已经淡忘了,最近一直在看knockout.js 和webAPI,本来打算采用MVC+k ...
- SpringMVC之简单的增删改查示例(SSM整合)
本篇文章主要介绍了SpringMVC之简单的增删改查示例(SSM整合),这个例子是基于SpringMVC+Spring+Mybatis实现的.有兴趣的可以了解一下. 虽然已经在做关于SpringMVC ...
- python3.6 使用 pymysql 连接 Mysql 数据库及 简单的增删改查操作
1.通过 pip 安装 pymysql 进入 cmd 输入 pip install pymysql 回车等待安装完成: 安装完成后出现如图相关信息,表示安装成功. 2.测试连接 import ...
- 通过flask实现web页面简单的增删改查bootstrap美化版
通过flask实现web页面简单的增删改查bootstrap美化版 项目目录结构 [root@node1 python]# tree -L 2 . ├── animate.css ├── fileut ...
随机推荐
- firewall&iptables
一.firewall 查看firewall状态 firewall-cmd --state 如果firewall为关闭状态,先启动firewall systemctl start firewalld 添 ...
- web项目问题总结
1.项目编码问题:建立项目之初,应统一设置项目组所有电脑的eclipse 默认项目编码,还有各个文件的编码格式 中文乱码的问题,需要三个地方同时设置utf-8编码,第一是数据库里表的编码,第二是jsp ...
- <三剑客> 老三:grep命令用法
grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正 ...
- Key Set
http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1011&cid=594 Key Set Time Limit: 2000 ...
- HDU 3183 A Magic Lamp(RMQ问题, ST算法)
原题目 A Magic Lamp Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- error C2872: ‘ofstream’ : ambiguous symbol
转自VC错误:http://www.vcerror.com/?p=1123 问题描述: 编译时出现: error C2872: 'ofstream' : ambiguous symbol error ...
- Windows-菜单太长点不到
显示设置里显示器方向调整成纵向
- centos查看磁盘空间大小
查看磁盘空间大小 df -h 查看当前文件夹所有文件大小 du -sh 查看指定文件夹大小 du -h /data 查看指定文件夹下所有文件的大小 du -h /data/ 查看指定文件大小 du - ...
- Tecplot 360 安装后弹出“Is your Tecplot 360 EX liense valid?”解决方法
在hosts文件中添加127.0.0.1 download.tecplot.com这句指令时,应注意1与download之间有空格!
- iview+vue 表格任一项实现鼠标划上显示内容
在新版本的iview中,表格新增了tooltip功能: 但做项目时并不是新的iview版本,又不想升级,如何才能实现当内容过多鼠标划上显示内容?下边是我做项目时的改动: { // fixed: 'le ...