OA项目总结

一、自定义拦截器:
     继承AbstractInterceptor,覆写intercept方法,实现功能逻辑,最后在Struts.xml文件中配置了自定义拦截器,首先自定义拦截器栈,

1 <!-- 配置拦截器 -->
2 <interceptors>
3 <interceptor name="cusInterceptor" class="com.swust.interceptor.CusInterceptor"/>
4 <!-- 声明拦截器栈 -->
5 <interceptor-stack name="myStack">
6 <interceptor-ref name="cusInterceptor"/>
7 <interceptor-ref name="defaultStack"/>
8 </interceptor-stack>
9 </interceptors>

然后自定义拦截器栈,使得单个包内或者整个项目经过自定义拦截器

<!-- 默认本包中的所有action都要经过myStack这个拦截器栈 -->
<default-interceptor-ref name="myStack"></default-interceptor-ref>

最后可以利用自定义拦截器通过地址栏的地址进行用户相应的权限控制

 1 package com.swust.oa.interceptor;
 2
 3 import com.swust.oa.domain.User;
 4 import com.swust.oa.struts2.action.LoginLogoutAction;
 5
 6 import com.opensymphony.xwork2.ActionContext;
 7 import com.opensymphony.xwork2.ActionInvocation;
 8 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
 9
10 @SuppressWarnings("serial")
11 public class CheckPrivilegeInterceptor extends AbstractInterceptor {
12
13     public String intercept(ActionInvocation invocation) throws Exception {
14         System.out.println("CheckPrivilegeInterceptor.intercept()");
15
16         // 获取当前的登录用户
17         User user = (User) ActionContext.getContext().getSession().get("user");
18         // 获取当前访问的URL(action的名称),需要处理一下UI后缀
19         String url = invocation.getProxy().getActionName();
20         if (url.endsWith("UI")) {
21             url = url.substring(0, url.length() - 2);
22         }
23         // 一、未登录的情况
24         if (user == null) {
25             if (invocation.getProxy().getAction() instanceof LoginLogoutAction) {
26                 // 如果正在使用登录用功能,则放行
27                 return invocation.invoke(); // 放行
28             } else {
29                 // 如果不是正在使用登录功能,则转到登录页面
30                 return "loginUI";
31             }
32         }
33         // 二、已登录的情况
34         else {
35             if (user.hasPrivilegeByUrl(url)) {
36                 // 如果有权限,则放行
37                 return invocation.invoke(); // 放行
38             } else {
39                 // 如果没有有权,则转到错误页面
40                 return "privilegeError";
41             }
42         }
43     }
44 }

二、修改struts原生标签
    在项目源文件下新建和框架中相同的包名和文件名称,同时修改源文件,之后即可实现覆盖元标签功能

  1 package org.apache.struts2.views.jsp.ui;
  2
  3 import javax.servlet.http.HttpServletRequest;
  4 import javax.servlet.http.HttpServletResponse;
  5 import javax.servlet.jsp.JspException;
  6
  7 import org.apache.struts2.components.Anchor;
  8 import org.apache.struts2.components.Component;
  9
 10 import com.swust.oa.domain.User;
 11
 12 import com.opensymphony.xwork2.util.ValueStack;
 13
 14 /**
 15  * @see Anchor
 16  */
 17 public class AnchorTag extends AbstractClosingTag {
 18
 19     private static final long serialVersionUID = -1034616578492431113L;
 20
 21     protected String href;
 22     protected String includeParams;
 23     protected String scheme;
 24     protected String action;
 25     protected String namespace;
 26     protected String method;
 27     protected String encode;
 28     protected String includeContext;
 29     protected String escapeAmp;
 30     protected String portletMode;
 31     protected String windowState;
 32     protected String portletUrlType;
 33     protected String anchor;
 34     protected String forceAddSchemeHostAndPort;
 35
 36     @Override
 37     public int doEndTag() throws JspException {
 38         // 获取当前登录用户
 39         User user = (User) pageContext.getSession().getAttribute("user");
 40         // 获取当前访问的URL(actionName),就是本类的action属性值
 41         // >> 去掉参数
 42         String url = action;
 43         int pos = url.indexOf(‘?‘);
 44         if (pos > -1) {
 45             url = url.substring(0, pos); // 去掉参数
 46         }
 47         // >> 去掉UI后缀(例:userAction_addUI就是userAction_add权限)
 48         if (url.endsWith("UI")) {
 49             url = url.substring(0, url.length() - 2);
 50         }
 51
 52         if (user.hasPrivilegeByUrl(url)) {
 53             return super.doEndTag(); // 正常显示超链接标签,并继续执行后面的内容
 54         } else {
 55             return EVAL_PAGE; // 不显示当前的超链接标签,只继续执行后面的内容
 56         }
 57     }
 58
 59     public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
 60         return new Anchor(stack, req, res);
 61     }
 62
 63     protected void populateParams() {
 64         super.populateParams();
 65
 66         Anchor tag = (Anchor) component;
 67         tag.setHref(href);
 68         tag.setIncludeParams(includeParams);
 69         tag.setScheme(scheme);
 70         tag.setValue(value);
 71         tag.setMethod(method);
 72         tag.setNamespace(namespace);
 73         tag.setAction(action);
 74         tag.setPortletMode(portletMode);
 75         tag.setPortletUrlType(portletUrlType);
 76         tag.setWindowState(windowState);
 77         tag.setAnchor(anchor);
 78
 79         if (encode != null) {
 80             tag.setEncode(Boolean.valueOf(encode).booleanValue());
 81         }
 82         if (includeContext != null) {
 83             tag.setIncludeContext(Boolean.valueOf(includeContext).booleanValue());
 84         }
 85         if (escapeAmp != null) {
 86             tag.setEscapeAmp(Boolean.valueOf(escapeAmp).booleanValue());
 87         }
 88         if (forceAddSchemeHostAndPort != null) {
 89             tag.setForceAddSchemeHostAndPort(Boolean.valueOf(forceAddSchemeHostAndPort).booleanValue());
 90         }
 91     }
 92
 93     public void setHref(String href) {
 94         this.href = href;
 95     }
 96
 97     public void setEncode(String encode) {
 98         this.encode = encode;
 99     }
