Day04系统权限

  1. 介绍

在Web应用中,控制权限就是控制URL的访问。

  • 实现步骤:

超级管理员:登录名为admin,有所有的权限,他的权限不需要分配,也不能取消。

二.初始化数据

  • 创建JavaBean:

实体类图:

Privilege.java:

package cn.itcast.oa.domain;

import java.util.HashSet;

import java.util.Set;

/*

* 实体:权限

*/

public class Privilege {

 

    private Long id;

    private String url;

    private String name;

    

    private Set<Role> roles = new HashSet<Role>();     //权限与角色        多对多

    

    private Privilege parent;     //子权限与父权限 多对一

    private Set<Privilege> children = new HashSet<Privilege>();    //父权限与子权限 一对多

    

    public Privilege(String name, String url, Privilege parent) {

        this.name = name;

        this.url = url;

        this.parent = parent;

    }

    

    public Privilege() {

    }

    

    public Long getId() {

        return id;

    }

    public void setId(Long id) {

        this.id = id;

    }

    public String getUrl() {

        return url;

    }

    public void setUrl(String url) {

        this.url = url;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public Set<Role> getRoles() {

        return roles;

    }

    public void setRoles(Set<Role> roles) {

        this.roles = roles;

    }

    public Privilege getParent() {

        return parent;

    }

    public void setParent(Privilege parent) {

        this.parent = parent;

    }

    public Set<Privilege> getChildren() {

        return children;

    }

    public void setChildren(Set<Privilege> children) {

        this.children = children;

    }

}

Tips:

set集合要new,因为他的getRoles方法要返回一个空的集合而不是null,这样可以避免很多空指针异常.而parent对象不能new,关联一个对象,你要new一个对象的话,就只有一个关联的,而集合不同.关联的不是集合而是集合中的多个元素,集合只是一个容器所以集合这个容器可以有,但里面不能有对象.

Role.java:(要新增下面这条代码,还要加上get,set方法)

private Set<Privilege> privileges = new HashSet<Privilege>();    //角色与权限 多对多

Privilege.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cn.itcast.oa.domain">

<class name="Privilege" table="itcast_privilege">

<id name="id">

<generator class="native"></generator>

</id>

 

<property name="url" column="url"></property>

<property name="name" column="name"></property>

 

<!-- parent属性,表达的是本对象与Privilege(parent)的多对一关系 -->

<many-to-one name="parent" class="Privilege" column="parentId"></many-to-one>

 

<!-- children属性,表达的是本对象与Privilege(children)的一对多关系 -->

<set name="children">

    <key column="parentId"></key>

    <one-to-many class="Privilege"/>

</set>

 

<!-- roles属性,表达的是本对象与Role的多对多关系 -->

<set name="roles" table="itcast_role_privilege">

    <key column="privilegeId"></key>

    <many-to-many class="Role" column="roleId"></many-to-many>

</set>

 

</class>

</hibernate-mapping>

Role.hbm.xml:(要新增以下这些代码)

<!-- privileges属性,表达的是本对象与Privilege的多对多关系 -->

<set name="privileges" table="itcast_role_privilege">

    <key column="roleId"></key>

    <many-to-many class="Privilege" column="privilegeId"></many-to-many>

</set>

Hibernate.cfg.xml:

<mapping resource="cn/itcast/oa/domain/Privilege.hbm.xml"/>

最后测试一下即可:

TestSpring:

package cn.itcast.oa.test;

 

import org.hibernate.SessionFactory;

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

public class TestSpring {

    

    private ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

    

    //测试SessionFactory

    @Test

    public void testSessionFactory() throws Exception{

        SessionFactory sf = (SessionFactory) ac.getBean("sessionFactory");

        System.out.println(sf.openSession());

    }

    

    //测试事务管理

    @Test

    public void testTx() throws Exception{

        TestService testService = (TestService) ac.getBean("testService");

        testService.saveTwoUsers();

    }

    

    //测试Action对象的管理

    @Test

    public void testAction() throws Exception{

        TestAction testAction = (TestAction) ac.getBean("testAction");

        System.out.println(testAction);

    }

}

 

  • 初始化类:

    Installer:

    package cn.itcast.oa.installer;

     

    import javax.annotation.Resource;

     

    import org.apache.commons.codec.digest.DigestUtils;

    import org.hibernate.SessionFactory;

    import org.hibernate.classic.Session;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.ClassPathXmlApplicationContext;

    import org.springframework.stereotype.Component;

    import org.springframework.transaction.annotation.Transactional;

     

    import cn.itcast.oa.domain.Privilege;

    import cn.itcast.oa.domain.User;

     

    @Component

    @SuppressWarnings("unused")

    public class Installer {

     

        @Resource

        private SessionFactory sessionFactory;

     

        @Transactional

