springboot+easyui+jpa實現動態權限角色的后台管理系統(二)


上一篇中已經介紹了我初步創建好管理系統和加載菜單的功能,這篇把用戶管理(新增用戶,修改用戶,分配角色)和角色管理(新增角色,修改角色,授權)的功能增設中的心得和問題記錄一下:

放上界面效果圖:

 

 

1.首先在數據庫的sys_resource表中找到用戶管理和角色管理,在這兩條數據的url字段中添加ftl的路徑

我在登陸和跳轉的controller層中先寫了獲取路徑的代碼:

    @RequestMapping(value = "/page/{tail}/{file}", method = RequestMethod.GET)
    public String currency(@PathVariable("file") String file, @PathVariable("tail") String tail) {
        return "/" + tail + "/" + file;
    }

然后在數據庫的url字段中添加

2.編寫前端的界面

roleInfo.ftl

<!DOCTYPE html>
<html>
<head>
<#include "../inc/inc.ftl"/>
</head>
<body>
<div class="easyui-layout" data-options="fit:true,border:false">
    <table id="dg"></table>
</div>

<div id="dlg" class="easyui-dialog" style="width:450px;height:auto;padding:10px 20px" buttons="#dlg-buttons"
     data-options="closed:true,modal:true">
    <form id="fm" method="post" enctype="multipart/form-data">
        <input type="hidden" id="roleId" name="roleId"/>
        <table class="grid">
            <tr>
                <td>角色名稱:</td>
                <td>
                    <input type="text" name="roleName" class="easyui-textbox"
                           data-options="required:true,validType:['length[0,50]']"/>
                </td>
            </tr>
            <tr>
                <td>備注:</td>
                <td>
                    <input type="text" name="remark" class="easyui-textbox" data-options="validType:['length[0,50]']"/>
                </td>
            </tr>
        </table>
    </form>
</div>
<div id="dlg-buttons">
    <a href="javascript:void(0)" class="easyui-linkbutton c8" data-options="iconCls:'icon-ok'"
       onclick="javascript:saveRole();" style="width:90px;">保存</a>
    <a href="javascript:void(0)" class="easyui-linkbutton c2" data-options="iconCls:'icon-cancel'"
       onclick="javascript:$('#dlg').dialog('close');" style="width:90px;">取消</a>
</div>

<div id="toolbar" style="padding:5px;height:auto">
    <div>
        <a onclick="addRole();" href="javascript:void(0);" class="easyui-linkbutton"
           data-options="plain:true,iconCls:'icon-add'">新增角色</a>
        <a onclick="editRole();" href="javascript:void(0);" class="easyui-linkbutton"
           data-options="plain:true,iconCls:'icon-edit'">修改角色</a>
        <a onclick="openAuth();" href="javascript:void(0);" class="easyui-linkbutton"
           data-options="plain:true,iconCls:'icon-edit'">授權</a>
    </div>
</div>

<#include "auth.ftl"/>
</body>
</html>


<script type="text/javascript">
    $(document).ready(function () {
        loadData();
    });

    function loadData() {
        $("#dg").datagrid({
            url: '${request.contextPath}/sys/role_list',
            striped: true,
            border: false,
            collapsible: false,        //是否可折疊的
            loadMsg: '正在加載數據...',
            fit: true,                //自動大小
            idField: 'roleId',
            singleSelect: true,//是否單選
            columns: [[{
                field: 'roleName',
                title: '角色名',
                width: 120,
                halign: 'center'
            }, {
                field: 'remark',
                title: '備注',
                width: 200,
                halign: 'center'
            }
            ]],
            toolbar: '#toolbar'
        });
    }

    function addRole() {
        $('#fm').form('clear');
        $('#dlg').dialog('open').dialog('setTitle', '新增');
    }

    function editRole() {
        var row = $('#dg').datagrid('getSelected');
        if (row) {
            $('#dlg').dialog('open').dialog('setTitle', '修改');
            $('#fm').form('load', row);
        } else {
            $.messager.alert("提示", "請選擇一條記錄");
        }
    }

    function saveRole() {
        $('#fm').form('submit', {
            url: "${request.contextPath}/sys/role_save",
            success: function (result) {
                var result = eval('(' + result + ')');
                if (result.code == 0) {
                    $('#dg').datagrid('reload');
                    $('#dlg').dialog('close');
                } else {
                    $.messager.show({
                        title: '提示',
                        msg: result.message
                    });
                }
            }
        });
    }