100
101     public void setIncludeContext(String includeContext) {
102         this.includeContext = includeContext;
103     }
104
105     public void setEscapeAmp(String escapeAmp) {
106         this.escapeAmp = escapeAmp;
107     }
108
109     public void setIncludeParams(String name) {
110         includeParams = name;
111     }
112
113     public void setAction(String action) {
114         this.action = action;
115     }
116
117     public void setNamespace(String namespace) {
118         this.namespace = namespace;
119     }
120
121     public void setMethod(String method) {
122         this.method = method;
123     }
124
125     public void setScheme(String scheme) {
126         this.scheme = scheme;
127     }
128
129     public void setValue(String value) {
130         this.value = value;
131     }
132
133     public void setPortletMode(String portletMode) {
134         this.portletMode = portletMode;
135     }
136
137     public void setPortletUrlType(String portletUrlType) {
138         this.portletUrlType = portletUrlType;
139     }
140
141     public void setWindowState(String windowState) {
142         this.windowState = windowState;
143     }
144
145     public void setAnchor(String anchor) {
146         this.anchor = anchor;
147     }
148
149     public void setForceAddSchemeHostAndPort(String forceAddSchemeHostAndPort) {
150         this.forceAddSchemeHostAndPort = forceAddSchemeHostAndPort;
151     }
152 }

三、懒加载

一般懒加载通过设置hibernate配置文件设置相关实体属性的懒加载为false,如果要实现延迟关闭
session,例如要在一次请求结束之后才实现关闭session,则可以在web.xml文件中添加如下拦截器:

1 <filter>
2 <filter-name>OpenSessionInViewFilter</filter-name>
3 <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
4 </filter>
5 <filter-mapping>
6 <filter-name>OpenSessionInViewFilter</filter-name>
7 <url-pattern>*.action</url-pattern>
8 </filter-mapping>

即可以实现延迟关闭session的功能。

四、js插件制作

 1 (function($){
 2         $.confirm = function(json){
 3             $("a").each(function(){
 4                 if($(this).text()=="删除"){
 5                     $(this).unbind("click");
 6                     $(this).bind("click",function(){
 7                         json.callback();
 8                         return window.confirm(json.message);
 9                     });
10                 }
11             });
12     }
13 })(&);

如上所述就可以制作出删除提示窗口插件