        public void install() {

            Session session = sessionFactory.getCurrentSession();

     

            // ================================

            // 1.超级管理员

            User user = new User();

            user.setLoginName("admin");

            user.setName("超级管理员");

            user.setPassword(DigestUtils.md5Hex("admin")); // 密码要使用MD5摘要

            session.save(user); // 保存

     

            // 2.权限数据

            Privilege menu, menu1, menu2, menu3, menu4, menu5;

     

            menu = new Privilege("系统管理", null, null);

            menu1 = new Privilege("岗位管理", "/role_list", menu);

            menu2 = new Privilege("部门管理", "/department_list", menu);

            menu3 = new Privilege("用户管理", "/user_list", menu);

     

            session.save(menu);

            session.save(menu1);

            session.save(menu2);

            session.save(menu3);

     

            session.save(new Privilege("岗位列表", "/role_list", menu1));

            session.save(new Privilege("岗位删除", "/role_delete", menu1));

            session.save(new Privilege("岗位添加", "/role_add", menu1));

            session.save(new Privilege("岗位修改", "/role_edit", menu1));

     

            session.save(new Privilege("部门列表", "/department_list", menu2));

            session.save(new Privilege("部门删除", "/department_delete", menu2));

            session.save(new Privilege("部门添加", "/department_add", menu2));

            session.save(new Privilege("部门修改", "/department_edit", menu2));

     

            session.save(new Privilege("用户列表", "/user_list", menu3));

            session.save(new Privilege("用户删除", "/user_delete", menu3));

            session.save(new Privilege("用户添加", "/user_add", menu3));

            session.save(new Privilege("用户修改", "/user_edit", menu3));

            session.save(new Privilege("用户初始化密码", "/user_initPassword", menu3));

     

            // ------

     

            menu = new Privilege("网上交流", null, null);

            menu1 = new Privilege("论坛管理", "/forumManage_list", menu);

            menu2 = new Privilege("论坛", "/forum_list", menu);

     

            session.save(menu);

            session.save(menu1);

            session.save(menu2);

     

            // ------

     

            menu = new Privilege("审批流转", null, null);

            menu1 = new Privilege("审批流程管理", "/processDefinition_List", menu);

            menu2 = new Privilege("申请模板管理", "/template_List", menu);

            menu3 = new Privilege("起草申请", "/flow_templateList", menu);

            menu4 = new Privilege("待我审批", "/flow_myTaskList", menu);

            menu5 = new Privilege("我的申请查询", "/flow_myApplicationList", menu);

     

            session.save(menu);

            session.save(menu1);

            session.save(menu2);

            session.save(menu3);

            session.save(menu4);

            session.save(menu5);

     

        }

     

        public static void main(String[] args) {

            System.out.println("正在初始化数据...");

     

            // 一定要从spring容器中取出对象

            ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

            Installer installer = (Installer) ac.getBean("installer");

            // 执行安装

            installer.install();

     

            System.out.println("数据初始化完成!");

        }

    }

    Tips:运行main方法即可初始化数据,运行一次即可.之前已经在Privilege.java中添加了无参和有参构造.这里有参构造的参数没写id和children,是因为,不写id也会自动生成.这里初始化的目的是为了将这些权限数据存入数据库中,而parent和children有关联,存了其中一个,另一个也相当于存进去了.

public Privilege() {

    }

public Privilege(String name, String url, Privilege parent) {

        this.name = name;

        this.url = url;

        this.parent = parent;

    }    

三.分配权限

1.先把所有权限展示出来,并实现回显功能,还未实现树状结构效果.

权限是在岗位列表页面的:

所以关于权限的代码要加到RoleAction中,

RoleAction:

@Controller

@Scope("prototype")

public class RoleAction extends BaseAction<Role>{

    

    Long[] privilegeIds;

 

    

    /**

     * 设置权限页面

     */

    public String setPrivilegeUI() throws Exception {

        //准备要回显的数据

        Role role = roleService.getById(model.getId());

        ActionContext.getContext().getValueStack().push(role);

        

        privilegeIds = new Long[ role.getPrivileges().size() ];

        int index = 0;

        for (Privilege p : role.getPrivileges()) {

            privilegeIds[ index++ ] = p.getId();

        }

        

        //准备数据

        List<Privilege> privilegeList = privilegeService.findAll();

        ActionContext.getContext().put("privilegeList", privilegeList);

        

        return "setPrivilegeUI";

    }

    

    /**

     * 设置权限

     */

    public String setPrivilege() throws Exception {

        //从数据库中获取要修改的原始数据

        Role role = roleService.getById(model.getId());

        

        //设置要修改的属性

        List<Privilege> privilegeList = privilegeService.getByIds(privilegeIds);

        role.setPrivileges(new HashSet<Privilege>(privilegeList));

        

        //保存到数据库

        roleService.update(role);

        

        return "toList";

    }

 

    public Long[] getPrivilegeIds() {

        return privilegeIds;

    }

 

