P20
保存日志信息,创建数据库表
代码生成器生成对象文件
- 修改文件
还要修改opuserid=>opuser.id
要把日志信息切入到哪个service方法中
把request绑定到线程中
因为所有请求都要通过拦截器,所以绑定在拦截器上
登录方法也能获取得到request对象。
public class LogUtil {
public void writeLog(){
System.out.println(UserContext.get());
System.out.println("*****************");
System.out.println("******写入日志******");
System.out.println("*****************");
}
}
LogUtil.java
public class LogUtil {
@Autowired
private ILogService logService;
public void wirteLog(JoinPoint joinPoint){
//出现自己切自己的情况
if(joinPoint.getTarget() instanceof ILogService){
return;
}
Log log = new Log();
log.setOptime(new Date());
HttpServletRequest request = UserContext.get();
Employee currentUser = (Employee) request.getSession().getAttribute(UserContext.USERINSESSION);
log.setOpuser(currentUser);
String ip = request.getRemoteAddr();
log.setOpip(ip);
String function = joinPoint.getTarget().getClass().getName()+":"+joinPoint.getSignature().getName();
log.setFunction(function);
ObjectMapper mapper = new ObjectMapper();
String params;
try {
params = mapper.writeValueAsString(joinPoint.getArgs());
log.setParams(params);
System.out.println(params);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
//插入日志记录到数据库
//logService.insert(log);
}
}
这里我必须要吐槽一下,WC...所有操作都完成了后,我去查询数据库,发现数据库里面的数据没有更新??,我就开始排查,一直在检查代码,看以前写过的项目,又重看视频两次,在想:mysql没有开启自动提交??文件打错了??差点还想着手动提交代码试一下了,不过我忘记怎么手动提交了[捂脸]
后面就想着要不重新开启一个新的窗口查询,居然...居然出来了,还出来了很多,从11:40分的数据到14:20的数据都出来了...好吧,以后再也不想用MySQLworkbeach的上一个窗口查询了。That's all.
总结
P21
创建数据库表
编写分页
- 添加权限
P22
双击选中添加权限
P23
将所有权限保存在一个集合中
执行逆向工程
先注释掉添加方法
测试
没有额外参数
获得参数
P24
查询该角色的权限
P25
查询权限
编辑
需要先删除以前的权限,在添加新的权限
测试一下
总结
P26
先点击角色,会加载权限信息=>点击新增的时候会带过来
P27
员工和角色之间的关系
employee.jsp
<tr>
<td>角色</td>
<td><input type="text" id="emp_roles" class="easyui-combobox" data-options="valueField:'id',textField:'name',url:'/role_queryForEmp',multiple:true"></td>
</tr>
测试,role下拉框
总结
P28
点击编辑的时候可以看到员工的所有角色信息
测试一下
编辑也是先把之前的角色信息删除掉,然后在添加新的进去
测试,更新成功
总结
P29
P30,URL控制
这一章节确实好难,要多敲多看几遍[捂脸]
LoginInterceptor .java
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
//-----------------为当前线程绑定request对象------------------
UserContext.set(httpServletRequest);
//-----------------登录拦截-------------------
// 从session中获取用户信息
Employee employee = (Employee) httpServletRequest.getSession().getAttribute(UserContext.USER_IN_SESSION);
if (employee == null) {
// 拦截请求并重定向到登录页面
httpServletResponse.sendRedirect("/login.jsp");
// 记得return false,否则程序还是会往下走,经过拦截器达到目标Controller
return false;
}
//-----------------权限校验-------------------
if (handler instanceof HandlerMethod) {
HandlerMethod methodObj = (HandlerMethod) handler;
String function = methodObj.getBean().getClass().getName() + ":" + methodObj.getMethod().getName();
// 判断当前用户是否有权限访问这个方法
boolean flag = PermissionUtil.checkPermission(function);
if (flag) {
return true;
} else {
System.out.println("被拦截了.");
return false;
}
}
}
return true;
}
PermissionUtil ,java
package com._520it.crm.util;
import com._520it.crm.domain.Employee;
import com._520it.crm.domain.Menu;
import com._520it.crm.domain.Permission;
import com._520it.crm.service.IPermissionService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Component
public class PermissionUtil {
/*
* Spring确实能给对象属性注入值
* 但我们必须搞明白,什么是对象属性?非静态字段!!
* 静态字段属于类,不属于对象。
* 不信的话,大家可以创建一个Person类,设定两个字段 静态的age、非静态的name。
* 结果你debug观察person对象只能看到name!
* */
private static IPermissionService permissionService;
@Autowired
public void setPermissionService(IPermissionService permissionService) {
PermissionUtil.permissionService = permissionService;
}
/**
* 你们可能觉得 超级管理员放行、ALL权限又放行,之间的逻辑是不是有点乱,感觉可以合并?其实仔细想想,确实有这样的需求的
* @param function
* @return
*/
public static boolean checkPermission(String function) {
System.out.println(function);
/*
* 如果是超级管理员直接放行
*
* 拿到当前系统所有权限资源(需要权限验证的url),判断当前方法是否包含在其中
* 1.不包含:不需要权限判断,返回true,放行
* 2.包含,则进一步判断当前用户是否拥有该权限
* 1)拥有:返回true,放行
* 2)没有:返回false,拦截
*
* */
// 如果是超级管理员,直接放行
Employee currentUser = (Employee) UserContext.get().getSession().getAttribute(UserContext.USER_IN_SESSION);
if (currentUser.getAdmin()) {
return true;
}
// 得到当前系统所有权限(需要权限验证的url的)
if (CommonUtil.ALL_PERMISSIONS.size() == 0) {
// 从数据库查询当前系统所有权限资源,封装到ALL_PERMISSIONS
List<Permission> permissions = permissionService.selectAll();
for (Permission permission : permissions) {
CommonUtil.ALL_PERMISSIONS.add(permission.getResource());
}
}
// 如果当前访问的url不在系统所有权限中,说明不需要验证,否则进行验证
if (CommonUtil.ALL_PERMISSIONS.contains(function)) {
// 当前访问的方法需要权限验证,所以要查看当前用户是否拥有该权限
List<String> userPermissions = (List<String>) UserContext.get().getSession().getAttribute(UserContext.PERMISSION_IN_SESSION);
if (userPermissions.contains(function)) {
return true;
} else {
// ALL权限匹配
String allPermission = function.split(":")[0] + ":ALL";
if (userPermissions.contains(allPermission)) {
return true;
} else {
return false;
}
}
} else {
// 当前访问的方法不需要权限验证,直接放行
return true;
}
}
/**
* 根据当前用户的权限,从全部菜单中筛选出用户能访问的菜单
*
* @param menuList
*/
public static void checkMenuPermission(List<Menu> menuList) {
/*
* 不知道有没有人注意到,老师for循环遍历是反过来的。
* 如果你是和我一样正向遍历,注意在remove后i--,否则会出错。
* 具体原因,大家自己画图分析一下就知道了,刘意老师在迭代器还是集合那边有提到过。
* 想视频里老师的做法,他的循环判断条件不受size影响,它只看i是否还大于0,即当前list是否还有元素,有就继续迭代
*
* */
// 用户拥有的权限
List<String> userPermissions = (List<String>) UserContext.get().getSession().getAttribute(UserContext.PERMISSION_IN_SESSION);
// 遍历系统菜单,与当前用户拥有的权限进行比对
for (int i = 0; i < menuList.size(); i++) {
String menuPermission = menuList.get(i).getFunction();
// 菜单需要访问权限
if (StringUtils.isNotBlank(menuPermission)) {
// 如果用户没有该菜单权限,删除它,这样前台就不会显示
if (!userPermissions.contains(menuPermission)) {
menuList.remove(i);
// 注意,如果是从前往后遍历,一定要i--,否则会出错
i--;
}
// else 就说明用户有权限,那么就不做处理,菜单保留着
}
// else 说明该菜单根本不要求访问权限,谁来都可以访问,那么当前用户也可以,还是不做处理,菜单保留着
// 递归处理子菜单
List<Menu> childrenMenuList = menuList.get(i).getChildren();
if (!childrenMenuList.isEmpty()) {
checkMenuPermission(childrenMenuList);
}
}
}
}
CommonUtil .java
package com._520it.crm.util;
import java.util.ArrayList;
import java.util.List;
public class CommonUtil {
// 存放当前系统所有权限资源(即需要进行权限判断的url地址)
public static final List<String> ALL_PERMISSIONS = new ArrayList<>();
}
总结
P32,拦截之后的相应处理
P33
按钮权限控制
自定义标签,现在可能不太常用了。毕竟JSP都快被淘汰了
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.w3.org/1999/XSL/Transform"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>CRM函数库</description>
<display-name>客户关系管理系统</display-name>
<tlib-version>1.1</tlib-version>
<short-name>myFn</short-name>
<uri>http://www.520it.com/crm/permission</uri>
<function>
<description>
用户权限控制
</description>
<name>checkPermission</name>
<function-class>com._520it.crm.util.PermissionUtil</function-class>
<function-signature>boolean checkPermission(java.lang.String)</function-signature>
<example>
${myFn:checkPermission('哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈')}
</example>
</function>
</taglib>
测试一下
总结
P34,系统菜单
菜单树结构自关联
逆向工程
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com._520it.crm.mapper.MenuMapper" >
<resultMap id="BaseResultMap" type="com._520it.crm.domain.Menu" >
<id column="id" property="id" jdbcType="BIGINT" />
<result column="text" property="text" jdbcType="VARCHAR" />
<result column="iconCls" property="iconCls" jdbcType="VARCHAR" />
<result column="checked" property="checked" jdbcType="BIT" />
<result column="state" property="state" jdbcType="VARCHAR" />
<result column="attributes" property="attributes" jdbcType="VARCHAR" />
<result column="function" property="function" jdbcType="VARCHAR" />
<collection property="children" column="id" ofType="com._520it.crm.domain.Menu" select="com._520it.crm.mapper.MenuMapper.queryByParentId"></collection>
</resultMap>
<select id="queryForMenu" resultMap="BaseResultMap">
select * from menu where parent_id is null
</select>
<select id="queryByParentId" resultMap="BaseResultMap">
select * from menu where parent_id = #{id}
</select>
</mapper>
测试一下
P35
用户登录的时候把登录放在session中
·菜单权限控制·
这一节有点难
https://www.bilibili.com/video/BV16E411q7N2?p=35
测试
又总结一下
学习自:小码哥JavaEE课程CRM项目(SSM实战项目)