OA项目总结

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

 <!-- 配置拦截器 -->
<interceptors>
<interceptor name="cusInterceptor" class="com.swust.interceptor.CusInterceptor"/>
<!-- 声明拦截器栈 -->
<interceptor-stack name="myStack">
<interceptor-ref name="cusInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>

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

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

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

 package com.swust.oa.interceptor;

 import com.swust.oa.domain.User;
import com.swust.oa.struts2.action.LoginLogoutAction; import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor; @SuppressWarnings("serial")
public class CheckPrivilegeInterceptor extends AbstractInterceptor { public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("CheckPrivilegeInterceptor.intercept()"); // 获取当前的登录用户
User user = (User) ActionContext.getContext().getSession().get("user");
// 获取当前访问的URL(action的名称),需要处理一下UI后缀
String url = invocation.getProxy().getActionName();
if (url.endsWith("UI")) {
url = url.substring(0, url.length() - 2);
}
// 一、未登录的情况
if (user == null) {
if (invocation.getProxy().getAction() instanceof LoginLogoutAction) {
// 如果正在使用登录用功能,则放行
return invocation.invoke(); // 放行
} else {
// 如果不是正在使用登录功能,则转到登录页面
return "loginUI";
}
}
// 二、已登录的情况
else {
if (user.hasPrivilegeByUrl(url)) {
// 如果有权限,则放行
return invocation.invoke(); // 放行
} else {
// 如果没有有权,则转到错误页面
return "privilegeError";
}
}
}
}

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

 package org.apache.struts2.views.jsp.ui;

 import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException; import org.apache.struts2.components.Anchor;
import org.apache.struts2.components.Component; import com.swust.oa.domain.User; import com.opensymphony.xwork2.util.ValueStack; /**
* @see Anchor
*/
public class AnchorTag extends AbstractClosingTag { private static final long serialVersionUID = -1034616578492431113L; protected String href;
protected String includeParams;
protected String scheme;
protected String action;
protected String namespace;
protected String method;
protected String encode;
protected String includeContext;
protected String escapeAmp;
protected String portletMode;
protected String windowState;
protected String portletUrlType;
protected String anchor;
protected String forceAddSchemeHostAndPort; @Override
public int doEndTag() throws JspException {
// 获取当前登录用户
User user = (User) pageContext.getSession().getAttribute("user");
// 获取当前访问的URL(actionName),就是本类的action属性值
// >> 去掉参数
String url = action;
int pos = url.indexOf('?');
if (pos > -1) {
url = url.substring(0, pos); // 去掉参数
}
// >> 去掉UI后缀(例:userAction_addUI就是userAction_add权限)
if (url.endsWith("UI")) {
url = url.substring(0, url.length() - 2);
} if (user.hasPrivilegeByUrl(url)) {
return super.doEndTag(); // 正常显示超链接标签,并继续执行后面的内容
} else {
return EVAL_PAGE; // 不显示当前的超链接标签,只继续执行后面的内容
}
} public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
return new Anchor(stack, req, res);
} protected void populateParams() {
super.populateParams(); Anchor tag = (Anchor) component;
tag.setHref(href);
tag.setIncludeParams(includeParams);
tag.setScheme(scheme);
tag.setValue(value);
tag.setMethod(method);
tag.setNamespace(namespace);
tag.setAction(action);
tag.setPortletMode(portletMode);
tag.setPortletUrlType(portletUrlType);
tag.setWindowState(windowState);
tag.setAnchor(anchor); if (encode != null) {
tag.setEncode(Boolean.valueOf(encode).booleanValue());
}
if (includeContext != null) {
tag.setIncludeContext(Boolean.valueOf(includeContext).booleanValue());
}
if (escapeAmp != null) {
tag.setEscapeAmp(Boolean.valueOf(escapeAmp).booleanValue());
}
if (forceAddSchemeHostAndPort != null) {
tag.setForceAddSchemeHostAndPort(Boolean.valueOf(forceAddSchemeHostAndPort).booleanValue());
}
} public void setHref(String href) {
this.href = href;
} public void setEncode(String encode) {
this.encode = encode;
} public void setIncludeContext(String includeContext) {
this.includeContext = includeContext;
} public void setEscapeAmp(String escapeAmp) {
this.escapeAmp = escapeAmp;
} public void setIncludeParams(String name) {
includeParams = name;
} public void setAction(String action) {
this.action = action;
} public void setNamespace(String namespace) {
this.namespace = namespace;
} public void setMethod(String method) {
this.method = method;
} public void setScheme(String scheme) {
this.scheme = scheme;
} public void setValue(String value) {
this.value = value;
} public void setPortletMode(String portletMode) {
this.portletMode = portletMode;
} public void setPortletUrlType(String portletUrlType) {
this.portletUrlType = portletUrlType;
} public void setWindowState(String windowState) {
this.windowState = windowState;
} public void setAnchor(String anchor) {
this.anchor = anchor;
} public void setForceAddSchemeHostAndPort(String forceAddSchemeHostAndPort) {
this.forceAddSchemeHostAndPort = forceAddSchemeHostAndPort;
}
}