    public void setPrivilegeIds(Long[] privilegeIds) {

        this.privilegeIds = privilegeIds;

    }

 

}

Strurs.xml:

<!-- 岗位管理 -->

    <action name="role_*" class="roleAction" method="{1}">

        <result name="setPrivilegeUI">/WEB-INF/jsp/roleAction/setPrivilegeUI.jsp</result>

……

    </action>

修改list中设置权限的链接:

    <s:a action="role_setPrivilegeUI?id=%{id}">设置权限</s:a>

setPrivilegeUI.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html>

<head>

<title>配置权限</title>

<%@include file="/WEB-INF/jsp/public/header.jspf" %>

    <script language="javascript" src="${pageContext.request.contextPath}/script/jquery_treeview/jquery.treeview.js"></script>

    <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/style/blue/file.css" />

    <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/script/jquery_treeview/jquery.treeview.css" />

 

</head>

<body>

 

<!-- 标题显示 -->

<div id="Title_bar">

<div id="Title_bar_Head">

<div id="Title_Head"></div>

<div id="Title"><!--页面标题-->

<img border="0" width="13" height="13" src="${pageContext.request.contextPath}/style/images/title_arrow.gif"/> 配置权限

</div>

<div id="Title_End"></div>

</div>

</div>

 

<!--显示表单内容-->

<div id=MainArea>

<s:form action="role_setPrivilege">

    <s:hidden name="id"></s:hidden>

<div class="ItemBlock_Title1"><!-- 信息说明 --><div class="ItemBlock_Title1">

    <img border="0" width="4" height="7" src="${pageContext.request.contextPath}/style/blue/images/item_point.gif" /> 正在为${name }配置权限 </div>

</div>

 

<!-- 表单内容显示 -->

<div class="ItemBlockBorder">

<div class="ItemBlock">

<table cellpadding="0" cellspacing="0" class="mainForm">

                    <!--表头-->

                    <thead>

                        <tr align="LEFT" valign="MIDDLE" id="TableTitle">

                            <td width="300px" style="padding-left: 7px;">

                                <!-- 如果把全选元素的id指定为selectAll,并且有函数selectAll(),就会有错。因为有一种用法:可以直接用id引用元素 -->

                                <input type="CHECKBOX" id="cbSelectAll" onClick="selectAll(this.checked)"/>

                                <label for="cbSelectAll">全选</label>

                            </td>

                        </tr>

                    </thead>

 

                     <!--显示数据列表-->

                    <tbody id="TableData">

                        <tr class="TableDetail1">

                            <!-- 显示权限树 -->

                            <td>

                            <s:checkboxlist list="privilegeList" name="privilegeIds" listKey="id" listValue="name">

                            </s:checkboxlist>

                            </td>

                        </tr>

                    </tbody>

</table>

</div>

</div>

 

<!-- 表单操作 -->

<div id="InputDetailBar">

<input type="image" src="${pageContext.request.contextPath}/style/images/save.png"/>

<a href="javascript:history.go(-1);"><img src="${pageContext.request.contextPath}/style/images/goBack.png"/></a>

</div>

</s:form>

</div>

 

<div class="Description">

    说明:<br />

    1,选中一个权限时:<br />

    &nbsp;&nbsp;&nbsp;&nbsp; a,应该选中 他的所有直系上级。<br />

    &nbsp;&nbsp;&nbsp;&nbsp; b,应该选中他的所有直系下级。<br />

    2,取消选择一个权限时:<br />

    &nbsp;&nbsp;&nbsp;&nbsp; a,应该取消选择 他的所有直系下级。<br />

    &nbsp;&nbsp;&nbsp;&nbsp; b,如果同级的权限都是未选择状态,就应该取消选中他的直接上级,并递归向上做这个操作。<br />

 

    3,全选/取消全选。<br />

    4,默认选中当前岗位已有的权限。<br />

</div>

 

</body>

</html>

Tips:

  1. 还是回显的问题.不一定要求数据库表中有privilegeIds字段,只要action中以属性驱动封装的属性,其属性名与下拉选,复选框等中的name值对应即可.如:

RoleAction:

Long[] privilegeIds;    

public Long[] getPrivilegeIds() {

        return privilegeIds;

    }

 

    public void setPrivilegeIds(Long[] privilegeIds) {

        this.privilegeIds = privilegeIds;

    }

<s:checkboxlist list="privilegeList" name="privilegeIds" listKey="id" listValue="name"></s:checkboxlist>

  1. 接收从页面传过来的多个id值时,通用办法:

Long[] privilegeIds;    

public Long[] getPrivilegeIds() {

        return privilegeIds;

    }

 

    public void setPrivilegeIds(Long[] privilegeIds) {

        this.privilegeIds = privilegeIds;

    }