</script>

userInfo.ftl:

<!DOCTYPE html>
<html>
<head>
<#include "../inc/inc.ftl"/>
</head>
<body>
<div class="easyui-layout" data-options="fit:true,border:false">
    <table id="dg"></table>
</div>

<div id="dlg" class="easyui-dialog" style="width:450px;height:auto;padding:10px 20px" buttons="#dlg-buttons"
     data-options="closed:true,modal:true">
    <form id="fm" method="post" enctype="multipart/form-data">
        <input type="hidden" id="userId" name="userId"/>
        <table class="grid">
            <tr>
                <td>用戶名:</td>
                <td>
                    <input type="text" name="username" class="easyui-textbox"
                           data-options="required:true,validType:['length[3,20]']"/>
                </td>
            </tr>
            <tr>
                <td>密碼:</td>
                <td>
                    <input type="text" name="password" class="easyui-passwordbox" iconWidth="28"
                           data-options="required:true,validType:['length[0,20]']"/>
                </td>
            </tr>
            <tr>
                <td>姓名:</td>
                <td>
                    <input type="text" name="staffName" class="easyui-textbox"
                           data-options="required:true,validType:['length[0,20]']"/>
                </td>
            </tr>
        </table>
    </form>
</div>
<div id="dlg-buttons">
    <a href="javascript:void(0)" class="easyui-linkbutton c8" data-options="iconCls:'icon-ok'"
       onclick="javascript:saveUser();" style="width:90px;">保存</a>
    <a href="javascript:void(0)" class="easyui-linkbutton c2" data-options="iconCls:'icon-cancel'"
       onclick="javascript:$('#dlg').dialog('close');" style="width:90px;">取消</a>
</div>

<div id="roleDlg" class="easyui-dialog" style="width:550px;height:450px;" buttons="#roleDlg-buttons"
     data-options="closed:true,modal:true,resizable:true">
    <div class="easyui-layout" data-options="fit:true,border:false">
        <div data-options="region:'west',collapsible:false" title="可分配角色" style="width:227px;padding:5px;">
            <table id="selectRoles"></table>
        </div>
        <div data-options="region:'center'" style="padding-top:120px;padding-left:1px;text-align:center">
            <a class="easyui-linkbutton" onclick="addRole();" style="width:40px;"> &gt;&gt; </a>
            <br/><br/><br/>
            <a class="easyui-linkbutton" onclick="removeRole();" style="width:40px;"> &lt;&lt; </a>
        </div>
        <div data-options="region:'east',collapsible:false" title="已分配角色" style="width:227px;padding:5px;">
            <table id="selectedRoles"></table>
        </div>
    </div>
</div>
<div id="roleDlg-buttons">
    <a href="javascript:void(0)" class="easyui-linkbutton c2" iconCls="icon-cancel"
       onclick="javascript:$('#roleDlg').dialog('close')" style="width:90px">關閉</a>
</div>

<div id="toolbar" style="padding:5px;height:auto">
    <div>
        <a onclick="addUser();" href="javascript:void(0);" class="easyui-linkbutton"
           data-options="plain:true,iconCls:'icon-add'">新增用戶</a>
        <a onclick="editUser();" href="javascript:void(0);" class="easyui-linkbutton"
           data-options="plain:true,iconCls:'icon-edit'">修改用戶</a>
        <a onclick="grantRole();" href="javascript:void(0);" class="easyui-linkbutton"
           data-options="plain:true,iconCls:'icon-edit'">分配角色</a>
    </div>
</div>
</body>
</html>