五、js面向对象写法
    分析所需要的方法的实现步骤,然后利用面向对象的方法将该需求进行分解,将该需求作为对象来对待,对其进行模块划分,一般涉及数据区,方法区两大类,最后在$().ready(function(){...});中进行调用该对象的相应方法完成相应的功能。

 1 var tree = {
 2     zTree: ‘‘,
 3     pNode: ‘‘,
 4     setting: {
 5         isSimpleData: true,
 6         treeNodeKey: "mid",
 7         treeNodeParentKey: "pid",
 8         showLine: true,
 9         root: {
10             isRoot: true,
11             nodes: []
12         },
13         callback: {
14             /**
15              * @param {Object} event
16              *     鼠标事件
17              * @param {Object} treeId
18              *     树的容器ID
19              * @param {Object} treeNode
20              *     当前点击的节点
21              */
22             expand: function(event, treeId, treeNode){
23                 tree.pNode = treeNode;
24                 tree.loadNodeByPNODE();
25             }
26         }
27     },
28     /**
29      * 1、回调函数是由服务器端触发的,什么时候执行由服务器决定
30      * 2、回调函数是由jQuery内核调用的
31      * 3、客户端存在两个线程
32      * 4、如果在js代码中,有一些代码要用到回调函数中的数据,那么这些代码必须放在回调函数中
33      */
34     loadTree: function(){
35         $.post("menuitemAction_getAllMenuitem.action", null, function(data){
36             $("#tree").zTree(tree.setting, data.menuitemList);
37         });
38     },
39     /**
40      * 一般情况下,如果一段代码中要用到一个变量,而这个变量的值是在回调函数中赋值的,这个时候一定要确保使用该函数时,回调函数已经执行了
41      */
42     loadRootNode: function(){
43         var parameter = {
44             pid: 0
45         };
46         $.post("menuitemAction_showMenuitemsByPid.action", parameter, function(data){
47             tree.zTree = $("#tree").zTree(tree.setting, data.menuitemList);
48         });
49     },
50     /**
51      * 该方法是在点击父节点的+号的时候执行的,这就意味着在执行该方法的时候,树早已经生成了,所以才能用tree.zTree;
52      */
53     loadNodeByPNODE: function(){
54         var parameter = {
55             pid: tree.pNode.mid
56         };
57         if (!tree.zTree.getNodeByParam("pid", tree.pNode.mid)) {
58             $.post("menuitemAction_showMenuitemsByPid.action", parameter, function(data){
59                 /**
60                  * 把查询出来的子节点追加到父节点上
61                  */
62                 tree.zTree.addNodes(tree.pNode, data.menuitemList, true);
63             });
64         }
65     }
66 };
67 $().ready(function(){
68     //tree.loadTree();
69     tree.loadRootNode();
70     //该方法能输出什么不确定:因为在执行该代码的时候,回调函数执行不确定,所以tree.zTree的赋值也不确定
71     //alert(tree.zTree);
72 });

上面就是在界面加载zTree的JS面向对象写法

六、通过泛型技术对Dao层和控制层的提取重构,提高代码的复用性;

1 public BaseDao<T>{
2         private Class classes;
3         public BaseDao(){
4             ParameterizedType parameterizedType  = (ParameterizedType)this.getClass().getGenericSuperclass();
5             this.classes = (Class) parameterizedType.getActualTypeArguments()[0];
6         }
7     }

七、用OGNL可以调用类的方法用于权限的设计
在实体User中有hasPrivilegeByName()方法用于判断用户的权限,则ognl可以直接调用该方法在页面中进行判断

1 <%-- 显示一级菜单 --%>
2 <s:if test="#session.user.hasPrivilegeByName(name)">
3 <li class="level1">
4 <div onClick="menuClick(this);" class="level1Style">
5 <img src="${pageContext.request.contextPath}/style/images/MenuIcon/${icon}" class="Icon" />
6 ${name}
7 </div>
8 </li>
9 </s>
时间: 2024-08-11 07:49:35

OA项目总结的相关文章

【Java EE 学习第58-67天】【OA项目练习】【JBPM工作流的使用】

OA项目中有极大可能性使用到JBPM框架解决流程控制问题,比如请假流程.报销流程等等. JBPM:JBoss Business Process Management,翻译过来就是业务流程管理.实际上就是一个java 框架. 学习JBPM最重要的就是学习数据库中的18张表,只要熟练掌握了这18张表,学习JBPM就大功告成了. 一.JBPM框架搭建 1.到JBPM官方网站上下载需要的jar包.源代码.文档等等 http://www.jbpm.org/ 比较流行的JBPM版本是JBPM4.4,本次使用

OA项目12:系统管理之用户管理