  1. ……
  2. /**
  3.      * 设置权限页面
  4.      */
  5.     public String setPrivilegeUI() throws Exception {
  6.         //准备要回显的数据
  7.         Role role = roleService.getById(model.getId());
  8.         ActionContext.getContext().getValueStack().push(role);
  9.         
  10.         privilegeIds = new Long[ role.getPrivileges().size() ];
  11.         int index = 0;
  12.         for (Privilege p : role.getPrivileges()) {
  13.             privilegeIds[ index++ ] = p.getId();
  14.         }
  15.         
  16.         //准备数据
  17.         List<Privilege> privilegeList = privilegeService.findAll();
  18.         ActionContext.getContext().put("privilegeList", privilegeList);
  19.         
  20.         return "setPrivilegeUI";
  21.     }

这里接收privilegeIds是为了实现页面的回显效果.

 

3. Struts2的复选框标签(跟下拉选差不多):

<s:checkboxlist list="privilegeList" name="privilegeIds" listKey="id" listValue="name"></s:checkboxlist>

页面效果:

4. action中的setPrivilege()方法需要根据id查询对象,

而提交给他的表单是来自setPrivilegeUI.jsp,故其表单中必须要将id提交过去,


不然会报空指针异常.

 

 

其他操作:

创建service,不要忘了将service放入容器中.

PrivilegeServiceImpl:

@Service

@Transactional

public class PrivilegeServiceImpl extends DaoSupportImpl<Privilege> implements PrivilegeService{

 

}

在BaseAction中注入PrivilegeService.

    @Resource

    protected PrivilegeService privilegeService;

2.实现页面中的树状结构展示:

  1. 实现简单的树状结构展示: ( 利用jquery_treeview (jquery中的某个文件夹) 完成)

    自己写个简单的html文件(放到jquery_treeview文件夹中):

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

    <html>

        <head>

            <title>Blank</title>

            <meta http-equiv="content-type" content="text/html; charset=UTF-8">

            

            <!-- 1,导入js与css文件 -->

            <script type="text/javascript" src="lib/jquery.js"></script>

            <script type="text/javascript" src="jquery.treeview.js"></script>

            <link rel="stylesheet" type="text/css" href="jquery.treeview.css">    

        </head>

     

        <body>

     

            <!-- 2,使用UL显示数据 -->

            <ul id="root">

                <li>系统管理

                    <ul>

                        <li>岗位管理</li>

                        <li>部门管理

                            <ul>

                                <li>aaa</li>

                                <li>bbb</li>

                            </ul>

                        </li>

                        <li>用户管理</li>

                    </ul>

                </li>

                <li>网上交流</li>

            </ul>

            

            <!-- 3.显示为树状结构 -->

            <script type="text/javascript">

                $("#root").treeview();

            </script>

        </body>

    </html>

    效果如图:

    总结:实现树状结构展示的步骤:

    1. 导入js与css文件

    <script type="text/javascript" src="lib/jquery.js"></script>

            <script type="text/javascript" src="jquery.treeview.js"></script>

            <link rel="stylesheet" type="text/css" href="jquery.treeview.css">

    (路径可能不一样,但要导入的文件是一样的)

    1. 使用UL显示数据

    3.显示为树状结构

        <script type="text/javascript">

            $("#root").treeview();

            </script>

    (root为ul的id)

     

  2. 之前在setPrivilegeUI.jsp中是利用Struts的复选框标签来展示所有权限的,

    <s:checkboxlist list="privilegeList" name="privilegeIds" listKey="id" listValue="name"></s:checkboxlist>

     

    使用Struts2的标签显示复选框,虽然有回显功能,但不方便修改显示效果。

     

    所以我们选择使用循环来显示复选框,但需要自己实现回显功能.

    setPrivilegeUI.jsp:

                        <tbody id="TableData">

                            <tr class="TableDetail1">

                                <!-- 显示权限树 -->

                                <!-- 使用struts2的标签来显示复选框,虽然有回显功能,但不方便修改显示效果. -->

                                <%--<td><s:checkboxlist list="privilegeList"

                                        name="privilegeIds" listKey="id" listValue="name">

                                    </s:checkboxlist>

                                </td> --%>

                                

                                <!-- 所以我们选择使用循环来显示复选框,但要自己实现回显功能-->

                                <s:iterator value="privilegeList">

                                    <input type="checkbox" name="privilegeIds" value="${id }" id="cb_${id}"

                                    <s:property value="%{ id in privilegeIds ? 'checked' : '' }"/>/>

                                    <label for="cb_${id }">${name}</label>

                                    <br/>

                                </s:iterator>

                            </tr>

                        </tbody>

<s:property value="%{ id in privilegeIds ? 'checked' : '' }"/>         作用:实现回显效果

<label for="cb_${id }">${name}</label>     作用:当点击名字时,名字前的复选框就会被选中或取消.

注意: for="cb_${id }" 引号前后不能有多余空格!!

 

  1. 实现树状结构展示:

    setPrivilege.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<html>

<head>

<title>配置权限</title>

<%@include file="/WEB-INF/jsp/public/header.jspf"%>

<script language="javascript"