<script type="text/javascript">
    $(document).ready(function () {
        loadData();
    });

    function loadData() {
        $("#dg").datagrid({
            url: '${request.contextPath}/sys/user_list',
            striped: true,
            border: false,
            collapsible: false,        //是否可折疊的
            loadMsg: '正在加載數據...',
            fit: true,                //自動大小
            idField: 'userId',
            singleSelect: true,//是否單選
            columns: [[{
                field: 'username',
                title: '用戶名',
                width: 120,
                halign: 'center'
            }, {
                field: 'staffName',
                title: '真實姓名',
                width: 200,
                halign: 'center'
            }
            ]],
            toolbar: '#toolbar'
        });
    }

    function addUser() {
        $('#fm').form('clear');
        $('#dlg').dialog('open').dialog('setTitle', '新增');
    }

    function editUser() {
        var row = $('#dg').datagrid('getSelected');
        if (row) {
            $('#dlg').dialog('open').dialog('setTitle', '修改');
            $('#fm').form('load', row);
        } else {
            $.messager.alert("提示", "請選擇一條記錄");
        }
    }

    function saveUser() {
        $('#fm').form('submit', {
            url: "${request.contextPath}/sys/user_save",
            success: function (result) {
                var result = eval('(' + result + ')');
                if (result.code == 0) {
                    $('#dg').datagrid('reload');
                    $('#dlg').dialog('close');
                } else {
                    $.messager.show({
                        title: '提示',
                        msg: result.message
                    });
                }
            }
        });
    }

    function grantRole() {
        var row = $('#dg').datagrid('getSelected');
        if (row) {
            $('#roleDlg').dialog('open').dialog('setTitle', '分配角色');
            $("#selectRoles").datagrid({
                url: "${request.contextPath}/sys/user_no_role?userId=" + row.userId,
                width: 210,
                height: 'auto',
                border: false,
                loadMsg: '正在加載數據...',
                fit: true,                //自動大小
                idField: 'roleId',
                rownumbers: true,//行號
                remoteSort: false,
                frozenColumns: [[
                    {field: 'ck', checkbox: true}
                ]],
                columns: [[{
                    field: 'roleName',
                    title: '角色名稱',
                    sortable: true,
                    width: 150,
                    align: 'center'
                }]]
            });
            $("#selectedRoles").datagrid({
                url: "${request.contextPath}/sys/user_role?userId=" + row.userId,
                width: 210,
                height: 'auto',
                border: false,
                loadMsg: '正在加載數據...',
                fit: true,                //自動大小
                idField: 'roleId',
                rownumbers: true,//行號
                remoteSort: false,
                frozenColumns: [[
                    {field: 'ck', checkbox: true}
                ]],
                columns: [[{
                    field: 'roleName',
                    title: '角色名稱',
                    sortable: true,
                    width: 150,
                    align: 'center'
                }]]
            });
        } else {
            $.messager.alert('提示', '請選擇一條記錄', 'info');
        }
    }

    //增加角色
    function addRole() {
        var row = $('#dg').datagrid('getSelected');
        var checknodes = $('#selectRoles').datagrid('getChecked');
        var prams = [];
        if (checknodes && checknodes.length > 0) {
            for (var i = 0; i < checknodes.length; i++) {
                var pram = new Object();
                pram.userId = row.userId;
                pram.roleId = checknodes[i].roleId;
                prams.push(pram);
            }
            //轉換成json字符串。
            var jsonText = JSON.stringify(prams);
            $.ajax({
                url: '${request.contextPath}/sys/add_role',
                type: 'post',
                dataType: 'json',
                data: {data: jsonText},
                success: function (result) {
                    if (result.code == 0) {
                        $('#selectRoles').datagrid('reload');
                        $('#selectedRoles').datagrid('reload');
                        //清除選中的狀態,(雖然看不到選中,但獲取選中行的時候還是會有)
                        $('#selectRoles').datagrid('clearSelections');
                        $('#selectedRoles').datagrid('clearSelections');
                        $.messager.show({
                            title: '提示',
                            msg: result.message
                        });
                        $('#dg').datagrid('reload');
                        $('#dlg').dialog('close');
                    } else {
                        $.messager.show({
                            title: '提示',
                            msg: result.message
                        });
                    }
                }
            });
        } else {
            $.messager.alert('提示', '請選擇可分配的角色', 'info');
        }
    }

    //移除角色
    function removeRole() {
        var row = $('#dg').datagrid('getSelected');
        var checknodes = $('#selectedRoles').datagrid('getChecked');
        var prams = [];
        if (checknodes && checknodes.length > 0) {
            for (var i = 0; i < checknodes.length; i++) {
                var pram = new Object();
                pram.userId = row.userId;
                pram.roleId = checknodes[i].roleId;
                prams.push(pram);
            }
            //轉換成json字符串。
            var jsonText = JSON.stringify(prams);
            $.ajax({
                url: '${request.contextPath}/sys/remove_role',
                type: 'post',
                dataType: 'json',
                data: {data: jsonText},
                success: function (result) {
                    if (result.code == 0) {
                        $('#selectRoles').datagrid('reload');
                        $('#selectedRoles').datagrid('reload');
                        //清除選中的狀態,(雖然看不到選中,但獲取選中行的時候還是會有)
                        $('#selectRoles').datagrid('clearSelections');
                        $('#selectedRoles').datagrid('clearSelections');
                        $.messager.show({
                            title: '提示',
                            msg: result.message
                        });
                        $('#dg').datagrid('reload');
                        $('#dlg').dialog('close');
                    } else {
                        $.messager.show({
                            title: '提示',
                            msg: result.message
                        });
                    }
                }
            });
        } else {
            $.messager.alert('提示', '請選擇可移除的角色', 'info');
        }
    }
