一、自定义拦截器:
继承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>
八、适配器设计模式
1 public interface UserService extends BaseService{ 2 3 public void geT(); 4 5 public void getUserById(); 6 }
1 public UserServiceImple exends BaseServiceimpl implements UserService{ 2 public User getUserById(){} 3 }
1 public BaseServiceImpl implements BaseService{ 2 public T getT(){} 3 }
其中UserServiceImpl充当了适配器的角色,用来提供Userservice中所需要而BaseService中没有的方法