    src="${pageContext.request.contextPath}/script/jquery_treeview/jquery.treeview.js"></script>

<link type="text/css" rel="stylesheet"

    href="${pageContext.request.contextPath}/style/blue/file.css" />

<link type="text/css" rel="stylesheet"

    href="${pageContext.request.contextPath}/script/jquery_treeview/jquery.treeview.css" />

 

</head>

<body>

 

<!-- 显示为树状结构(使用<ul>标签) -->

<ul id="tree">

<s:iterator value="privilegeList">

    <li>

        <input type="checkbox" name="privilegeIds" value="${id }"

            id="cb_${id}"

            <s:property value="%{ id in privilegeIds ? 'checked' : '' }"/> />

        <label for="cb_${id }">${name}</label>

    </li>

</s:iterator>

</ul>

 

<script type="text/javascript">

    $("#tree").treeview();

</script>

</body>

</html>

%@include file="/WEB-INF/jsp/public/header.jspf"%

header.jspf中已经导入了

<script language="javascript" src="${pageContext.request.contextPath}/script/jquery.js"></script>

所以第一步导入js,cs文件(总共三个文件)的工作已经完成.

 

相应的action中:

List<Privilege> privilegeList = privilegeService.findAll();

ActionContext.getContext().put("privilegeList", privilegeList);

所以页面效果如图:

原本的action是将所有权限查出来,并没有体现出层次关系.而我们要做的是从顶级权限开始,一层一层往下…,所以要修改action中的代码:

        //准备数据

        List<Privilege> topPrivilegeList = privilegeService.findtopPrivilegeList();

        ActionContext.getContext().put("topPrivilegeList", topPrivilegeList);

PrivilegeServiceImpl:

    /**

     * 查询所有顶级权限

     */

    public List<Privilege> findtopPrivilegeList() {

        return getSession().createQuery(//

                "from Privilege p where p.parent is null")//

                .list();

    }

setPrivilegeUI.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<html>

<head>

<title>配置权限</title>

<%@include file="/WEB-INF/jsp/public/header.jspf"%>

<script language="javascript"

    src="${pageContext.request.contextPath}/script/jquery_treeview/jquery.treeview.js"></script>

<link type="text/css" rel="stylesheet"

    href="${pageContext.request.contextPath}/style/blue/file.css" />

<link type="text/css" rel="stylesheet"

    href="${pageContext.request.contextPath}/script/jquery_treeview/jquery.treeview.css" />

 

</head>

<body>

……

            <!-- 表单内容显示 -->

            <div class="ItemBlockBorder">

                <div class="ItemBlock">

                    <table cellpadding="0" cellspacing="0" class="mainForm">

                        <!--表头-->

                        <thead>

                            <tr align="LEFT" valign="MIDDLE" id="TableTitle">

                                <td width="300px" style="padding-left: 7px;">

                                    

                                    <input type="CHECKBOX" id="cbSelectAll" onclick="$('input[name=privilegeIds]').attr('checked', this.checked)" />

                                    <label for="cbSelectAll">全选</label>

                                    

                                </td>

                            </tr>

                        </thead>

 

                        <!--显示数据列表-->

                        <tbody id="TableData">

                            <tr class="TableDetail1">

                                <!-- 显示权限树 -->

 

<!-- 显示为树状结构(使用<ul>标签) -->

<ul id="tree">

<!-- 第一层 -->

<s:iterator value="topPrivilegeList">

    <li>

        <input type="checkbox" name="privilegeIds" value="${id }" id="cb_${id}"

            <s:property value="%{ id in privilegeIds ? 'checked' : '' }"/> />

        <label for="cb_${id }"><span class="folder">${name}</span></label>

        <ul>

            <!-- 第二层 -->

            <s:iterator value="children">

                <li>

                    <input type="checkbox" name="privilegeIds" value="${id }" id="cb_${id}"

                        <s:property value="%{ id in privilegeIds ? 'checked' : '' }"/> />

                    <label for="cb_${id }"><span class="folder">${name}</span></label>

                    <ul>

                        <!-- 第三层 -->

                        <s:iterator value="children">

                            <li>

                                <input type="checkbox" name="privilegeIds" value="${id }" id="cb_${id}"

                                    <s:property value="%{ id in privilegeIds ? 'checked' : '' }"/> />

                                <label for="cb_${id }"><span class="folder">${name}</span></label>

                            </li>

                        </s:iterator>

                    </ul>

                </li>

            </s:iterator>

        </ul>

    </li>

</s:iterator>

</ul>

 

<script type="text/javascript">