</script>

授權功能的資源界面 auth.ftl

(存在資源樹)

效果圖如下:

代碼如下:

<!-- 授權panel -->
<div id="authDlg" class="easyui-dialog" style="width:460px;height:500px;padding:10px;" buttons="#authDlg-buttons"
     data-options="closed:true,modal:true,resizable:true">
    <div class="easyui-layout" data-options="fit:true,border:false">
        <div data-options="region:'west'" style="width:310px;padding:10px;">
            <ul id="accessTree"></ul>
            <input id="roleId" name="roleId" hidden="hidden"/>
        </div>
        <div data-options="region:'center'" style="text-align:center;padding-top:200px;">
            <div>
                <a class="easyui-linkbutton" onclick="checkAll();" style="width:60px;">全選</a>
                <br/> <br/>
                <a class="easyui-linkbutton" onclick="checkInverse();" style="width:60px;">反選</a>
                <br/> <br/>
                <a class="easyui-linkbutton" onclick="uncheckAll();" style="width:60px;">取消</a>
            </div>
        </div>
    </div>
</div>
<div id="authDlg-buttons">
    <a href="javascript:void(0)" class="easyui-linkbutton c8" iconCls="icon-ok" onclick="saveAuth();"
       style="width:90px">保存</a>
    <a href="javascript:void(0)" class="easyui-linkbutton c2" iconCls="icon-cancel"
       onclick="javascript:$('#authDlg').dialog('close')" style="width:90px">取消</a>
</div>
<!-- 授權panel結束 -->


