1、Struts 2.0 中的 ModelDriven 拦截器负责把 Action 类以外的一个对象压入到值栈栈顶
2、prepare 拦截器负责准备为 getModel() 方法准备 model
3、ModelDriven可以单独使用,但是Prepareable需要配套ModelDriven
4、使用ModelDriven接口之后需要根据指定的实体类写getModel方法,而且要return这个实体类对象
5、如果用了Prepareable接口之后,要写prepare()方法,按照需要可以对原有方法创建prepareXXX函数,这样的话调用方法的时候struts2就会自动去调用对用prepareXXX函数对应的方法了
6、配置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>
<constant name="struts.action.extension" value="action,do,"></constant>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<package name="default" namespace="/" extends="struts-default">
<action name="Test-*" class="com.demo.sshtest.InfoAction" method="{1}">
<result name="{1}">/Test-{1}.jsp</result>
<result name="success" type="redirectAction">Test-show</result>
</action>
<action name="Test-show" class="com.demo.sshtest.InfoAction" method="show">
<result name="show">/Test-show.jsp</result>
</action>
</package>
</struts>
配置没什么特别的,只是用了通配符,方便添加和删除、修改这三个操作的跳转,当这三个方法操作成功后会返回”success”,这个时候就调用查询操作并跳转回表单显示页面显示结果
7、调用进入显示数据页的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>index</title>
</head>
<body>
<a href="Test-show">进入数据列表/Enter data list view</a>
</body>
</html>
8、显示数据页面 Test-show.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>
<a href="Test-add.jsp">添加数据/Add data</a>
<br>
<hr>
<br>
<table cellpadding="10" cellspacing="0" border="1">
<thead>
<tr>
<td>Id</td>
<td>Name</td>
<td>Password</td>
<td>Descrition</td>
<td>Edit</td>
<td>Delete</td>
</tr>
</thead>
<tbody>
<s:iterator value="#request.map">
<tr>
<td>${id }</td>
<td>${name }</td>
<td>${pswd }</td>
<td>${desp }</td>
<td><a href="Test-edit?id=${id }">修改/Update</a></td>
<td><a href="Test-delete?id=${id }">删除/Delete</a></td>
</tr>
</s:iterator>
</tbody>
</table>
</body>
</html>
这些会显示数据的页面一定要记得加<%@ taglib prefix="s" uri="/struts-tags" %>
9、添加数据页面 Test-add.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>
<a href="Test-show">返回/Back</a>
<br>
<s:form action="Test-add">
<s:textfield name="name" label="NAME"></s:textfield>
<s:textfield name="pswd" label="PASSWARD"></s:textfield>
<s:textfield name="desp" label="DESCRITION"></s:textfield>
<s:submit></s:submit>
</s:form>
</body>
</html>
10、修改数据的页面 Test-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>
<a href="Test-show">返回/Back</a>
<br>
<s:debug></s:debug>
<br>
<s:form action="Test-update">
<s:hidden name="id"></s:hidden>
<s:textfield name="name" label="Name"></s:textfield>
<s:textfield name="pswd" label="Password"></s:textfield>
<s:textfield name="desp" label="Descrition"></s:textfield>
<s:submit></s:submit>
</s:form>
</body>
</html>
这里是通过调用Test-edit这个action进来Test-edit.jsp的,然后更新数据是调用Test-update进行更新操作
11、数据属性类 InfoBean.java
package com.demo.sshtest;
public class InfoBean {
//用于储存属性参数
private int id = 0;
private String name = "";
private String pswd = "";
private String desp = "";
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPswd() {
return pswd;
}
public void setPswd(String pswd) {
this.pswd = pswd;
}
public String getDesp() {
return desp;
}
public void setDesp(String desp) {
this.desp = desp;
}
public InfoBean(){}
public InfoBean(String name, String pswd, String desp) {
super();
this.name = name;
this.pswd = pswd;
this.desp = desp;
System.out.println("name:"+this.name);
System.out.println("pswd:"+this.pswd);
System.out.println("desp:"+this.desp);
}
public InfoBean(int id, String name, String pswd, String desp) {
super();
this.id = id;
this.name = name;
this.pswd = pswd;
this.desp = desp;
}
}
要写空构造函数和构造函数,后面需要用来更新给ModelDriven做实体类赋值用
12、对应增删查改的工具类 Dao.java
package com.demo.sshtest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class Dao {
//-----------------------------------------------------------------------------------------//
//用于储存从数据库获取到得数据
public static Map<Integer, InfoBean> map = new TreeMap<Integer, InfoBean>();
//模拟连接数据库后第一次拿到的数据
//连接数据库之后可以把获取的值在showData()里面给map赋值
static{
map.put(1, new InfoBean(1,"NameA","123456","this is NameA"));
map.put(2, new InfoBean(2,"NameB","123456","this is NameB"));
map.put(3, new InfoBean(3,"NameC","123456","this is NameC"));
map.put(4, new InfoBean(4,"NameD","123456","this is NameD"));
}
//-----------------------------------------------------------------------------------------//
//(增)
public void addData(InfoBean info){
int newId = 1;
//map中有数据,添加一条id为当前最大id+1的数据
if(map.size()!=0){
newId = Integer.valueOf(getMaxKey(map)) + 1;
}
info.setId(newId);
map.put(info.getId(), info);
}
//(删)
public void deleteData(int id){
map.remove(id);
}
//(查)
public List<InfoBean> showData(){
return new ArrayList<>(map.values());
}
//(改)
public void editData(InfoBean info){
map.put(info.getId(), info);
}
//获取指定id的数据
public InfoBean getSingleData(Integer infoId){
return map.get(infoId);
}
//-----------------------------------------------------------------------------------------//
//获取map中key的最大值,后面添加数据id为getMaxKey+1
public static String getMaxKey(Map<Integer, InfoBean> map) {
if (map == null) return null;
Set<Integer> set = map.keySet();
Object[] obj = set.toArray();
Arrays.sort(obj);
return String.valueOf(obj[obj.length-1]);
}
//-----------------------------------------------------------------------------------------//
}
都写注释了 ,这里看注释就可以
13、action类 InfoAction.java
package com.demo.sshtest;
import java.util.Map;
import org.apache.struts2.interceptor.RequestAware;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;
public class InfoAction implements RequestAware,ModelDriven<InfoBean>, Preparable {
// 实例化信息处理的工具类的实体类
private Dao dao = new Dao();
// 实例化信息属性类的实体类
private InfoBean infoBean = new InfoBean();
// 获得当前请求中包含request对象中全部attributes的一个map对象
private Map<String, Object> request;
@Override
public void setRequest(Map<String, Object> arg0) {
this.request = arg0;
}
// (增)
public String add() {
System.out.println("add");
dao.addData(infoBean);
return "success";
}
public void prepareAdd(){
infoBean = new InfoBean();
System.out.println("prepareAdd");
}
// (删)
public String delete() {
System.out.println("delete");
dao.deleteData(infoBean.getId());
return "success";
}
public void prepareDelete(){
System.out.println("prepareDelete");
//因为prepare是在set方法之前执行,所以这里getId会为空
//dao.deleteData(infoBean.getId());
}
// (查)
public String show() {
System.out.println("show");
//request.put("map", (dao.showData()));
return "show";
}
public void prepareShow(){
System.out.println("prepareShow");
request.put("map", (dao.showData()));
}
// (改)
public String update() {
System.out.println("update");
dao.editData(infoBean);
return "success";
}
public void prepareUpdate(){
System.out.println("prepareUpdate");
infoBean = new InfoBean();
}
//跳转到Test-edit页面,获取并且显示对应id的数据
public String edit(){
System.out.println("edit");
//(1)、传入id
//(2)、根据id获取InfoBean对象
InfoBean info = dao.getSingleData(infoBean.getId());
//(3)、封装栈顶对象,不然页面获取的属性值都是null
infoBean.setName(info.getName());
infoBean.setPswd(info.getPswd());
infoBean.setDesp(info.getDesp());
return "edit";
}
public void prepareEdit(){
System.out.println("prepareEdit");
}
//-------------------------------------------------------------------------//
//Struts 2.0 中的 modelDriven 拦截器负责把 Action 类以外的一个对象压入到值栈栈顶
//而 prepare 拦截器负责准备为 getModel() 方法准备 model
//Prepareable接口的作用有:
//1、为二次绑定数据
//2、作为公共的数据准备函数
//注意事项:
//1、prepare()方法是在set()、excute()方法之前运行的
//2、需要跟ModelDriven一起用(但是ModelDriven可以单独用)
//3、常用于一个对象多属性,但是页面只显示其中一部分属性的时候
//4、如果一个action里面有多个方法,为了避免冲突,可以多写一个prepareXXX()函数(XXX代表原来需要执行的函数名)
//5、其实不用根据前台传入值来调用set方法获取值再来做对应操作的方法(如:add()、show()、update()),都可以把部分操作的代码写到prepareXXX()中
@Override
public void prepare() throws Exception {
System.out.println("prepare");
}
//这里使用ModelDriven<Object>,是为了代码方便重用
//1、ModelDriven只有一个方法,就是getModel(),该方法返回的是你的ModelDrivern泛型中设定的实体类
//2、ModelDriven的作用就是统一设定一个实体类来接收页面传过来的值,不管哪个表单,只要进入实现ModelDriven接口的这个Action类,就会调用设定的实体类接收对应属性的值
//3、根据第二点可以知道,写了getModel()之后,Action就不用定义参数和不写对应的getset方法了,因为这个时候Action会自动调用设定实体类中的set方法
@Override
public InfoBean getModel() {
System.out.println("-------getModel-------start");
System.out.println("id:"+infoBean.getId());
System.out.println("name:"+infoBean.getName());
System.out.println("pswd:"+infoBean.getPswd());
System.out.println("desp:"+infoBean.getDesp());
System.out.println("-------getModel-------end");
return infoBean;
}
}
这里也写了注释,看注释就好了,特别注意的是
- 调用edit方法的时候要封装栈顶对象
- 引用了ModelDriven和Prepareable接口后一定要写getModel()和prepare()方法
- prepareXXX()方法可写可不写,里面的内容怎么写,也是随意
- 需要调用的方法或属性少的时候,prepareable的效果看不出来,所以按照情况再决定用不用这个接口
14、项目目录
15、运行截图
(1)首页
(2)显示数据页
(3)添加新数据
(4)修改数据
数据显示页面中的数据后面有个Edit按钮,点击之后就会跳转到修改数据的页面,这个时候会把对应记录的数据回显到页面上,id用隐藏域,不显示出来
16、demo地址:
https://download.csdn.net/download/qq_22778717/10275941
17、直接按着一步一步写就能成功,不下载demo应该也可以