    $("#tree").treeview();

</script>

……

</body>

</html>

 

解析:

1.从需求页面来看:

最多有三层结构,而这层次结构在初始化权限数据之后是不能改变的了.想改变层次结构就得改动源码,所以层次结构比较固定,所以在权限设置页面上,我们可以通过做三层循环来体现层次关系.

2. <span class="folder">${name}</span>

实现的是文件夹效果:

(这是jquery写好的,可以直接使用)

3.除了第一层循环,第二第三层的循环value值都是children属性,children是Privilige对象中的一个set集合,因为set集合无序,所以每次刷新页面时,除了第一层的系统管理位置不变,其他的排序都会变化.

解决办法,在Privilege.hbm.xml中加上:

<!-- children属性,表达的是本对象与Privilege(children)的一对多关系 -->

<set name="children" order-by="id ASC">

    <key column="parentId"></key>

    <one-to-many class="Privilege"/>

</set>

4.全选/全不选功能:

<input type="CHECKBOX" id="cbSelectAll" onclick="$('input[name=privilegeIds]').attr('checked', this.checked)" />

                                    <label for="cbSelectAll">全选</label>

意思是点击后,将全选框的状态(选中或未选中)赋值给name为privilegeIds的input框.(即checked = this.checked)

5.导入jquery的js,cs文件之后,

Images的位置不能随便乱挪,因为他下面的css文件已经将images的路径写成绝对路径,乱挪的话,会导致css找不到图片.

 

  1. 树状结构中,选中或取消的效果
  • 选择上一级元素        parent( expr )
  • 选择所有上级元素(前辈)    parents( expr ) (只包括直系上级,旁系的不包括(比如上级的同级))
  • 选择下一级元素        children( expr )
  • 选择所有后代元素        find( expr )
  • 选择同级元素(兄弟)    siblings( expr )
  • 选择兄元素(前一个)    prev( expr )
  • 选择弟元素(后一个)    next( expr )

根据需求页面的源码来判断关系,如:

 

setPrivilegeUI:

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<html>

<head>

<title>配置权限</title>

<%@include file="/WEB-INF/jsp/public/header.jspf"%>

<script language="javascript"

    src="${pageContext.request.contextPath}/script/jquery_treeview/jquery.treeview.js"></script>

<link type="text/css" rel="stylesheet"

    href="${pageContext.request.contextPath}/style/blue/file.css" />

<link type="text/css" rel="stylesheet"

    href="${pageContext.request.contextPath}/script/jquery_treeview/jquery.treeview.css" />

 

<script type="text/javascript">

    $(function(){

        //增加onclick处理函数

        $("input[name=privilegeIds]").click(function(){

            //当选中或取消某个权限时,同时也选中或取消所有的下级权限

            $(this).siblings("ul").find("input").attr("checked" , this.checked);

            

            //当选中某个权限时,应同时选中他的直系上级权限

            if(this.checked == true){// 可以直接写为 if(this.checked) 因为checked为布尔值

                $(this).parent().parent().siblings("input").attr("checked" , true);

                /* 或者$(this).parents("li").children("input").attr("checked" , true); */

            }

            //当取消掉某个权限时,如果同级的也没有勾选,那也取消上级权限

            else{

                if($(this).parent().siblings("li").children("input:checked").size() == 0){

                    $(this).parent().parent().siblings("input").attr("checked" , false);

                }

            }

        })

    })

</script>

</head>

<body>

 

    <!-- 标题显示 -->

    <div id="Title_bar">

        <div id="Title_bar_Head">

            <div id="Title_Head"></div>

            <div id="Title">

                <!--页面标题-->

                <img border="0" width="13" height="13"

                    src="${pageContext.request.contextPath}/style/images/title_arrow.gif" />

                配置权限

            </div>

            <div id="Title_End"></div>

        </div>

    </div>

 

    <!--显示表单内容-->

    <div id=MainArea>

        <s:form action="role_setPrivilege">

            <s:hidden name="id"></s:hidden>

            <div class="ItemBlock_Title1">

                <!-- 信息说明 -->

                <div class="ItemBlock_Title1">

                    <img border="0" width="4" height="7"

                        src="${pageContext.request.contextPath}/style/blue/images/item_point.gif" />

                    正在为${name }配置权限

                </div>

            </div>

 

            <!-- 表单内容显示 -->

            <div class="ItemBlockBorder">

                <div class="ItemBlock">

                    <table cellpadding="0" cellspacing="0" class="mainForm">

                        <!--表头-->

                        <thead>

                            <tr align="LEFT" valign="MIDDLE" id="TableTitle">

                                <td width="300px" style="padding-left: 7px;">

                                    

                                    <input type="CHECKBOX" id="cbSelectAll" onclick="$('input[name=privilegeIds]').attr('checked', this.checked)" />

                                    <label for="cbSelectAll">全选</label>

                                    

                                </td>

                            </tr>

                        </thead>

 

                        <!--显示数据列表-->

                        <tbody id="TableData">

                            <tr class="TableDetail1">

                                <!-- 显示权限树 -->

<!-- 使用struts2的标签来显示复选框,虽然有回显功能,但不方便修改显示效果. -->

<%--<td><s:checkboxlist list="privilegeList"