<script type="text/javascript">
    //==================================授權=============================
    var accessTree;

    function openAuth() {


        var row = $('#dg').datagrid('getSelected');
        if (row) {
            $('#authDlg').dialog('open').dialog('setTitle', '授權');
            //-----------可分配權限資源樹--------------
            accessTree = $('#accessTree').tree({
                url: '${request.contextPath}/sys/auth_resource',
                parentField: 'parentId',
                lines: true,
                checkbox: true,
                cascadeCheck: false
            });
//            $('#authForm').form('clear');
            $('#roleId').val(row.roleId);
            loadAuth(row.roleId);
        } else {
            $.messager.alert('提示', '請選擇一條記錄');
        }
    }

    //加載該角色已有權限
    function loadAuth(id) {
        $.ajax({
            url: '${request.contextPath}/sys/role_auth',
            type: 'post',
            dataType: 'json',
            data: {roleId: id},
            success: function (result) {
                for (var i = 0; i < result.length; i++) {
                    if (accessTree.tree('find', result[i].resourceId)) {
                        accessTree.tree('check', accessTree.tree('find', result[i].resourceId).target);
                    }
                }
            }
        });
    }

    //全選
    function checkAll() {
        var nodes = accessTree.tree('getChecked', 'unchecked');
        if (nodes && nodes.length > 0) {
            for (var i = 0; i < nodes.length; i++) {
                accessTree.tree('check', nodes[i].target);
            }
        }
    }

    //取消選擇
    function uncheckAll() {
        var nodes = accessTree.tree('getChecked');
        if (nodes && nodes.length > 0) {
            for (var i = 0; i < nodes.length; i++) {
                accessTree.tree('uncheck', nodes[i].target);
            }
        }
    }

    //反選
    function checkInverse() {
        var unchecknodes = accessTree.tree('getChecked', 'unchecked');
        var checknodes = accessTree.tree('getChecked');
        if (unchecknodes && unchecknodes.length > 0) {
            for (var i = 0; i < unchecknodes.length; i++) {
                accessTree.tree('check', unchecknodes[i].target);
            }
        }
        if (checknodes && checknodes.length > 0) {
            for (var i = 0; i < checknodes.length; i++) {
                accessTree.tree('uncheck', checknodes[i].target);
            }
        }
    }

    //保存
    function saveAuth() {
        var checknodes = accessTree.tree('getChecked');
        var roleId = $('#roleId').val();
        var prams = [];
        if (checknodes && checknodes.length > 0) {
            for (var i = 0; i < checknodes.length; i++) {
                var pram = new Object();
                pram.roleId = roleId;
                pram.resourceId = checknodes[i].id;
                prams.push(pram);
            }
        }
        //轉換成json字符串。
        var jsonText = JSON.stringify(prams);
        $.post('${request.contextPath}/sys/auth_save', {data: jsonText, roleId: roleId}, function (result) {
            if (result.code == 0) {
                $('#authDlg').dialog('close');
                $.messager.show({
                    title: '提示',
                    msg: result.message
                });
            } else {
                $.messager.show({
                    title: '提示',
                    msg: result.message
                });
            }
        }, 'json');
    }
</script>

Service:

用戶管理(依次是獲取當前用戶角色,獲取當前用戶沒有的角色,添加用戶角色,移除用戶角色)

package com.lk.modeleasyui.service;

import com.lk.modeleasyui.dao.SysRoleDAO;
import com.lk.modeleasyui.dao.SysRoleUserDAO;
import com.lk.modeleasyui.domain.SysRole;
import com.lk.modeleasyui.domain.SysRoleUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Lukizzz
 * @Date: 2018/9/12 11:48
 * @Description:
 */
@Service
public class SysRoleUserService {

    @Autowired
    private SysRoleUserDAO sysRoleUserDAO;
    @Autowired
    private SysRoleDAO sysRoleDAO;

    public List<SysRole> getUserRole(Long userId) {
        List<SysRoleUser> list = sysRoleUserDAO.findAllByUserId(userId);
        List<Long> roleIds = new ArrayList<>();
        for (SysRoleUser sysRoleUser : list) {
            roleIds.add(sysRoleUser.getRoleId());
        }
        return sysRoleDAO.findAllByRoleIdIn(roleIds);
    }

    public List<SysRole> getUserNoRole(Long userId) {
        List<SysRoleUser> list = sysRoleUserDAO.findAllByUserId(userId);
        if (list.isEmpty()) {
            return sysRoleDAO.findAll();
        } else {
            List<Long> roleIds = new ArrayList<>();
            for (SysRoleUser sysRoleUser : list) {
                roleIds.add(sysRoleUser.getRoleId());
            }
            return sysRoleDAO.findAllByRoleIdNotIn(roleIds);
        }
    }

    public void addRole(List<SysRoleUser> roleUserList) {
        for (SysRoleUser roleUser : roleUserList) {
            SysRoleUser sysRoleUser = new SysRoleUser();
            sysRoleUser.setRoleId(roleUser.getRoleId());
            sysRoleUser.setUserId(roleUser.getUserId());
            sysRoleUserDAO.save(sysRoleUser);
        }
    }

    public void removeRole(List<SysRoleUser> roleUserList) {
        for (SysRoleUser roleUser : roleUserList) {
            SysRoleUser sysRoleUser = new SysRoleUser();
            sysRoleUser.setUserId(roleUser.getUserId());
            sysRoleUser.setRoleId(roleUser.getRoleId());
            sysRoleUserDAO.deleteAllByRoleIdAndAndUserId(sysRoleUser.getRoleId(),sysRoleUser.getUserId());
        }
    }

}

