1. 扩展列表显示示例 ( 添加分页处理 )
a.在TaskDAO中添加两个方法
package dao; import java.util.List; import entity.Task; public interface TaskDAO{ //查处数据库中的所有数据 public List<Task> findAll() throws Exception; /** * 分页查询 * @param page 查询第几页 * @param pageSize 每一页最多显示几条记录 * @return * @throws Exception */ public List<Task> findAll(int page, int pageSize) throws Exception; /** * 统计一共有多少页 * @param pageSize 每一页最多显示几条记录 * @return * @throws Exception */ public int countTotalPage(int pageSize) throws Exception; }
b .在TaskDAOimpl中写方法实现
package dao.impl; import java.util.ArrayList; import java.util.List; import java.sql.*; import util.DBUtil; import dao.TaskDAO; import entity.Task; public class TaskDAOimpl implements TaskDAO{ public List<Task> findAll() throws Exception { List<Task> taskList = new ArrayList<Task>(); Connection conn = DBUtil.getConnection(); String sql = "select * from t_task"; PreparedStatement pstmt = conn.prepareStatement(sql); ResultSet rs = pstmt.executeQuery(); while(rs.next()){ Task task = new Task(); task.setId(rs.getLong("id")); task.setTas_id(rs.getString("tas_id")); task.setTas_name(rs.getString("tas_name")); task.setTas_begin(rs.getDate("tas_begin")); task.setTas_end(rs.getDate("tas_end")); taskList.add(task); } DBUtil.close(conn); return taskList; } public List<Task> findAll(int page, int pageSize) throws Exception { List<Task> taskList = new ArrayList<Task>(); Connection conn = DBUtil.getConnection(); String sql = "select * from t_task limit ?,?"; PreparedStatement pstmt = conn.prepareStatement(sql); //设置分页查询参数 int begin = (page-1) * pageSize; pstmt.setInt(1, begin); pstmt.setInt(2, pageSize); ResultSet rs = pstmt.executeQuery(); while(rs.next()){ Task task = new Task(); task.setId(rs.getLong("id")); task.setTas_id(rs.getString("tas_id")); task.setTas_name(rs.getString("tas_name")); task.setTas_begin(rs.getDate("tas_begin")); task.setTas_end(rs.getDate("tas_end")); taskList.add(task); } DBUtil.close(conn); return taskList; } public int countTotalPage(int pageSize) throws Exception { Connection conn = DBUtil.getConnection(); String sql = "select count(*) from t_task"; PreparedStatement pstmt = conn.prepareStatement(sql); ResultSet rs = pstmt.executeQuery(); rs.next(); int count = rs.getInt(1); DBUtil.close(conn); //计算最大页,如果没有数据,最大页设为1 if(count ==0){ return 1; }else if(count % pageSize == 0){ return count/pageSize; }else{ return count/pageSize + 1; } } }
c.修改TaskAction 添加属性方法
package action; import java.util.List; import dao.impl.TaskDAOimpl; import entity.Task; public class TaskAction { private List<Task> taskList; //当前要显示第几页 private int page=1; //成员变量 //最大页 private int totalPage; //每页显示3条数据 public static final int PAGE_SIZE = 3; public String execute(){ TaskDAOimpl dao = new TaskDAOimpl(); try { //查询数据 taskList = dao.findAll(page, PAGE_SIZE); //获取最大页, //最大页也可根据list集合获得,为了提高效率,最好使用此方法 totalPage = dao.countTotalPage(PAGE_SIZE); return "success"; } catch (Exception e) { e.printStackTrace(); return "error"; } } public List<Task> getTaskList() { return taskList; } public void setTaskList(List<Task> taskList) { this.taskList = taskList; } public int getPage() { return page; } public void setPage(int page) { this.page = page; } public int getTotalPage() { return totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } }
d.修改视图list.jsp
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <title>Insert title here</title> </head> <body> <table border="1"> <tr> <th>编号</th> <th>任务名称</th> <th>开始事件</th> <th>结束事件</th> </tr> <c:forEach items="${taskList}" var="list"> <tr> <td>${list.tas_id}</td> <td>${list.tas_name }</td> <td>${list.tas_begin }</td> <td>${list.tas_end }</td> </tr> </c:forEach> </table> <c:choose> <c:when test="${page <= 1}"> <a>上一页</a> </c:when> <c:otherwise> <a href="/struts2_showlist/list?page=${page-1 }">上一页<<</a> </c:otherwise> </c:choose> 第${page }页,共${totalPage }页 <c:choose> <c:when test="${page >= totalPage}"> <a>下一页</a> </c:when> <c:otherwise> <a href="/struts2_showlist/list?page=${page+1 }">下一页>></a> </c:otherwise> </c:choose> </body> </html>
修改完毕,(无法上传图片,所以展示运行效果).
了解一下 Action 中成员变量和属性概念 , 一般情况下成员变量名和属性名一致 . 属性需要有对应的 setter 和 getter 方法 .
public class A{
private String n;// 成员变量名为 n
// 属性名为 name
public void setName(String name){...}
public String getName(){...}
}
(1)Struts2 将请求参数值给 Action 传递时 , 属性名与请求参数名保持一致 .
(2) 在 JSP 视图中 , 使用 EL 表达式获取 Action 数据时 , 与 属性保持一致 .
2.OGNL 技术的使用
OGNL 技术源于 ognl.jar, ognl.jar 在 webwork 框架中开始引入 , 后来在 Struts2 才延续下来 .
(1).ognl.jar 有什么作用 .
Object Graphic Navigation Language 对象图导航语言
ognl.jar 可以便于对复杂对象的访问 , 例如属性获取和设置值 , 方法调用等 . 使用时需要编写 OGNL 表达式 . 比 EL 表达式功能强大 .
(2)OGNL 基本语法
a. 基本类型属性
“id”, “name”
b. 数组和 List
“array[0]”, “list[1]”
c. Map
“map.key”, “map[‘key’]”
d. 基本运算符
+,-,*,/ 三目运算等都支持
e. 方法调用
array[0].toLowerCase()
f. 静态方法和常量调用
@java.lang.Math@PI
@ 包名 . 类名 @ 常量
@ 包名 . 类名 @ 静态方法 ()
g. 集合过滤
集合属性 .{?#this.age>15}
#this 可以理解成集合元素
? 指的是返回满足过滤条件的所有元素
^ 指的是返回第一个满足条件的元素
$ 指的是返回最后一个满足条件的元素
h. List 和 Map 常量的定义
List 常量 ”{‘tom’,’scott’}”, ”{1,2,3}”
Map 常量 “#{‘age’:20, ‘name’:’ 张三 ’}”
代码演示
创建FOO实体类
package entity; import java.util.List; import java.util.Map; public class Foo { private int id; private String name; private String[] array; private List<String> list; private Map<String,String> map; private List<Person> pers; public List<Person> getPers() { return pers; } public void setPers(List<Person> pers) { this.pers = pers; } public String[] getArray() { return array; } public void setArray(String[] array) { this.array = array; } public int getId() { return id; } public void setId(int id) { this.id = id; } public List<String> getList() { return list; } public void setList(List<String> list) { this.list = list; } public Map<String, String> getMap() { return map; } public void setMap(Map<String, String> map) { this.map = map; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
创建Person实体类
package entity; public class Person { private Address address; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } }
创建Address类
package entity; public class Address { private String street; private String zipcode; public Address(String street, String zipcode) { super(); this.street = street; this.zipcode = zipcode; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getZipcode() { return zipcode; } public void setZipcode(String zipcode) { this.zipcode = zipcode; } }
创建TestOgnl_01类
package test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import ognl.Ognl; import ognl.OgnlException; import org.junit.Test; import entity.Address; import entity.Foo; import entity.Person; public class TestOgnl { @Test public void test1(){ Foo foo = new Foo(); foo.setId(100); foo.setName("张三"); foo.setArray(new String[]{"A","B","C"}); List<String> list = new ArrayList<String>(); list.add("one"); list.add("two"); list.add("three"); foo.setList(list); Map<String,String> map = new HashMap<String, String>(); map.put("one", "壹"); map.put("two", "贰"); map.put("three", "叁"); foo.setMap(map); List<Person> pers = new ArrayList<Person>(); Person p1 = new Person(); p1.setAddress(new Address("中鼎大厦","100021")); Person p2 = new Person(); p2.setAddress(new Address("CBD大街","120002")); pers.add(p1); pers.add(p2); foo.setPers(pers); //利用OGNL对foo对象访问 //Ognl.getValue("OGNL表达式", foo); try { //基本类型数据的访问 Integer id = (Integer)Ognl.getValue("id", foo); System.out.println(id); String name = (String)Ognl.getValue("name", foo); System.out.println(name); //数组访问 String arry = (String)Ognl.getValue("array[0]",foo); System.out.println(arry); //List集合访问,表达式风格与数组一样 Ognl.setValue("list[0]", foo, "oneone"); String lst = (String)Ognl.getValue("list[0]",foo); System.out.println(lst); //map集合访问,map['key']或map.key String mp = (String)Ognl.getValue("map['three']", foo); System.out.println(mp); //访问pers集合属性值 String val = (String)Ognl.getValue("'北三环'+pers[0].address.street", foo); System.out.println(val); //方法调用 String str = (String)Ognl.getValue("array[0].toLowerCase()", foo); System.out.println(str); //Ognl.getValue("list.size()", foo); //静态方法和常量访问 Object obj = Ognl.getValue("@java.lang.Math@PI", foo); System.out.println(obj); } catch (OgnlException e) { e.printStackTrace(); } } }
创建TestOgnl_02类
package test; import java.util.ArrayList; import java.util.List; import org.junit.Test; import ognl.Ognl; import ognl.OgnlException; import entity.Address; import entity.Foo; import entity.Person; public class TestOgnl_02 { @Test public void test1(){ Foo foo = new Foo(); List<Person> pers = new ArrayList<Person>(); Person p1 = new Person(); p1.setAge(18); p1.setAddress(new Address("中鼎大厦A","10021")); Person p2 = new Person(); p2.setAge(13); p2.setAddress(new Address("中鼎大厦B","10022")); Person p3 = new Person(); p3.setAge(20); p3.setAddress(new Address("中鼎大厦C","10023")); pers.add(p1); pers.add(p2); pers.add(p3); foo.setPers(pers); //集合的过滤 try { List<Person> list = (List) Ognl.getValue("pers.{?#this.age>15}", foo); for(Person p : list){ System.out.println(p.getAge() + p.getAddress().getStreet()); } //List常量定义 Object obj = Ognl.getValue("{1,2,3}", null); System.out.println(obj.getClass()); } catch (OgnlException e) { e.printStackTrace(); } } }
(3)OGNL 体系结构
主要包含三个组成部分
OGNL 引擎 : 负责解析 OGNL 表达式 , 访问目标对象 (root) 和上下文对象 (context).
root 对象 :Object 类型 , 根对象 , 默认访问此对象
context 对象 :map 类型 , 上下文对象 , 表达式以 # 开始时访问此对象
3.OGNL 在 Struts2 中的使用
(1)XWork 框架对 OGNL 进行了改造
XWork 提供了一个 CompountRoot 对象 , 替换了 OGNL 原有的 Root 对象 . CompountRoot 是一个栈结构 , 可以存放多个root对象,当输入 ”name” OGNL 表达式时 , OGNL 引擎会从栈顶对象向下一次寻找属性值 , 找到返回 , 找不到返回 null.
context对象同OGNL一样.
(2)ValueStack 对象
ValueStack 对象类型为 OgnlValueStack, 内部封装了 OGNL 体系结构 , 内部提供了访问和存储机制 .
当客户端发送请求之后 , Struts 框架会自动创建一个 ValueStack, 并存入 request 中 , key 为 ”struts.valueStack”, 然后将 request, session,application 等对象存入 context 区域 , 将 Action 对象存入 root 栈顶 , 当请求完毕后 , Action 对象会清除 , 然后将下一个请求的 Action 压入 .
4. 使用 OGNL+Struts2 标签重构列表显示示例
修改list.jsp
<table border="1"> <tr> <th>编号</th> <th>任务名称</th> <th>开始事件</th> <th>结束事件</th> </tr> <s:iterator value="taskList" var="list"> <tr> <td><s:property value="#list.tas_id"/></td> <td><s:property value="#list.tas_name"/></td> <td><s:property value="#list.tas_begin"/></td> <td><s:property value="#list.tas_end"/></td> </tr> </s:iterator> </table> <s:if test="page <= 1"> <a>上一页</a> </s:if> <s:else> <a href="/struts2_showlist/list?page=<s:property value="page-1"/>">上一页</a> </s:else> 第<s:property value="page"/>页,共<s:property value="totalPage"/>页 <s:if test="page >= totalPage"> <a>下一页</a> </s:if> <s:else> <a href="/struts2_showlist/list?page=<s:property value="page+1"/>">下一页</a> </s:else>
5. EL 表达式在 Struts2 中的使用
EL 可以从 page,request,action,session,application 范围中取值并显示 .
EL 为什么在 JSP 中可以访问到 Action 属性 ?
${name} -->
String name = request.getAttribute(“name”);
out.println(name);
Struts2 将原有的 request 对象封装了 , 并重写了 getAttribute 方法 .
public class StrutsRequestWrapper extends HttpServletRequestWrapper{ public Object getAttribute(String key){ Object value = super.getAttribute(key); if(value == null){ valueStack.findValue(“OGNL表达式”); //Ognl.getValue(“name”, context, root); } return value; } }