        name="privilegeIds" listKey="id" listValue="name">

    </s:checkboxlist>

</td> --%>

 

<!-- 所以我们选择使用循环来显示复选框,但要自己实现回显功能-->

<%-- <s:iterator value="privilegeList">

    <input type="checkbox" name="privilegeIds" value="${id }"

        id="cb_${id}"

        <s:property value="%{ id in privilegeIds ? 'checked' : '' }"/> />

    <label for="cb_${id }">${name}</label>

    <br />

</s:iterator> --%>

 

<!-- 显示为树状结构(使用<ul>标签) -->

<ul id="tree">

<!-- 第一层 -->

<s:iterator value="topPrivilegeList">

    <li>

        <input type="checkbox" name="privilegeIds" value="${id }"

            id="cb_${id}"

            <s:property value="%{ id in privilegeIds ? 'checked' : '' }"/> />

        <label for="cb_${id }"><span class="folder">${name}</span></label>

        <ul>

            <!-- 第二层 -->

            <s:iterator value="children">

                <li>

                    <input type="checkbox" name="privilegeIds" value="${id }"

                        id="cb_${id}"

                        <s:property value="%{ id in privilegeIds ? 'checked' : '' }"/> />

                    <label for="cb_${id }"><span class="folder">${name}</span></label>

                    <ul>

                        <!-- 第三层 -->

                        <s:iterator value="children">

                            <li>

                                <input type="checkbox" name="privilegeIds" value="${id }"

                                    id="cb_${id}"

                                    <s:property value="%{ id in privilegeIds ? 'checked' : '' }"/> />

                                <label for="cb_${id }"><span class="folder">${name}</span></label>

                            </li>

                        </s:iterator>

                    </ul>

                </li>

            </s:iterator>

        </ul>

    </li>

</s:iterator>

</ul>

 

<script type="text/javascript">

    $("#tree").treeview();

</script>

 

 

                            </tr>

                        </tbody>

                    </table>

                </div>

            </div>

 

            <!-- 表单操作 -->

            <div id="InputDetailBar">

                <input type="image"

                    src="${pageContext.request.contextPath}/style/images/save.png" />

                <a href="javascript:history.go(-1);"><img

                    src="${pageContext.request.contextPath}/style/images/goBack.png" /></a>

            </div>

        </s:form>

    </div>

 

    <div class="Description">

        说明:<br /> 1,选中一个权限时:<br /> &nbsp;&nbsp;&nbsp;&nbsp; a,应该选中 他的所有直系上级。<br />

        &nbsp;&nbsp;&nbsp;&nbsp; b,应该选中他的所有直系下级。<br /> 2,取消选择一个权限时:<br />

        &nbsp;&nbsp;&nbsp;&nbsp; a,应该取消选择 他的所有直系下级。<br />

        &nbsp;&nbsp;&nbsp;&nbsp; b,如果同级的权限都是未选择状态,就应该取消选中他的直接上级,并递归向上做这个操作。<br />

 

        3,全选/取消全选。<br /> 4,默认选中当前岗位已有的权限。<br />

    </div>

 

</body>

</html>

<script type="text/javascript">

    $(function(){

        ……

        })

    })

</script>

 

这样写的效果是:等页面加载完成之后才有效果.

 

四.使用权限

系统权限---登陆注销

新建个登陆注销专用的action

loginoutAction:

@Controller

@Scope("prototype")

public class LoginoutAction extends BaseAction<User>{

    

    /** 登录页面 */

    public String loginUI() throws Exception {

        return "loginUI";

    }

    

    /** 登录 */

    public String login() throws Exception {

        //验证登录名和密码,如果正确就返回这个用户,不正确就返回null

        User user = userService.findByLoginNameAndPassword(model.getLoginName(), model.getPassword());

          

// 如果登录名或密码不正确,就转回到登录页面并提示错误消息

        if(user == null){

            addFieldError("login", "对不起,您的账号密码输入错误!");

            return "loginUI";

        //如果用户名和密码都正确,就登录用户.

        }else{

            ActionContext.getContext().getSession().put("user", user);

            return "toHome";

        }

        

    }

    

    /** 注销 */

    public String logout() throws Exception {

        ActionContext.getContext().getSession().remove("user");

        return "logout";

    }    

}

ActionContext.getContext().getSession().put("user", user);

这是struts2提供的解耦和的方式,不依赖原生Servlet的API的方式.采用第二种方式的话不方便测试,因为原生API方式依赖servlet的环境,得放到tomcat容器中,启动服务器才能拿到session.

 

不用再新建service,直接用原来的userService就好

UserServiceImpl:

    /**

     * 验证登录名和密码,如果正确就返回这个用户,不正确就返回null

     */

    public User findByLoginNameAndPassword(String loginName, String password) {

        String md5 = DigestUtils.md5Hex(password);

        return (User) getSession().createQuery(//

                "from User u where u.loginName = ? and u.password = ?")//

                .setParameter(0, loginName)//

                .setParameter(1, md5)//密码要用md5摘要

                .uniqueResult();

    }

