下面主要来说说Thymeleaf模板使用和权限分配的实现思路。
先看效果图:
实现该功能的思路是:传往前端的数据为Map,该Map以columnName(权限分栏名)为key,以该分栏下的所有权限为value。因为要回显权限是否选中,这里为权限实体类(Perm)定义了一个属性checkedFlag(默认为false)
private boolean checkedFlag = false;
角色管理功能中,首先将得到columnList,遍历columnList,然后以columnId查询属于该分栏下的所有权限得到permList,根据roleId查询权限映射表(permmapping)得到mappingList,如果某个permId既在permList中又在mappingList中,说明该权限为选中状态。
@GetMapping("/assignPerm")
public ModelAndView assignPerm(@RequestParam int roleId,@RequestParam String roleName){
//权限分栏集合
List columnList = columnService.findColumnList();
Role role = roleService.findRoleById(roleId);
ResultEntity resultEntity = new ResultEntity();
//获取当前的方法名
String methodName = new Exception().getStackTrace()[0].getMethodName();
resultEntity.setResultCode("200");
resultEntity.setOperMessage(CLASS_NAME+"---"+methodName);
resultEntity.setResultObject(role);
resultEntity.setResultList(columnList);
HashMap> map = new HashMap<>();
List mappingList = permMappingService.findMappingListByRole(roleId);
for(Column column:columnList){
//获取该分栏下的所有权限(permList)
List permList= permService.findPermByColumn(column.getColumnId());
//遍历permList
for(Perm perm:permList){
for(PermMapping permMapping:mappingList){
if(permMapping.getPermId()==perm.getPermId()){
//当映射关系集合mappingList中对象的permId与permList中对象permId相同时,将permChecked的状态设置为true
perm.setCheckedFlag(true);
}
}
}
//以权限所属的columnName(分栏名)为key,以该columnName下的permList(权限勾选对象集合)为value
map.put(column.getColumnName(),permList);
}
resultEntity.setResultListMap(map);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("resultEntity",resultEntity);
modelAndView.setViewName("/roleOper");
return modelAndView;
}
看这部分对应的前端:
从上面的代码中可以看出,权限分栏下的所有checkbox的值为该权限的id。Thymeleaf能够接收Map类型的值,Map的取值方式为
map['key']
,如果key是变量的话,取值方式为map['__${variable}__']。
其中,权限分栏的checkbox的name属性是以checkGroup为前缀,以columnId为后缀,以下划线分隔。权限的checkbox的name属性是以checkItem为前缀,以它所属的columnId为后缀,以下划线分隔。全选的checkbox的name属性的值为checkAll
th:name="'checkGroup_'+${column.columnId}"
th:name="'checkItem_'+${perm.columnId}"
name="checkAll"
下面就是js中checkbox全选和反选的逻辑:
var totalLength = $(":checkbox[name!='checkAll']").length;
var checkedLength = 0;
$(":checkbox[name^='checkGroup']").each(
function(){
var perffix = 'checkItem';
var suffix = $(this).attr('name').split('_')[1];
var itemLength = $(":checkbox[name^='"+perffix+"'][name$='"+suffix+"']").length;
var itemCheckedLength = $(":checkbox[name^='"+perffix+"'][name$='"+suffix+"']:checked").length;
if(itemCheckedLength == itemLength){
if(itemCheckedLength > 0){
this.checked = true;
checkedLength += itemCheckedLength+1;
$(":checkbox[name^='"+perffix+"'][name$='"+suffix+"']").each(
function(){
this.checked = true;
}
);
}
}else{
checkedLength += itemCheckedLength;
}
if(checkedLength==totalLength){
$(":checkbox[name='checkAll']").attr("checked",true);
}
}
);
$(":checkbox[name^='checkGroup']").click(
function(){
var perffix = 'checkItem';
var suffix = $(this).attr('name').split('_')[1];
var flag = this.checked;
$(":checkbox[name^='"+perffix+"'][name$='"+suffix+"']").each(
function(){
this.checked = flag;
}
);
}
);
$(":checkbox[name^='checkItem']").click(function(){
var suffix = $(this).attr('name').split('_')[1];
var itemLength = $(":checkbox[name^='checkItem'][name$='"+suffix+"']").length;
var itemCheckedLength = $(":checkbox[name^='checkItem'][name$='"+suffix+"']:checked").length;
if(itemCheckedLength == itemLength){
$(":checkbox[name^='checkGroup'][name$='"+suffix+"']").each(
function () {
this.checked = true;
}
);
}else{
$(":checkbox[name^='checkGroup'][name$='"+suffix+"']").each(
function () {
this.checked = false;
}
);
}
});
$(":checkbox[name!='checkAll']").click(function () {
var checkedLength = $(":checkbox[name!='checkAll']:checked").length;
if(checkedLength == totalLength){
$(":checkbox[name='checkAll']").each(
function () {
this.checked = true;
}
);
}else {
$(":checkbox[name='checkAll']").each(
function () {
this.checked = false;
}
);
}
});
/*全选*/
$(":checkbox[name^='checkAll']").click(
function () {
var flag = this.checked;
$(":checkbox").each(
function () {
this.checked = flag;
}
)
}
);
var powerIdArray = new Array();
$("#submitBtn").click(
function () {
var roleId = $("#roleId").val().trim();
var roleName = $("#roleName").val().trim();
var roleInfo = $("#roleInfo").val().trim();
$(":checkbox[name^='checkItem']:checked").each(
function () {
powerIdArray.push($(this).val());
console.info("powerIdArray: "+$(this).val());
}
);
$.ajax({
url: [[@{/powerManage/assignPower}]],
type: 'post',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify({primaryMappingId:roleId,formMappingIdArray : powerIdArray,primaryMappingName : roleName,primaryMappingInfo : roleInfo}),
async: true,
success: function(data){
if(data != null){
alert(data.msg);
if(data.success == true){
window.location.reload();
}else{
$(".assign_box").hide();
}
}
}
});
});
如果某个权限被选中,就将该权限Id加入permIdArray(权限数组)
var permIdArray = new Array();
$("#submitBtn").click(
function () {
var roleId = $("#roleId").val().trim();
var roleName = $("#roleName").val().trim();
var roleInfo = $("#roleInfo").val().trim();
var creatorName = 'admin';
console.info("date: "+getNowFormatDate());
console.info("roleId: "+roleId);
$(":checkbox[name^='checkItem']:checked").each(
function () {
permIdArray.push($(this).val());
console.info("permIdArray: "+$(this).val());
}
);
为方便描述映射关系,这里定义了一个MappingEntity(映射实体类)
public class MappingEntity {
private int primeMapId;//主映射(一对多的一方)
private int[] minorMapIdArray;//从映射(一对多的多方)
private String primeMapName;
private String primeMapInfo;
private String creatorName;
private Date createTime;
public int getPrimeMapId() {
return primeMapId;
}
public void setPrimeMapId(int primeMapId) {
this.primeMapId = primeMapId;
}
public int[] getMinorMapIdArray() {
return minorMapIdArray;
}
public void setMinorMapIdArray(int[] minorMapIdArray) {
this.minorMapIdArray = minorMapIdArray;
}
public String getPrimeMapName() {
return primeMapName;
}
public void setPrimeMapName(String primeMapName) {
this.primeMapName = primeMapName;
}
public String getPrimeMapInfo() {
return primeMapInfo;
}
public void setPrimeMapInfo(String primeMapInfo) {
this.primeMapInfo = primeMapInfo;
}
public String getCreatorName() {
return creatorName;
}
public void setCreatorName(String creatorName) {
this.creatorName = creatorName;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
勾选中后提交的请求
$.ajax({
url: [[@{/admin/assignPerm.asy}]],
type: 'post',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify({primeMapId:roleId,minorMapIdArray : permIdArray,primeMapName : roleName,primeMapInfo : roleInfo,creatorName : creatorName}),
async: true,
success: function(data){
if(data != null){
alert(data.hintMsg);
if(data.operFlag == true){
window.location.reload();
}else{
$(".role_box").hide();
}
}
}
});
});
在分配权限的实现过程中,涉及到多次分配权限的问题。首先看看映射表是否存在该映射,如果不存在,说明是第一次分配权限,直接插入即可;如果存在,说明是不是第一次分配权限,要获取上一次权限Id的list,比较前端传过来的数组,将多余的删除,缺少的插入。通过ArrayCompare这个工具来实现
public class ArrayCompare {
/*第一个数组独有的部分*/
public static List findOwnPart(int[] compareArray,int[] referArray){
/* int[] array1 = listToArray(list);*/
List fristOwnList=new ArrayList<>();
for (int compare:compareArray) {
boolean tag = true;
for(int refer:referArray){
if(compare==refer){
tag = false;
break;
}
}
if(tag){
fristOwnList.add(compare);
}
}
return fristOwnList;
}
}
权限分配的代码逻辑
@PostMapping("/assignPerm.asy")
public void addPermMapping(@RequestBody MappingEntity mappingEntity, HttpServletResponse resp) throws Exception{
//时间格式
Date date=new Date();
Timestamp timeStamp = new Timestamp(date.getTime());
System.out.println(timeStamp.toString());
JSONObject jsonObject = new JSONObject();
String hintMsg = null;
boolean operFlag = false;
//查找之前是否存在映射关系
List permIdList = permMappingService.permIdList(mappingEntity.getPrimeMapId());
int[] minorMapIdArray = mappingEntity.getMinorMapIdArray();
if(minorMapIdArray == null){
hintMsg = "前端传递的数据为空!!!";
}else{
if(permIdList.size()==0){
//将role-perm映射关系插入permmapping表
List permMappingList = new ArrayList<>();
for(int i=0;i deleteList = ArrayCompare.findOwnPart(oldArray, minorMapIdArray);
//需要添加的部分
List insertList = ArrayCompare.findOwnPart(minorMapIdArray, oldArray);
if(deleteList.size()>0){
ArrayList permMappingList = new ArrayList<>();
for(Integer permId:deleteList){
PermMapping permMapping = new PermMapping();
permMapping.setPermId(permId);
permMapping.setRoleId(mappingEntity.getPrimeMapId());
permMappingList.add(permMapping);
}
permMappingService.deletePermMappingList(permMappingList);
}
if(insertList.size()>0){
List permMappingList = new ArrayList<>();
for(int permId:insertList){
//创建PermMapping对象,存放 role-perm 的映射信息
PermMapping permMapping = new PermMapping();
permMapping.setRoleId(mappingEntity.getPrimeMapId());
permMapping.setPermId(permId);
permMapping.setCreatorName(mappingEntity.getCreatorName());
permMapping.setCreateTime(timeStamp);
//将role-perm 的映射信息存入permMappingList
permMappingList.add(permMapping);
}
permMappingService.addPermMappingList(permMappingList);
}
hintMsg = "插入数据成功!!!";
operFlag = true;
}
}
jsonObject.put("hintMsg",hintMsg);
jsonObject.put("operFlag",operFlag);
System.out.println(jsonObject.toJSONString());
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().println(jsonObject.toJSONString());
resp.getWriter().close();
}
如果系统中的用户与角色的关系也是1对N的话,给用户分配角色的思路也是一样的。
系统中除了登录,注册,退出操作以外的所有请求都要进行拦截(这里我在考虑能否用网关拦截)。根据请求携带的session或cookie得到当前的用户信息。去数据库查询该用户的所有权限(建议将权限信息存入redis中),看看用户是否有当前操作的权限,如果没有,进行提示。