角色管理:(獲取當前角色列表,修改角色,獲取授權列表也就是resource的列表,保存授權的列表)

package com.lk.modeleasyui.service;

import com.lk.modeleasyui.dao.SysRoleDAO;
import com.lk.modeleasyui.dao.SysRoleResourceDAO;
import com.lk.modeleasyui.domain.SysRole;
import com.lk.modeleasyui.domain.SysRoleResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Author: Lukizzz
 * @Date: 2018/9/11 13:49
 * @Description:
 */
@Service
public class SysRoleService {
    @Autowired
    private SysRoleDAO sysRoleDAO;
    @Autowired
    private SysRoleResourceDAO sysRoleResourceDAO;

    public List<SysRole> getRoleList() {
        return sysRoleDAO.findAll();
    }

    public void editRole(Long roleId, String roleName, String remark) {
        if (roleId != null) {
            sysRoleDAO.editRole(roleId, roleName, remark);
        } else {
            sysRoleDAO.createRole(roleName, remark);
        }
    }

    public List<SysRoleResource> getRoleAuth(Long roleId) {
        return sysRoleResourceDAO.findAllByRoleId(roleId);
    }

    public void saveRoleAuth(List<SysRoleResource> list, Long roleId) {
        sysRoleResourceDAO.deleteAllByRoleId(roleId);
        for (SysRoleResource sysRoleResource : list) {
            SysRoleResource sysRoleResource1 = new SysRoleResource();
            sysRoleResource1.setRoleId(sysRoleResource.getRoleId());
            sysRoleResource1.setResourceId(sysRoleResource.getResourceId());
            sysRoleResourceDAO.save(sysRoleResource1);
        }
    }

}

在這期間遇到的問題:

1.首先一個,因為roleId是個集合(默認一個用戶可以有多個角色),又因為roleId是Long類型,所以在獲取並計算的過程中,應該用List<Long>,如果不這樣的話會報錯說明錯誤的封裝類型和long類型不匹配

2.第二個問題,在前端點擊授權功能和分配角色功能的時候出現如下報錯:

看字面意思是說這個表不存在,但是我的數據庫里面是沒有這個表的,去網上查了一下也沒有很好的答案,后來發現是id生成策略的問題,解決方法是在實體類的@GeneratedValue后面加上一句代碼

(strategy = GenerationType.IDENTITY)

關於id生成策略的問題網上有介紹

3.我在進行對數據庫刪除操作的時候出現過這樣的問題:

原因是JPA中特有的在DAO層執行update和delete操作的時候,沒有對事務進行處理,我們需要在數據庫操作的方法上添加一個注解

@Transactional(rollbackFor = Exception.class)

4.增刪改查的功能后台功能沒有寫錯,但是在存入數據庫的時候出現了亂碼,頁面上顯示的也是數據庫的亂碼,按照網上的解決辦法我進行了一步步的查驗:

首先查看了數據表中相應字段的屬性

沒問題,然后看了數據庫的屬性

也沒問題,然后去看了項目的配置文件

 

也沒什么問題,在網查了解決方法后看到了一個帖子,按照上面的方法查詢了數據庫的默認編碼配置,發現default-character-server的配置不是utf8,按照教程打開MYSQL的安裝目錄,在安裝目錄下有個my.ini文件,通過記事本打開這個文件

 

在[client]下添加default-character-set=utf8

[mysqld]下添加character-set-server=utf8

配置修改完成后重啟MySQL就可以了

5.在完成模版項目的編寫后打算上傳gitlab和github,方便以后大家的使用,在push過程中首先遇到個問題,http認證失敗

因為生成了ssh公鑰,但是在gitlab的setting的ssh key中沒有添加公鑰.我重新生成了一遍公鑰並不設置密碼,在gitlab的setting的ssh key中添加key,通過ssh的地址上傳

而這樣又跳出來提示是push被攔截,在網上搜了一個教程,自己使用后push成功.

解決方案如下:

1.切換到自己項目所在的目錄,右鍵選擇GIT BASH Here,Idea中可使用Alt+F12

2.在terminl窗口中依次輸入命令:

git pull

git pull origin master

git pull origin master --allow-unrelated-histories

3.在idea中重新push自己的項目,成功!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM