𝑰’𝒎 𝒉𝒉𝒈, 𝑰 𝒂𝒎 𝒂 𝒈𝒓𝒂𝒅𝒖𝒂𝒕𝒆 𝒔𝒕𝒖𝒅𝒆𝒏𝒕 𝒇𝒓𝒐𝒎 𝑵𝒂𝒏𝒋𝒊𝒏𝒈, 𝑪𝒉𝒊𝒏𝒂.
- 🏫 𝑺𝒉𝒄𝒐𝒐𝒍: 𝑯𝒐𝒉𝒂𝒊 𝑼𝒏𝒊𝒗𝒆𝒓𝒔𝒊𝒕𝒚
- 🌱 𝑳𝒆𝒂𝒓𝒏𝒊𝒏𝒈: 𝑰’𝒎 𝒄𝒖𝒓𝒓𝒆𝒏𝒕𝒍𝒚 𝒍𝒆𝒂𝒓𝒏𝒊𝒏𝒈 𝒅𝒆𝒔𝒊𝒈𝒏 𝒑𝒂𝒕𝒕𝒆𝒓𝒏, 𝑳𝒆𝒆𝒕𝒄𝒐𝒅𝒆, 𝒅𝒊𝒔𝒕𝒓𝒊𝒃𝒖𝒕𝒆𝒅 𝒔𝒚𝒔𝒕𝒆𝒎, 𝒎𝒊𝒅𝒅𝒍𝒆𝒘𝒂𝒓𝒆 𝒂𝒏𝒅 𝒔𝒐 𝒐𝒏.
- 💼 𝑷𝒓𝒐𝒇𝒆𝒔𝒔𝒊𝒐𝒏𝒂𝒍 𝒔𝒌𝒊𝒍𝒍𝒔:𝒎𝒚 𝒅𝒓𝒆𝒂𝒎
1-1:查看接口
1-2:/system/dict/data/type/sys_normal_disable和/system/dict/data/type/sys_user_sex
找接口:
这两个接口都是同一个,用idea 查接口的工具搜一下:
数据字典:
这里涉及到一个数据字典的概念,数据字典用来干嘛,比如这里的两个请求分别对应了两个下拉框:
为什么要查后台呢?因为这些如果前台写死了,那么我突然要加一个进去怎么加?就必须重新修改前端然后去再发一个版本才能加上去,如果说我动态访问后端,由后端到数据库里读,然后前端显示,这样就能解决这个问题了。令我不解的是,为什么若依有的是用来做数据字典,有的确没有加入到字典中去。
Redis中进行缓存:
数据字典访问核心代码:
@Override
public List<SysDictData> selectDictDataByType(String dictType)
{
List<SysDictData> dictDatas = DictUtils.getDictCache(dictType);
if (StringUtils.isNotEmpty(dictDatas))
{
return dictDatas;
}
dictDatas = dictDataMapper.selectDictDataByType(dictType);
if (StringUtils.isNotEmpty(dictDatas))
{
DictUtils.setDictCache(dictType, dictDatas);
return dictDatas;
}
return null;
}
很明显,数据字典是不经常修改的,所以redis是最好的归宿,这里就是常规的redis操作。
1-3:/system/user/list?pageNum=1&pageSize=10分页查找
1-3-1:分页PageHelper
我看PageHelper网上教程是通过配置文件实现的,比如这样:
但是我找半天也没在若依里面找到,于是仔细看了看,发现这些若依使用代码进行配置的。代码如下:
public class PageUtils extends PageHelper
{
/**
* 设置请求分页数据
*/
public static void startPage()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
Boolean reasonable = pageDomain.getReasonable();
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
}
}
}
大概就是从request请求中读几个参数,然后进行设置。
封装返回给前端的page对象:
protected TableDataInfo getDataTable(List<?> list)
{
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setRows(list);
rspData.setMsg("查询成功");
rspData.setTotal(new PageInfo(list).getTotal());
return rspData;
}
分页怎么用的,基本上就是这些了。开始分页+查+封装分页返回对象。
1-3-2:dataScope 数据范围
相关包:
一直好奇这个是用来干嘛的,直到遇见了才发现,这是一个数据范围的控制,也就是说控制一个用户,能看到的数据有哪些。
aspect中定义的权限等级:
/**
* 全部数据权限
*/
public static final String DATA_SCOPE_ALL = "1";
/**
* 自定数据权限
*/
public static final String DATA_SCOPE_CUSTOM = "2";
/**
* 部门数据权限
*/
public static final String DATA_SCOPE_DEPT = "3";
/**
* 部门及以下数据权限
*/
public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
/**
* 仅本人数据权限
*/
public static final String DATA_SCOPE_SELF = "5";
具体实现:
先获取当前已经登陆的用户,查看这个user有哪些角色,对于这些角色,在数据库中能看到哪些部门,通过sql语句拼接,然后将sql语句存进user对象的参数field中,再到mapper中去拼接sql,mapper中的返回值是当前用户能看到的所有user。打开MySQL可以发现,datascope在role中设置的。
注解里面的两个字段,deptAlias = “d”, userAlias = “u”,这两个是数据表的别名,可能是为了更灵活吧,因为放在了公共模块里面,当然越灵活越好。
/**
* 数据范围过滤
*
* @param joinPoint 切点
* @param user 用户
* @param deptAlias 部门别名
* @param userAlias 用户别名
*/
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
{
StringBuilder sqlString = new StringBuilder();
for (SysRole role : user.getRoles())
{
String dataScope = role.getDataScope();
if (DATA_SCOPE_ALL.equals(dataScope))
{
sqlString = new StringBuilder();
break;
}
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
{
sqlString.append(StringUtils.format(
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
role.getRoleId()));
}
else if (DATA_SCOPE_DEPT.equals(dataScope))
{
sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
}
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
{
sqlString.append(StringUtils.format(
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
deptAlias, user.getDeptId(), user.getDeptId()));
}
else if (DATA_SCOPE_SELF.equals(dataScope))
{
if (StringUtils.isNotBlank(userAlias))
{
sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
}
else
{
// 数据权限为仅本人且没有userAlias别名不查询任何数据
sqlString.append(" OR 1=0 ");
}
}
}
if (StringUtils.isNotBlank(sqlString.toString()))
{
Object params = joinPoint.getArgs()[0];
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
}
}
}
可以看一个例子:
@Override
@DataScope(deptAlias = "d", userAlias = "u")
public List<SysUser> selectUserList(SysUser user)
{
return userMapper.selectUserList(user);
}
除了上面的数据范围,如果你还想进行对当前用户已有的能看到的所有user,再次进行一个筛选,比如我看我对userId=2的这个用户,能不能看到他。我就在SysUser user对象里面设置一个id,mybatis里面会判空比如:
<if test="userId != null and userId != 0">
AND u.user_id = #{userId}
</if>
最后的一个sql语句就是这样:
select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u left join sys_dept d on u.dept_id = d.dept_id where u.del_flag = '0' AND u.user_id = 5 AND (d.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = 2 ) );
AND (d.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = 2 )
这个是AOP干的事情。
1-3-3:/system/dept/treeselect
/**
* 获取部门下拉树列表
*/
@GetMapping("/treeselect")
public AjaxResult treeselect(SysDept dept)
{
List<SysDept> depts = deptService.selectDeptList(dept);
return AjaxResult.success(deptService.buildDeptTreeSelect(depts));
}
就是从数据库中读所有部门,然后再构建一下树形结构,递归做一下,没有什么特别的。
1-3-4:/config/configKey/sys.user.initPassword
从数据库里面读初始密码,并且缓存起来,这个还挺简单的。