1.数据回现:
不论什么回显只需在跳转页面时,传递属性值即可
2.设置级联操作:如:删除顶级部门时,删除所有子部门
casecade:根据需要设置
3.查找顶级部门,查找子部门
1)("from Department d where d.parent is NULL").list
2)("from Department d where d.parent.id=?").setParameter(0,parentId).list
4.OGNL表达式
1)判断:userAction_%{id==null? 'add':'edit'}
2)获取数组某个值如:%{#departmentList[0].parent.id}
5.树状结构
1)工具类:
-------------------------------------------------------------------------------
/**
* 遍历部门树,得到所有的部门列表,并修改了名称以表示层次。
*
* @param topList
* @return
*/
public static List<Department> getAllDepartments(List<Department> topList) {
List<Department> list = new ArrayList<Department>();
walkDepartmentTrees(topList, "┣", list);
return list;
}
/*
* 遍历部门树,把遍历出来的部门都放到指定的集合中
*/
private static void walkDepartmentTrees(Collection<Department> topList, String prefix, List<Department> list) {
for (Department top : topList) {
// 顶点
Department copy = new Department(); // 原对象是在Session中的对象,是持久化状态,所以要使用副本。
copy.setId(top.getId());
copy.setName(prefix + top.getName());
list.add(copy);
// 子树
walkDepartmentTrees(top.getChildren(), " " + prefix, list); // 使用的是全角的空格
}
}
-------------------------------------------------------------------------------------
2)配置子部门排序:
<set name="children" sort="unsorted" cascade="delete" order-by="id">
========================================================================================================
6.登陆权限的实现:
思路:
1)创建监听器继承ServletContextListener接口,监听服务器容器的创建销毁
2)在init中获取所有的权限信息,放入application作用域
3)在页面进行权限的判断显示(主菜单)
1.建立用户===角色===权限的多对多关系,创建表,映射
2.初始化权限数据,初始化超级管理员 MD5加密的使用:DigestUtils.md5Hex("admin")
3.设置权限树(权限管理)的显示及效果 roleAction/setPrivilegeUI.jsp
4. 1)创建监听器继承ServletContextListener接口,监听服务器容器的创建销毁
2)在init中获取所有的权限信息,放入application作用域
----------------------------------------------------------------------
public void contextInitialized(ServletContextEvent sce) {
ServletContext application=sce.getServletContext();
//得到service的对象实例
ApplicationContext ac=WebApplicationContextUtils.getWebApplicationContext(application);
PrivilegeService privilegeService=(PrivilegeService) ac.getBean("privilegeServiceImpl");
//准备所有顶级权限的集合(顶级菜单)
List<Privilege> topPrivilegeList=privilegeService.findTopList();
application.setAttribute("topPrivilegeList", topPrivilegeList);
System.out.println("------已准备好顶级权限的数据----------");
//准备所有权限的url集合(用于拦截器中权限的判断,防止用户手工输入地址)
List<String> allPrivilegeUrls=privilegeService.getAllPrivilegeUrls();
application.setAttribute("allPrivilegeUrls",allPrivilegeUrls);
System.out.println("------已准备好所有权限的url数据");
}
----------------------------------------------------------------------
3)在页面进行权限的判断显示(主菜单)
①懒加载异常的处理
将所有相关联的数据(role,user,privilege):lazy="false"
①核心代码:
页面: homeAction/left.jsp
-----------------------------------------------------------------------
<ul id="MenuUl">
<%-- 顶级菜单 --%>
<s:iterator value="#application.topPrivilegeList">
☆ <s:if test="#session.user.hasPrivilegeByName(name)">
<li class="level1">
<div onClick="menuClick(this);" class="level1Style">
<img src="style/images/MenuIcon/${icon}" class="Icon" />
${name}
</div>
<%-- 二级菜单 display: none; --%>
<ul style="" class="MenuLevel2">
<s:iterator value="children">
<s:if test="#session.user.hasPrivilegeByName(name)">
<li class="level2">
<div class="level2Style">
<img src="style/images/MenuIcon/menu_arrow_single.gif" />
<a target="right" href="${pageContext.request.contextPath}/${url}.action"> ${name}</a>
</div>
</li>
</s:if>
</s:iterator>
</ul>
</li>
</s:if>
</s:iterator>
</ul>
-------------------------------------------------------------------------------------------------------
后台: domian/user.hasPrivilegeByName
public boolean hasPrivilegeByName(String privilegeName){
//超级管理员有所有的权限
if(isAdmin()){
return true;
}
//一般用户有权限才返回true
for(Role role:roles){
for(Privilege privilege:role.getPrivileges()){
if(privilege.getName().equals(privilegeName)){
return true;
}
}
}
return false;
}
---------------------------------------------------------------------------------------------------------
5.进行三级菜单的判断显示(方案:重写<s:a>的doendTag方法)
1)重写类 org/apache/struts2/views/jsp/ui/AnchorTag.java
2)重写方法
--------------------------------------------------------------------------------------------------
public int doEndTag() throws JspException {
//获取当前用户
User user= (User) pageContext.getSession().getAttribute("user");
//获取当前url 如果有参数就要去掉后面的参数字符串
String privilegeUrl=action;
System.out.println(action+"----------------------------");
int pos=privilegeUrl.indexOf("?");
if(pos>-1){
privilegeUrl=privilegeUrl.substring(0,pos);
}
if(user.hasPrivilegeByUrl(privilegeUrl)){
//如果有权限则正常的生成与输出a标签
return super.doEndTag();
}else{
//没有权限不显示任何东西,继续执行页面中后面的代码
return EVAL_PAGE;
}
}
---------------------------------------------------------------------------------------------------
6.配建登陆拦截器实现intercepter接口,进行登陆拦截判断(判断用户是否登陆,防止用户直接输入地址)
1)在监听器中,将所有的权限url放入application中(不包含null(主菜单)和重复的)
2)在拦截器中判断用户: 类:CheckPrivilegeInterceptor
1.是否已经登陆,及是否正要去登陆
2.判断已登陆用户的权限(从url集合中排除公共权限,如:注销,登陆) 方法:user.hasPrivilegeByUrl();
---------------------------------------------------------------------------------------------------------------
public class CheckPrivilegeInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception {
//获取当前用户
User user=(User) ActionContext.getContext().getSession().get("user");
//获取当前访问的url,并去掉当前应用 的前缀(也就是nameSpace+actionName)
String privilegeUrl=null;
String namespace=invocation.getProxy().getNamespace();
String actionName=invocation.getProxy().getActionName();
if(namespace.endsWith("/")){
privilegeUrl=namespace+actionName;
}else{
privilegeUrl=namespace+"/"+actionName;
}
//去掉开头的‘/’
if(privilegeUrl.startsWith("/")){
privilegeUrl=privilegeUrl.substring(1);
}
//如果未登陆用户
if(user==null){
if(privilegeUrl.startsWith("userAction_login")){
//如果是去登陆,则放行
return invocation.invoke();
}else{
//如果不是去登陆,就转到登陆界面
return "loginUI";
}
}else{
//如果已经登陆,则判断权限
if(user.hasPrivilegeByUrl(privilegeUrl)){
//如果有权限就放行
return invocation.invoke();
}else{
//如果没有就转到提示页面
return "noPrivilegeError";
}
}
}
}
--------------------------------------------------------------------------------------------------------
public boolean hasPrivilegeByUrl(String privilegeUrl) {
// 超级管理员有所有的权限
if (isAdmin()) {
return true;
}
// 如果以UI后缀结尾,就去掉UI后缀,以得到对应的权限(例如:addUI与add是同一个权限)
if (privilegeUrl.endsWith("UI")) {
privilegeUrl = privilegeUrl.substring(0, privilegeUrl.length() - 2);
}
//取出数据库中所有的权限url
List<String> allPrivilegeUrls=(List<String>) ActionContext.getContext().getApplication().get("allPrivilegeUrls");
if(!allPrivilegeUrls.contains(privilegeUrl)){
//设置不需要控制的功能,权限 如:userAction_loginUI/login/homeAction_index
return true;
}else{
//要控制的功能
// 其他用户要是有权限才返回true
for (Role role : roles) {
for (Privilege privilege : role.getPrivileges()) {
if (privilegeUrl.equals(privilege.getUrl())) {
return true;
}
}
}
}
return false;
}
================================================================================================================
7.细节处理:
1) 解决服务器重启session失效问题 : 序列化 implements Serializable
2)session过期导致登陆页面层叠嵌套问题 : 刷新上级窗口
if (window.parent != window) {
window.parent.location.reload(true);
}