首注:本学习教程为传智播客汤阳光讲师所公布的免费OA项目视频我的文字版实践笔记,本人用此来加强巩固自己开发知识,如有网友转载,请注明。谢谢。
一 使用递归使部门列表树状显示:
1.写一个工具类,实现通过顶级部门查询所有,具体如下:
1 package cn.clear.oa.util; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.List; 6 7 import cn.clear.oa.domain.Department; 8 9 public class DepartmentUtil { 10 //遍历部门树,把所有部门遍历出来以树状显示 11 public static List<Department> getAllDepartments(List<Department> topList) { 12 List<Department> departments = new ArrayList<Department>(); 13 walkDepartmentTreeList(topList,"┣ ",departments); 14 return departments; 15 } 16 17 private static void walkDepartmentTreeList(Collection<Department> topList,String prefix, List<Department> departments){ 18 19 for (Department top : topList) { 20 Department copy = new Department();//创建副本,不要使用在Session的原对象 21 //遍历顶点 22 copy.setId(top.getId()); 23 copy.setName(prefix + top.getName()); 24 departments.add(copy); 25 //遍历子树 26 walkDepartmentTreeList(top.getChildren()," "+prefix,departments); 27 } 28 } 29 }
DepartmentUtil.java
2.因为部门列表在新建页面和修改页面存在,所有修改新建页面和修改页面的action,如下:
1 public String addUI() throws Exception { 2 // 准备departmentList数据 3 List<Department> topList = departmentService.findTopList(); 4 List<Department> departmentList = DepartmentUtil 5 .getAllDepartments(topList); 6 // 放在值栈中的map中 7 ActionContext.getContext().put("departmentList", departmentList); 8 return "saveUI"; 9 }
addUI()
1 public String editUI() throws Exception { 2 // 准备departmentList数据 3 List<Department> topList = departmentService.findTopList(); 4 List<Department> departmentList = DepartmentUtil 5 .getAllDepartments(topList); 6 // 放在值栈中的map中 7 ActionContext.getContext().put("departmentList", departmentList); 8 9 Department department = departmentService.findById(model.getId()); 10 // 将对象放在栈顶 11 ActionContext.getContext().getValueStack().push(department); 12 // 回显上级部门 13 if (department.getParent() != null) { 14 parentId = department.getParent().getId(); 15 } 16 return "saveUI"; 17 }
editUI()
3.发现树形列表的顺序混乱(即刷新会改变顺序),这是因为在hibernate映射文件中使用了set集合,是无序的,要使得按顺序排列,那么修改映射文件,在查询子部门列表集合时增加一个order-by="id ASC"标签,这个标签的值应该是sql的排序语句,具体如下:
查询子列表(Department.hbm.xml)
二 对所有jsp页面进行优化:
将所有公共的jsp导入代码抽取到一个新的页面,之后只要引用该新页面即可,不用再在每个页面进行多次导入操作了。
新页面commons.jspf:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <%@ taglib prefix="s" uri="/struts-tags"%> 3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 4 <script language="javascript" src="${pageContext.request.contextPath}/script/jquery.js"></script> 5 <script language="javascript" src="${pageContext.request.contextPath}/script/pageCommon.js" charset="utf-8"></script> 6 <script language="javascript" src="${pageContext.request.contextPath}/script/PageUtils.js" charset="utf-8"></script> 7 <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/style/blue/pageCommon.css" /> 8 <script type="text/javascript"> 9 </script>
commons.jspf
其他页面的和commons.jspf代码相同的全部删除,然后在页面中设置一个包含标签,将commons页面引入即可:
<%@ include file="/WEB-INF/jsp/public/commons.jspf" %>
三 抽取后台action的相同代码,放到BaseAction.java中,在使用时只要继承该类即可:
1.建立BaseAction.java:
1 package cn.clear.oa.base; 2 3 import java.lang.reflect.ParameterizedType; 4 5 import javax.annotation.Resource; 6 7 import cn.clear.oa.service.DepartmentService; 8 import cn.clear.oa.service.RoleService; 9 10 import com.opensymphony.xwork2.ActionSupport; 11 import com.opensymphony.xwork2.ModelDriven; 12 13 @SuppressWarnings("unchecked") 14 public abstract class BaseAction<T> extends ActionSupport implements 15 ModelDriven<T> { 16 17 /** 18 * 19 */ 20 private static final long serialVersionUID = 1L; 21 //=======================ModelDriven的支持========================== 22 protected T model; 23 24 public BaseAction(){ 25 26 try { 27 //通过反射获取model的真实类型 28 ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); 29 30 Class<T> clazz = (Class<T>) pt.getActualTypeArguments()[0]; 31 //通过反射创建model的实例 32 model = clazz.newInstance(); 33 } catch (Exception e) { 34 // TODO Auto-generated catch block 35 throw new RuntimeException(e); 36 } 37 } 38 39 public T getModel() { 40 // TODO Auto-generated method stub 41 return model; 42 } 43 44 45 //=========================Service的声明============================ 46 @Resource 47 protected RoleService roleService; 48 @Resource 49 protected DepartmentService departmentService; 50 }
BaseAction.java
2.在具体action中将与BaseAction.java相同的代码去除,指定具体action只继承BaseAction即可,这样在action就可以专注自己的代码了。
四 将Dao层和Service层代码结合在Service层,减少两层间的重用代码:
1.将Dao层所有代码(包括实现类)全部删除;
2.此时因为Dao层已经消亡,所以将BaseDao.java及BaseDaoImpl.java名字改为DaoSupport.java及DaoSupportImpl.java,以告知这是Dao数据库操作支持;
3.将Service层的接口类直接实现DaoSupport.java,将Service层的实现类继承DaoSupportImpl.java,并将所有重复的业务代码删除即可。
以下就是修改后的整体结构图:
五 修改以上后测试发现无法修改和删除实体,究其原因是因为Service的实现类开启事务方法是使用@Transactional注解,但是Service的实现类继承自DaoSupportImpl.java,而该类是无法使用子类的事务,所以解决的方法是在DaoSupportImpl.java中也使用该注解开启事务,此注解可以继承,即子类可以字节使用父类开启的事务,所以在Service的实现类中可以将该注解移除。修改完之后开启服务器测试,Ok。