|
Posted on 2010-01-13 15:32 長城 阅读(401) 评论(0) 编辑 收藏
今日完成部门(department)和员工(employee)管理,由于昨天已经对增、删、改、查摸了遍,所以今日的内容相对就比较简单了。虽然简单,仍然有需要注意的地方。经验丰富的程序员,编写的代码十分优雅,这也是新人们严重不足的地方,当然我也应该加强这方面的能力。 不过说来也十分无聊,手动编写OA项目已二天了。这两天除了项目的架构与优雅的接口设计让我感觉好些外,其他没有什么让我感觉愉快的。因为剩下的就是对数据库的CRUD操作,无聊之极。但是我仍然需要努力学习,并在工作中总结经验。将这部分的操作变得更简洁一些。 一、部门管理 部门管理的难点在于,一个部门可以有一个“上级部门”与多个“下级部门”。对应的DispatchAciton有六个处理请求的方法。 1.显示部门列表的list方法 显示部门列表的方式:在页面中显示出顶级部门(没有上级部门的部门),点击其中的某个部门后显示出对应部门的所有子部门。方法如下: DepartmentService deptServ = new DepartmentServiceImpl(); /** * 部门列表 */ public ActionForward list(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取页面传递过来的上级部门ID Long parentId = null; if(request.getParameter("parentId")!=null) parentId = Long.parseLong(request.getParameter("parentId")); // 如果上级部门ID不为null则获取对应部门的所有下级部门,否则获取所有顶级部门 List<Department> list = null; if (parentId == null || this.deptServ.getById(parentId)==null) list = this.deptServ.getTopLevel(); else { Department dept = this.deptServ.getById(parentId); request.setAttribute("parent",dept); list = new ArrayList<Department>(dept.getChildren()); } // 将获取后的部门列表存放于request的属性中 request.setAttribute("departmentList", list); // 跳转到显示部门列表页面 return mapping.findForward("list"); // list.jsp } | 这里我有必要说一下我的实现思想,我受以前面向过程编程的思想的影响没有从完全面向对象的角度去解决这个实现。之前在老方的课堂上也是这样,我没有从完全面向对象的角度去思考他提出的问题,只想着最简洁、最快速的面向过程实现方法。 我在实现上面的方法时也忽略的面向对象的思想,直接使用hibernate去查询数据库。事实上完全没必要,因为部门之间的关系我们已经通过对象与映射文件描述出来了。直接使用对象的属性就可以了!比如,获取所有子部门。 2.跳转到添加部门的addUI方法 /** * 跳转至添加部门页面 */ public ActionForward addUI(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取部门列表,以备指定被添加部门的上级部门 List<Department> list = this.deptServ.getTopLevel(); // getAllDepartmentList方法将部门以树型的方法显示 request.setAttribute("departmentList", DepartmentUtils.getAllDepartmentList(list)); // 跳转至添加部门页面 return mapping.findForward("saveUI"); // saveUI.jsp } | 这里只有以树型显示部门列表的方法是个小重点,我们使用了递归的方法实现的: public static List<Department> getAllDepartmentList( List<Department> topLevelList) { List<Department> list = new ArrayList<Department>(); formatDepartmentList(topLevelList, "┠", list); return list; } private static void formatDepartmentList(Collection<Department> deptList, String prefix, List<Department> reval) { for (Department dept : deptList) { // 新创建一个Department,防止修改hibernate缓存中的数据记录。 Department newDept = new Department(); newDept.setId(dept.getId()); newDept.setName(prefix + dept.getName()); // 添加到返回值接收的List中 reval.add(newDept); // 递归调用子部门 formatDepartmentList(dept.getChildren(), " " + prefix, reval); } } | 3.添加部门的add方法 /** * 添加部门 */ public ActionForward add(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取表单提交过来的信息,转成Department的Bean数据 DepartmentActionForm deptForm = (DepartmentActionForm) form; Department dept = new Department(); dept.setName(deptForm.getName()); dept.setParent(this.deptServ.getById(deptForm.getParentId())); // 保存数据 this.deptServ.save(dept); // 因为添加部门后我们需要显示与被添加部门的所有同级部门,所以传递给显示页面上级部门的ID参数。 ActionForward af = mapping.findForward("toList"); return new ActionForward(af.getPath() + "&parentId=" + deptForm.getParentId(),af.getRedirect()); } | 4.跳转到修改部门的editUI方法 /** * 跳转到修改部门页面 */ public ActionForward editUI(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取部门列表,以备指定被修改部门的上级部门 List<Department> list = this.deptServ.getTopLevel(); request.setAttribute("departmentList", DepartmentUtils.getAllDepartmentList(list)); // 将被修改部门的信息封装到ActionForm中 DepartmentActionForm deptForm = (DepartmentActionForm) form; Department dept = this.deptServ.getById(deptForm.getId()); deptForm.setName(dept.getName()); if (dept.getParent() != null) deptForm.setParentId(dept.getParent().getId()); // 跳转至修改部门页面 return mapping.findForward("saveUI"); // saveUI.jsp } | 5.修改部门的edit方法 /** * 修改部门 */ public ActionForward edit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取表单提交过来的信息,转成Department的Bean数据 DepartmentActionForm deptForm = (DepartmentActionForm) form; // 先到数据库中获取被修改部门的记录,是因为Bean与ActionForm属性不一致。 Department dept = this.deptServ.getById(deptForm.getId()); dept.setName(deptForm.getName()); dept.setParent(this.deptServ.getById(deptForm.getParentId())); // 更新数据 this.deptServ.update(dept); // 因为更新部门后我们需要显示与被添加部门的所有同级部门,所以在传递给显示页面上级部门的ID。 ActionForward af = mapping.findForward("toList"); return new ActionForward(af.getPath() + "&parentId=" + deptForm.getParentId(),af.getRedirect()); } | 6.删除部门 /** * 删除部门 */ public ActionForward del(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取部门id并删除 String id = request.getParameter("id"); this.deptServ.delete(Long.parseLong(id)); // 因为删除部门后我们需要显示与被添加部门的所有同级部门,所以在传递给显示页面上级部门的ID。 ActionForward af = mapping.findForward("toList"); return new ActionForward(af.getPath() + "&parentId=" + request.getParameter("parentId"), af.getRedirect()); } | 上面这些方法十分简单! 二、员工管理 员工管理的难点在于,员工具有一个部门和多个岗位的特性。我们通过指定员工对象的部门属性和员工集合属性,可以简单的描述它们之间的关系。但添加或修改员工时,员工的部门和岗位的属性如何显示在页面上呢?我们的页面表单使用的是struts的html标签,部门使用下拉列表框显示,岗位使用列表框显示。这两个组件的选中项,只需要对应的id值即可。 这样,我们就需要将员工的部门属性和岗位集合属于转换为对应的id即可。我们将EmployeeActionForm对部门属性定义为“Long departmentId;”,岗位集合属性定义为“Set<Role> roleIdList;”,具体看下面的代码。 1.员工列表 /** * 员工列表 */ public ActionForward list(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { List<Employee> employees = this.empServ.findAll(); request.setAttribute("employeeList", employees); return mapping.findForward("list"); // list.jsp } | 2.跳转到添加员工页面 /** * 添加员工页面 */ public ActionForward addUI(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取部门和岗位列表,提供给添加员工时使用 List<Department> depts = this.deptServ.findAll(); List<Role> roles = this.roleServ.findAll(); request.setAttribute("departmentList", DepartmentUtils.getAllDepartmentList(depts)); request.setAttribute("roleList", roles); return mapping.findForward("saveUI"); // saveUI.jsp } | 3.添加员工 /** * 添加员工 */ public ActionForward add(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取页面提交过来的员工信息 EmployeeActionForm empForm = (EmployeeActionForm) form; Employee emp = new Employee(); BeanUtils.copyProperties(emp, empForm); // 根据选中的部门id,获取部门对象 emp.setDepartment(this.deptServ.getById(empForm.getDepartmentId())); // 根据选中的岗位id数组,获取岗位对象集合 Set<Role> roles = new HashSet(this.roleServ.findByQuery(empForm.getRoleIdList())); emp.setRoles(roles); // 保存 this.empServ.save(emp); // 跳转到显示员工列表页面 return mapping.findForward("toList"); } | 4.跳转到修改员工页面 /** * 修改员工页面 */ public ActionForward editUI(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取被修改员工的信息 Long id = Long.parseLong(request.getParameter("id")); Employee emp = this.empServ.getById(id); // 将被修改员工的信息封装到ActionForm中 EmployeeActionForm empForm = (EmployeeActionForm) form; BeanUtils.copyProperties(empForm, emp); // 获取部门ID empForm.setDepartmentId(emp.getDepartment().getId()); // 根据岗位集合获取对象岗位id数组 empForm.setRoleIdList(this.roleServ.getIdsByRoles(emp.getRoles())); // 获取部门和岗位列表,并添加到request的属性中 List<Department> depts = this.deptServ.findAll(); List<Role> roles = this.roleServ.findAll(); request.setAttribute("departmentList", DepartmentUtils.getAllDepartmentList(depts)); request.setAttribute("roleList", roles); // 跳转到修改页面 return mapping.findForward("saveUI"); // saveUI.jsp } | 5.修改员工 /** * 修改员工 */ public ActionForward edit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 先到数据库中获取被修改员工的记录,是因为Bean与ActionForm属性不一致。 Long id = Long.parseLong(request.getParameter("id")); Employee emp = this.empServ.getById(id); BeanUtils.copyProperties(emp, form); // 修改员工信息 this.empServ.update(emp); // 跳转到显示员工列表页面 return mapping.findForward("toList"); } | 6.删除员工 /** * 删除员工 */ public ActionForward del(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 根据删除员工id,删除员工 Long id = Long.parseLong(request.getParameter("id")); this.empServ.delete(id); // 跳转到显示员工列表页面 return mapping.findForward("toList"); } | 7.特别注意 员工对象有一个入职时间的属性,我们将这个属性类型定义为java.util.Date类型。但保存或获取SQL数据库中的Date类型记录时,我们需要转换。但在程序中我们使用“BeanUtils.copyProperties(dest, orig);”方法将ActionForm中的数据拷贝到Dean对象中,此时我们需要为BeanUtils添加一个指定类型的转换器,在HibernateSessionFilter的init方法中注册转换器: public void init(FilterConfig arg0) throws ServletException { ConvertUtils.register(new BeanDateConvert(), Date.class); System.out.println("过滤器HibernateSessionFilter注册转换器BeanDateConvert成功!"); } | 转换器: import java.text.*; import java.util.Date; import org.apache.commons.beanutils.Converter; public class BeanDateConvert implements Converter { private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); public Object convert(Class clazz, Object value) { if(value == null) return null; if(value instanceof Date) return value; if(value instanceof String){ try { return this.sdf.parse((String) value); } catch (ParseException e) { e.printStackTrace(); return null; } } throw new IllegalArgumentException("不支持的类型:"+value.getClass().getName()); } } | 给员工分配帐户,以及登陆与注销管理在此就不总结了,因为它十分简单。 三、JSP页面整合与JQuery插件 现在,我们将这两天编写的内容使用framset整合到一起(index.jsp): <!-- 主页面 --> <frameset border="0" rows="70px,20px,*" border="0" id="framesetRows"> <!-- 上部 --> <frame name="top" src="top.jsp" noresize="noresize" scrolling="no"> <!-- 分隔条 --> <frame name="top" src="top2.jsp" noresize="noresize" scrolling="no"> <!-- 下部 --> <frameset cols="200px,17px,*" border="0" id="framesetCols"> <!-- 左部 --> <frame name="left" src="left.jsp" noresize="noresize"> <!-- 分隔条 --> <frame name="middle" src="middle.jsp" noresize="noresize" scrolling="no"> <!-- 右部 --> <frame name="right" src="right.jsp" noresize="noresize"> </frameset> </frameset> | 我们在左部页面使用了树型,显示各应用模块和模块详细。在这里我们使用的是xtree这个JQuery插件。使用JQuery插件非常简单,直接在网页中引入插件的js文件,然后调用相关接口即可使用插件: <script type="text/javascript" src="${pageContext.request.contextPath}/script/xtree/xtree.js"></script> <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/script/xtree/xtree.css" /> <script type="text/javascript"> var tree = new WebFXTree("导航菜单"); var item0 = tree.add(new WebFXTreeItem("Welcome, [${user.employee.name}]")); item0.add(new WebFXTreeItem("登录", "<html:rewrite action='/user?method=loginUI'/>", null, null, null, "right")); item0.add(new WebFXTreeItem("注销", "<html:rewrite action='/user?method=logout'/>", null, null, null, "right")); var item3 = tree.add(new WebFXTreeItem("组织机构管理")); var item = item3.add(new WebFXTreeItem("部门管理", "<html:rewrite action='/dept?method=list'/>", null, null, null, "right")); item3.add(new WebFXTreeItem("岗位管理", "<html:rewrite action='/role?method=list'/>", null, null, null, "right")); item3.add(new WebFXTreeItem("员工管理", "<html:rewrite action='/emp?method=list'/>", null, null, null, "right")); document.write(tree); tree.expandAll(); </script> | 我们也有在添加员工时为入职时间指定了一个日期框的插件,使用起来非常方便。 OK,上边就是今天的内容!还有OA项目还有三天,接下来的三天主要使用JBPM来完成审批管理、审批流转、表单查询功能。 以前学的零散的知识,现在用到了一起,感觉very fine!
|