首注:本学习教程为传智播客汤阳光讲师所公布的免费OA项目视频我的文字版实践笔记,本人用此来加强巩固自己开发知识,如有网友转载,请注明.谢谢. 一 之前在第8节时已经将User实体及映射文件建立好了,所以设计实体已经完成了,下面来做功能了. 二 我们对照静态页面看用户管理页面分析发现,增删改查功能跟之前一样,多了一个初始化密码的请求.当然,这不是问题,下面开始做功能吧! 三 开发: 1.写action及struts2映射,具体如下: 1)UserAction.java: 1 package cn.

OA项目2:环境搭建之ssh框架整合

首注:本学习教程为传智播客汤阳光讲师所公布的免费OA项目视频的文字版,本人用此来加强巩固自己开发知识,如有网友转载,请注明.谢谢. 今天做Spring+Hibernate+Struts2整合. 一 Struts2与Spring的整合. 1.整合之前Struts2例子: 在src下建立一个包,包名为:cn.clear.oa.test,在包下面建立一个类TestAction.java,内容如下: 1 package cn.clear.oa.test; 2 3 import com.opensymph

[deviceone开发]-企业OA项目开源分享

一.简介 是一个真实的企业OA项目改造的开源项目,几乎涵盖了所有常用的组件,包括环信实现在线聊天等功能,类似微信的朋友圈功能,自定义的智能搜索等,而且这个是真实的通过Http链接后台web服务,里面很多地方都值得参考和学习. 二.效果图      三.相关下载 https://github.com/do-project/OA-Sample 四.相关讨论 http://bbs.deviceone.net/forum.php?mod=viewthread&tid=123 五.更多案例 http://

OA项目1:环境搭建之数据库创建与环境添加

首注:本学习教程为传智播客汤阳光讲师所公布的免费OA项目视频的文字版,本人用此来加强巩固自己开发知识,如有网友转载,请注明.谢谢. 一   指定数据库:Mysql database:oa 建库语句:create database oa default character set utf8 二   指定ide开发工具:MyEclipse 项目名称:新建web工程,名字为:OA,并设置项目工程编码:utf-8 环境所用主要技术框架:JUnit4,Struts2.3.15.1,Hibernate3.6

OA项目15:权限管理实体设计及映射

首注:本学习教程为传智播客汤阳光讲师所公布的免费OA项目视频我的文字版实践笔记,本人用此来加强巩固自己开发知识,如有网友转载,请注明.谢谢. 一 实体设计: 1.权限实体设计: 1)属性设计: 主键:id 关联属性:Set<Role> roles,Set<Privilege> privileges,Privilege parent,Set<Privilege> children 一般属性:name,url 特殊属性:暂无 2)涉及到3个实体:User(用户),Role(

OA项目4:BaseDao设计

首注:本学习教程为传智播客汤阳光讲师所公布的免费OA项目视频的文字版,本人用此来加强巩固自己开发知识,如有网友转载,请注明.谢谢. 一 为什么要设计BaseDao? 为了减少代码量,用最少的代码实现最多的功能. 二 建立一个cn.clear.oa.base包,在包下写一个接口类,有最基本的增删改查功能,具体内容如下: 1 package cn.clear.oa.base; 2 3 import java.util.List; 4 5 public interface BaseDao<T> {

OA项目3:其他配置

首注:本学习教程为传智播客汤阳光讲师所公布的免费OA项目视频的文字版,本人用此来加强巩固自己开发知识,如有网友转载,请注明.谢谢. 一 资源分类 源码包,文件等资源的分类如下图所示: 注:其中cn.clear.oa.dao与cn.clear.oa.service跟其实现类层是分开的,上图只展现了实现类层的分类,展开的源码分类应类似如下图: 二 log4j日志配置: 加入slf4j-api-1.5.0.jar与slf4j-log4j12-1.5.0.jar包,并且在config源码包下加入log4

jbpm与OA项目-oa概念

oa: *  控制商业流程按照指定的路线进行 *  在工作流程中,会产生很多数据,我们会对数据做进一步的分析,从而得出一些结论 智能分析: 从大量的数据中经过滤过.分析,得出很有用的数据,供决策和参考-->产品经理 数据挖掘: 更深层次的数据分析 协同: 好几个部门在一起,共同完成一件事情的过程 整个过程是一个比较大的工作流,得对细节做更精细的控制,这个时候要用到工作流框架 jbpm与OA项目-oa概念

OA项目11:部门列表树状显示功能及其他代码优化

首注:本学习教程为传智播客汤阳光讲师所公布的免费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.clea