三、懒加载

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

 <filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>

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

四、js插件制作

 (function($){
$.confirm = function(json){
$("a").each(function(){
if($(this).text()=="删除"){
$(this).unbind("click");
$(this).bind("click",function(){
json.callback();
return window.confirm(json.message);
});
}
});
}
})(&);

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

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

 var tree = {
zTree: '',
pNode: '',
setting: {
isSimpleData: true,
treeNodeKey: "mid",
treeNodeParentKey: "pid",
showLine: true,
root: {
isRoot: true,
nodes: []
},
callback: {
/**
* @param {Object} event
* 鼠标事件
* @param {Object} treeId
* 树的容器ID
* @param {Object} treeNode
* 当前点击的节点
*/
expand: function(event, treeId, treeNode){
tree.pNode = treeNode;
tree.loadNodeByPNODE();
}
}
},
/**
* 1、回调函数是由服务器端触发的,什么时候执行由服务器决定
* 2、回调函数是由jQuery内核调用的
* 3、客户端存在两个线程
* 4、如果在js代码中,有一些代码要用到回调函数中的数据,那么这些代码必须放在回调函数中
*/
loadTree: function(){
$.post("menuitemAction_getAllMenuitem.action", null, function(data){
$("#tree").zTree(tree.setting, data.menuitemList);
});
},
/**
* 一般情况下,如果一段代码中要用到一个变量,而这个变量的值是在回调函数中赋值的,这个时候一定要确保使用该函数时,回调函数已经执行了
*/
loadRootNode: function(){
var parameter = {
pid: 0
};
$.post("menuitemAction_showMenuitemsByPid.action", parameter, function(data){
tree.zTree = $("#tree").zTree(tree.setting, data.menuitemList);
});
},
/**
* 该方法是在点击父节点的+号的时候执行的,这就意味着在执行该方法的时候,树早已经生成了,所以才能用tree.zTree;
*/
loadNodeByPNODE: function(){
var parameter = {
pid: tree.pNode.mid
};
if (!tree.zTree.getNodeByParam("pid", tree.pNode.mid)) {
$.post("menuitemAction_showMenuitemsByPid.action", parameter, function(data){
/**
* 把查询出来的子节点追加到父节点上
*/
tree.zTree.addNodes(tree.pNode, data.menuitemList, true);
});
}
}
};
$().ready(function(){
//tree.loadTree();
tree.loadRootNode();
//该方法能输出什么不确定:因为在执行该代码的时候,回调函数执行不确定,所以tree.zTree的赋值也不确定
//alert(tree.zTree);
});

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

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

 public BaseDao<T>{
private Class classes;
public BaseDao(){
ParameterizedType parameterizedType = (ParameterizedType)this.getClass().getGenericSuperclass();
this.classes = (Class) parameterizedType.getActualTypeArguments()[0];
}
}

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

 <%-- 显示一级菜单 --%>
<s:if test="#session.user.hasPrivilegeByName(name)">
<li class="level1">
<div onClick="menuClick(this);" class="level1Style">
<img src="${pageContext.request.contextPath}/style/images/MenuIcon/${icon}" class="Icon" />
${name}
</div>
</li>
</s>

八、适配器设计模式

 public interface UserService extends BaseService{

     public void geT(); 

     public void getUserById();
}
 public UserServiceImple exends BaseServiceimpl implements UserService{
public User getUserById(){}
}
 public BaseServiceImpl implements BaseService{
public T getT(){}
}

其中UserServiceImpl充当了适配器的角色,用来提供Userservice中所需要而BaseService中没有的方法

上一篇:c语言基础数据类型及命名规范


下一篇:Spark核心RDD:combineByKey函数详解