uniqueResult()

这个方法确保只返回一个user对象,如果有多个返回值,则提示错误.

Struts.xml:

    <!-- 用户登录注销功能 -->

    <action name="loginout_*" class="loginoutAction" method="{1}">

        <result name="loginUI">/WEB-INF/jsp/loginoutAction/loginUI.jsp</result>

        <result name="logout">/WEB-INF/jsp/loginoutAction/logout.jsp</result>

        <result name="toHome" type="redirect">/index.jsp</result>

    </action>

Index.jsp(这里只是测试页面):

Welcome, ${user.name} !

LoginUI.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<HTML>

<HEAD>

<META http-equiv=Content-Type CONTENT="text/html; charset=gbk" />

    <TITLE>Itcast OA</TITLE>

    <%@ include file="/WEB-INF/jsp/public/header.jspf" %>

    <LINK HREF="${pageContext.request.contextPath}/style/blue/login.css" type=text/css rel=stylesheet />

</HEAD>

<BODY LEFTMARGIN=0 TOPMARGIN=0 MARGINWIDTH=0 MARGINHEIGHT=0 CLASS=PageBody >

 

<s:form action="loginout_login">

<DIV ID="CenterAreaBg">

<DIV ID="CenterArea">

<DIV ID="LogoImg"><IMG BORDER="0" SRC="${pageContext.request.contextPath}/style/blue/images/logo.png" /></DIV>

<DIV ID="LoginInfo">

<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 width=100%>

<TR>

    <tr>

        <div style="color:red"><s:fielderror></s:fielderror></div>

    </tr>

<TD width=45 CLASS="Subject"><IMG BORDER="0" SRC="${pageContext.request.contextPath}/style/blue/images/login/userId.gif" /></TD>

<TD>

    <%-- 用户名 --%>

    <%-- <s:textfield SIZE="20" cssClass="TextField" NAME="loginName" /> --%>

    <s:textfield size="20" cssClass="TextField" name="loginName" />

</TD>

<TD ROWSPAN="2" STYLE="padding-left:10px;"><INPUT TYPE="image" SRC="${pageContext.request.contextPath}/style/blue/images/login/userLogin_button.gif"/></TD>

</TR>

<TR>

<TD CLASS="Subject"><IMG BORDER="0" SRC="${pageContext.request.contextPath}/style/blue/images/login/password.gif" /></TD>

<TD>

    <%-- 密码,不需要回显 --%>

    <%-- <s:password showPassword="false" SIZE="20" cssClass="TextField" NAME="password" /> --%>

    <s:password size="20" cssClass="TextField" showPassword="false" name="password" />

</TD>

</TR>

</TABLE>

</DIV>

<DIV ID="CopyRight"><A HREF="javascript:void(0)">&copy; 2010 版权所有 itcast</A></DIV>

</DIV>

</DIV>

</s:form>

 

</BODY>

</HTML>

Tips:之前没注意name的大小写问题,一种用大写,这么低级的错误却浪费了我很多时间!!!细心!!!!如果用大写,会报空指针异常:

 

<s:fielderror name="login"></s:fielderror>这样写的话是将name为login的错误消息显示出来.

<s:fielderror></s:fielderror>这样写的话是将所有错误消息显示出来.

 

Logout.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html>

 

<head>

<%@ include file="/WEB-INF/jsp/public/header.jspf" %>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

<title>您已退出Itcast OA系统</title>

    <link href="${pageContext.request.contextPath}/style/blue/logout.css" rel="stylesheet" type="text/css" />

</head>

 

<body>

    <table border=0 cellspacing=0 cellpadding=0 width=100% height=100%>

        <tr>

            <td align=center>

                <div id=Logout>

                    <div id=AwokeMsg><img id=LogoutImg src="${pageContext.request.contextPath}/style/blue/images/logout/logout.gif" border=0 /><img id=LogoutTitle src="${pageContext.request.contextPath}/style/blue/images/logout/logout1.gif" border=0 /></div>

                    <div id=LogoutOperate>

<img src="${pageContext.request.contextPath}/style/blue/images/logout/logout2.gif" border=0 />

    <!-- 这里不适用s:a标签!!! -->

    <a href="${pageContext.request.contextPath }/loginout_loginUI.do">重新进入系统</a>

 

<img src="${pageContext.request.contextPath}/style/blue/images/logout/logout3.gif" border=0 /> <a href="javascript: window.close();">关闭当前窗口</a>

</div>

                </div>

            </td>

        </tr>

    </table>

</body>

</html>

效果图:

(快捷键:home跳到当前行的开头,end跳到当前行的结尾)

猜你喜欢

转载自www.cnblogs.com/xm-tx/p/8876497.html