上一篇中已經介紹了我初步創建好管理系統和加載菜單的功能,這篇把用戶管理(新增用戶,修改用戶,分配角色)和角色管理(新增角色,修改角色,授權)的功能增設中的心得和問題記錄一下:
放上界面效果圖:
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;"> >> </a> <br/><br/><br/> <a class="easyui-linkbutton" onclick="removeRole();" style="width:40px;"> << </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自己的項目,成功!!!