文章目录
- 第一章:授权操作
- 第一节:经典权限5张表的关系分析
- 1、数据库模型关系图
- 2、用户角色关系表
- 3、角色权限关系表
- 4、修改用户SysUser实体
- 5、修改角色Role实体
- 6、修改权限Permission实体
- 第二节:查看用户的角色详情功能
- 1、页面入口
- 2、编写Controller
- 3、编写Service
- 4、编写Dao
- 编写userDao
- 编写RoleDao(user下有role)
- 编写PermissionDao(Role下有permission)
- 5、修改前端user-show.jsp
- 第三节:为用户分配角色-角色列表数据回显
- 1、页面入口
- 2、编写Controller
- 3、页面回显数据(user-role-add.jsp)
- 第四节:为用户分配角色-更新关系到用户角色中间表
- 1、页面入口
- 2、编写Controller
- 3、编写Service
- 4、编写Dao
- 第五节:为角色添加权限数据回显(和user添加role雷同)
- 1、页面入口
- 2、编写Controller
- 3、编写Service
- 4、编写Dao
- 5、前端页面(role-permission-add.jsp)
- 第六节:为角色添加权限-实际保存即往中间表插入记录(和user添加role雷同)
- 1、页面入口
- 2、编写Controller
- 3、编写service
- 4、编写dao
- 第七节:为用户设置真正的角色
- 第二章:授权后的安全控制
- 第一节:在JSP页面控制菜单权限(不显示UI)
- 1、spring-security.xml配置文件
- 第二节:在服务器端控制权限(拦截请求 防止用户直接输入url访问)
- 1、修改spring-mvc.xml配置
- 2、在需要进行控制的Controller上添加@Secured注解
- 3、更换默认403 forbidden界面
- 第三章:系统日志功能
- 第一节:AOP记录日志
- 1、日志表sys_log和实体Log
- 2、springmvc.xml配置文件中开启aop的自动代理
- 3、在web.xml中配置监听request对象的监听器
- 4、编写切面类(切面类内部有增强)
- 5、Service代码实现
- 6、Dao代码实现
- 第二节 查询日志
- 1、页面入口
- 2、编写Controller
- 3、编写service
- 4、编写dao
- 5、修改domain
- 6、修改页面
第一章:授权操作
第一节:经典权限5张表的关系分析
1、数据库模型关系图

2、用户角色关系表
多对多的关系:就是两个一对多
一对多:在一的方向添加一个集合属性即可
-- 用户角色关系表 多对多 引入中间表
CREATE TABLE sys_user_role(
userId number,
roleId number,
PRIMARY KEY(userId,roleId), --联合主键:两个不能同时一样
FOREIGN KEY (userId) REFERENCES sys_USER(id),
FOREIGN KEY (roleId) REFERENCES sys_role(id)
)
3、角色权限关系表
CREATE TABLE sys_role_permission(
permissionId number,
roleId number,
PRIMARY KEY(permissionId,roleId),
FOREIGN KEY (permissionId) REFERENCES sys_permission(id),
FOREIGN KEY (roleId) REFERENCES sys_role(id)
)
4、修改用户SysUser实体
@Data
public class SysUser {
private Long id;
private String username;
private String email;
private String password;
private String phoneNum;
private int status;
//一个用户对应多个角色
private List<Role> roles = new ArrayList<>();//new出来 防止空指针
}
5、修改角色Role实体
@Data
public class Role {
private Integer id;
private String roleName;
private String roleDesc;
//一个角色被多个用户所拥有
private List<SysUser> users = new ArrayList<>();
//一个角色拥有多个权限
private List<Permission> permissions = new ArrayList<>();
}
6、修改权限Permission实体
@Data
public class Permission {
private Integer id;
private String permissionName;
private String url;
private Integer pid;//写简单的pid 不能写Permission对象 随便想想也是死循环
//一个权限被多个角色拥有
private List<Role> roles=new ArrayList<>();
}
第二节:查看用户的角色详情功能
1、页面入口
<a href="${pageContext.request.contextPath}/user/details?userId=${user.id}" class="btn bg-olive btn-xs">详情</a>
2、编写Controller
/**
* 查询某用户的详情功能
* 用户有哪些角色 角色分别有哪些权限
* @param userId
* @return
*/
@RequestMapping("/details")
public ModelAndView details(Integer userId){
LogUtils.print("用户详情:"+userId);
//查询数据--用户详情
SysUser user=userService.findById(userId);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("user",user);
modelAndView.setViewName("user-show");
return modelAndView;
}
3、编写Service
findById(Integer userId);
@Override
public SysUser findById(Integer userId) {
return userdao.findById(userId);
}
4、编写Dao
编写userDao
@Select("select * from sys_user where id = #{userId}")
@Results({
@Result(id=true,property = "id",column = "id"),//主键id 最好都加上 否则后端获取id为null
@Result(property = "roles",column = "id", //还是本张表主键id,因为是根据本张表主键id关联到role的
//根据userId查询角色列表
// cn.ahpu.dao.RoleDao.findRolesByUserId
many = @Many(select = "cn.ahpu.dao.RoleDao.findRolesByUserId"))
})
SysUser findById(Integer userId);
编写RoleDao(user下有role)
@Select("select r.* from sys_user_role ur,sys_role r where ur.roleid=r.id and ur.userid=#{userId}")
@Results({
@Result(id=true,property = "id",column = "id"),//主键id 最好加上 否则id只能用一次 后端查id就是null了
@Result(property = "permissions",column = "id", //还是本张表主键id,因为是根据本张表主键id关联到role的
many = @Many(select = "cn.ahpu.dao.PermissionDao.findPermissionsByRoleId"))
})
List<Role> findRolesByUserId(Integer userId);
编写PermissionDao(Role下有permission)
@Select("select p.* from sys_role_permission rp,sys_permission p where rp.roleid=#{roleId} and rp.permissionid=p.id")
List<Permission> findPermissionsByRoleId(Integer roleId);
5、修改前端user-show.jsp
<thead>
<tr>
<th>名称</th>
<th>描述</th>
</tr>
</thead>
<tr data-tt-id="0">
<td colspan="2">${user.username}</td>
</tr>
<tbody>
<c:forEach items="${user.roles}" var="role" varStatus="i">
<tr data-tt-id="${role.id}" data-tt-parent-id="0">
<td>${role.roleName }</td>
<td>${role.roleDesc }</td>
</tr>
<%--子标签的父id要唯一对应 得用${i.count}了 }
若dao中id@Result()里id都单独配置了
那么id可以多次使用 将i.count全部换成 role.id也不错
--%>
<c:forEach items="${role.permissions}" var="permission">
<tr data-tt-id="${role.id}-${permission.id}" data-tt-parent-id="${role.id}">
<td>${permission.permissionName}</td>
<td>${permission.url}</td>
</tr>
</c:forEach>
</c:forEach>
</tbody>
第三节:为用户分配角色-角色列表数据回显
1、页面入口
2、编写Controller
@RequestMapping("/addRoleToUserUI")
public ModelAndView addRoleToUserUI(Integer userId){
LogUtils.print("addRoleToUserUI:"+userId);
//所有角色
List<Role> roles = roleService.findAll();
//当前用户拥有的角色 直接将当前用户传过去也行 延迟加载还能起点作用
SysUser user = userService.findById(userId);
//方便选中已有的 换种写法
List<Role> userOwnedRoles = user.getRoles();
//把该用户拥有的角色id存到list放到前端
//id变成一个list 前端方便判断该id是否在数组中 el ${fn:contains(ids,id)}
List<Integer> ids=new ArrayList<>();
for (Role role : userOwnedRoles) {
ids.add(role.getId());
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("roles",roles);
modelAndView.addObject("ids",ids);
//真正执行添加业务时需要userId 因此也需要传过去
modelAndView.addObject("userId",user.getId());//user.getId()而不直接写userId "永远使用最后一次得到的数据"
modelAndView.setViewName("user-role-add");
return modelAndView;
}
3、页面回显数据(user-role-add.jsp)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<section class="content">
<input type="hidden" name="userId" value="${userId}"><%--用户id隐藏域--%>
<table id="dataList"
class="table table-bordered table-striped table-hover dataTable">
<thead>
<tr>
<th class=""style="padding-right:">
<input id="selall"
type="checkbox" class="icheckbox_square-blue"></th>
<th class="sorting_asc">ID</th>
<th class="sorting">角色名称</th>
<th class="sorting">角色描述</th>
</tr>
</thead>
<tbody>
<c:forEach items="${roles}" var="role">
<tr>
<td><input name="ids" type="checkbox" value="${role.id}"
<%--<c:if test="${fn:contains(ids, role.id)}">checked="checked"</c:if>--%>
<%--大神更牛的写法--%>
${fn:contains(ids, role.id)?"checked":" "}
></td>
<td>${role.id}</td>
<td>${role.roleName }</td>
<td>${role.roleDesc}</td>
</tr>
</c:forEach>
</tbody>
</table>
第四节:为用户分配角色-更新关系到用户角色中间表
1、页面入口
2、编写Controller
/**
* 给指定用户添加指定角色
* @param userId 需要添加角色的用户id
* @param ids 添加角色的id数组
* @return
*/
@RequestMapping("/addRolesToUser")
public String addRolesToUser(Integer userId,Integer[] ids){
userService.addRolesToUser(userId,ids);
return "redirect:/user/findAll";
}
3、编写Service
接口
/**
* 添加角色列表到用户
* @param userId
* @param ids
*/
void addRolesToUser(Integer userId, Integer[] ids);
实现
@Override
public void addRolesToUser(Integer userId, Integer[] ids) {
//先清空该用户拥有的所有角色
userdao.delRolesFromUser(userId);
if(ids!=null){
for (Integer roleId : ids) {
userdao.saveRoleToUser(userId,roleId);
}
}
}
4、编写Dao
/**
* 清空用户原来有的所有角色
* @param userId
*/
@Delete("delete from sys_user_role where userId=#{userId}")
void delRolesFromUser(Integer userId);
/**
* 为用户添加一个角色
* @param userId
* @param roleId
*/
@Insert("insert into sys_user_role values(#{param1},#{param2})")
void saveRoleToUser(Integer userId, Integer roleId);
第五节:为角色添加权限数据回显(和user添加role雷同)
1、页面入口
<a href="${pageContext.request.contextPath}/role/addPermissionsToRoleUI?roleId=#{role.id}" class="btn bg-olive btn-xs">添加权限</a>
2、编写Controller
/**
* 添加权限到角色的数据回显
* @param roleId
* @return
*/
@RequestMapping("/addPermissionsToRoleUI")
public ModelAndView addPermissionsToRoleUI(Integer roleId){
LogUtils.print(roleId);
//获取所有权限
List<Permission> permissions = permissionService.findAll();
//获取角色已有权限id列表
Role role = roleService.findById(roleId);
List<Permission> rolePermissions = role.getPermissions();
List<Integer> ids=new ArrayList<>();
for (Permission p : rolePermissions) {
ids.add(p.getId());
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("permissions",permissions);
modelAndView.addObject("ids",ids);
modelAndView.addObject("roleId",roleId);
modelAndView.setViewName("role-permission-add");
return modelAndView;
}
3、编写Service
findById(Integer roleId);
@Override
public Role findById(Integer roleId) {
return roleDao.findById(roleId);
}
4、编写Dao
@Select("select * from sys_role where id=#{roleId}")
@Results({
@Result(property = "id",column = "id"),
@Result(property = "permissions",column = "id",
many=@Many(select = "cn.ahpu.dao.PermissionDao.findPermissionsByRoleId",fetchType = FetchType.LAZY)
)
})
Role findById(Integer roleId);
5、前端页面(role-permission-add.jsp)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<form
action="${pageContext.request.contextPath}/role/addPermissionToRole.do"
method="post">
<!-- 正文区域 -->
<section class="content"> <input type="hidden" name="roleId"
value="${roleId}">
<table id="dataList"
class="table table-bordered table-striped table-hover dataTable">
<thead>
<tr>
<th class=""style="padding-right:">
<input id="selall"
type="checkbox" class="icheckbox_square-blue"></th>
<th class="sorting_asc">ID</th>
<th class="sorting">权限名称</th>
<th class="sorting">URL</th>
</tr>
</thead>
<tbody>
<c:forEach items="${permissions}" var="permission">
<tr>
<td><input name="ids" type="checkbox" value="${permission.id}"
${fn:contains(ids, permission.id)?"checked":""}
></td>
<td>${permission.id}</td>
<td>${permission.permissionName }</td>
<td>${permission.url}</td>
</tr>
</c:forEach>
</tbody>
</table>
<!--订单信息/--> <!--工具栏-->
<div class="box-tools text-center">
<button type="submit" class="btn bg-maroon">保存</button>
<button type="button" class="btn bg-default"
onclick="history.back(-1);">返回</button>
</div>
<!--工具栏/--> </section>
<!-- 正文区域 /-->
</form>
第六节:为角色添加权限-实际保存即往中间表插入记录(和user添加role雷同)
1、页面入口
2、编写Controller
/**
* 为角色添加权限 动数据库表
* @param roleId
* @param ids
* @return
*/
@RequestMapping("/addPermissionsToRole")
public String addPermissionsToRole(Integer roleId,Integer[] ids){
LogUtils.print(ids);
LogUtils.print(roleId);
roleService.addPermissionsToRole(roleId,ids);
return "redirect:/role/findAll";
}
3、编写service
void addPermissionsToRole(Integer roleId, Integer[] ids);
/**
* 为角色roleId 添加 ids这么多的权限
* @param roleId
* @param ids
*/
@Override
public void addPermissionsToRole(Integer roleId, Integer[] ids) {
//删除roleId所有权限
roleDao.delPermissionsFromRole(roleId);
if(ids!=null){
for (Integer permissionId : ids) {
roleDao.savePermissionToRole(roleId,permissionId);
}
}
}
4、编写dao
@Delete("delete from sys_role_permission where roleid=#{roleId}")
void delPermissionsFromRole(Integer roleId);
/**
* 注意参数顺序
* @param roleId
* @param permissionId
*/
@Insert("insert into sys_role_permission values(#{param2},#{param1})")
void savePermissionToRole(Integer roleId, Integer permissionId);
第七节:为用户设置真正的角色
修改UserServiceImpl的loadUserByUsername方法,为用户设置真正的角色
/**
* 通过用户名 得到用户对象
* 创建用户详情对象,返回
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//根据用户名获取用户(SysUser)对象--同时查询相应角色
SysUser sysUser = userdao.findByUsername(username);
if(sysUser==null) return null;
/* 添加的都是假的角色对象 真正的角色对象需要到数据库内查
//配置文件里没有指定角色了 需要自己创建角色对象
//创建角色的集合对象
Collection<GrantedAuthority> authorities=new ArrayList<>();
//创建临时角色对象 正常情况下应该是数据库角色表中查的
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
//对象添加到集合中
authorities.add(grantedAuthority);
//User是安全框架内实现了UserDetails接口的一个类
//第三个参数是:角色列表对象 (此处角色名ROLE_USER自己定义 xml里需要这个名字)
//{noop}前缀表示不加密 该把不加密去掉了*/
//添加数据库里真正的角色对象
Collection<GrantedAuthority> authorities=new ArrayList<>();
//登录时授权给用户 有哪些权限就授予哪些权限
for (Role role : sysUser.getRoles()) {
//LogUtils.print(role.getRoleName());
//创建角色对象
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_"+role.getRoleName());
//添加角色对象到集合
authorities.add(grantedAuthority);
}
//用户名 密码 角色
UserDetails user = new User(sysUser.getUsername(),sysUser.getPassword(),authorities);
return user;
}
userdao.findByUsername(username);,加个一对多结果集映射,否则查不到用户所拥有的权限
//根据用户名查询用户对象 唯一对象(username必须唯一)
@Select("select * from sys_user where username = #{username} and status=1")
@Results({
@Result(id=true,property = "id",column = "id"),//主键id 最好都加上 否则后端获取id为null
@Result(property = "roles",column = "id", //还是本张表主键id,因为是根据本张表主键id关联到role的
many = @Many(select = "cn.ahpu.dao.RoleDao.findRolesByUserId",fetchType = FetchType.LAZY))
})
SysUser findByUsername(String username);
第二章:授权后的安全控制
第一节:在JSP页面控制菜单权限(不显示UI)
在JSP页面中使用security:authorize标签,可以控制菜单是否显示。security:authorize标签的 access=“hasAnyRole(‘ROLE_USER’,‘ROLE_ADMIN’)”。因为标签的access使用的是表达式,所以需要将spring- security.xml配置文件的use-expressions设置为true。
1、spring-security.xml配置文件
1、使用表达式改为true: use-expressions=“true”
2、access不能直接写权限名而要写成:access="hasAnyRole(‘ROLE_USER’,‘ROLE_ADMIN’)”
表示拥有’ROLE_USER’,'ROLE_ADMIN’中任意一个权限就初步可以访问/**任意路径(真正目的是啥权限都没有时无法访问本网站任意未放行路径)
3、前端jsp 先加上标签库 然后
系统管理UI用 <security:authorize access=“hasRole(‘ROLE_ADMIN’)”></security:authorize>包裹
基础数据UI用<security:authorize access=“hasAnyRole(‘ROLE_ADMIN’,‘ROLE_USER’)”></security:authorize>包裹
jsp:
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
<security:authorize access="hasRole('ROLE_ADMIN')">
<li class="treeview"><a href="#"> <i class="fa fa-cogs"></i>
<span>系统管理</span> <span class="pull-right-container"> <i
class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li id="system-setting"><a
href="${pageContext.request.contextPath}/user/findAll"> <i
class="fa fa-circle-o"></i> 用户管理
</a></li>
<li id="system-setting"><a
href="${pageContext.request.contextPath}/role/findAll"> <i
class="fa fa-circle-o"></i> 角色管理
</a></li>
<li id="system-setting"><a
href="${pageContext.request.contextPath}/permission/findAll">
<i class="fa fa-circle-o"></i> 权限管理
</a></li>
<li id="system-setting"><a
href="${pageContext.request.contextPath}/pages/syslog-list.jsp"> <i
class="fa fa-circle-o"></i> 访问日志
</a></li>
</ul></li>
</security:authorize>
<%--ROLE_ADMIN和ROLE_USER都可以使用 换言之啥权限都没有连基础数据都不能访问--%>
<security:authorize access="hasAnyRole('ROLE_ADMIN','ROLE_USER')">
<li class="treeview"><a href="#"> <i class="fa fa-cube"></i>
<span>基础数据</span> <span class="pull-right-container"> <i
class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li id="system-setting"><a
href="${pageContext.request.contextPath}/product/findAll">
<i class="fa fa-circle-o"></i> 产品管理
</a></li>
<li id="system-setting"><a
href="${pageContext.request.contextPath}/order/findAll">
<i class="fa fa-circle-o"></i> 订单管理
</a></li>
</ul></li>
</security:authorize>
第二节:在服务器端控制权限(拦截请求 防止用户直接输入url访问)
虽然页面菜单对不同角色显示类不同的菜单,但是如果直接访问服务器端的url还是可以访问到资源信息的,所以好 需要对服务器端的资源进行安全控制。
控制方式就是借助于Spring的AOP,对Controller的的访问进行权限的功能增强。 修改spring-security.xml配置文件,添加aop的自动代理
1、修改spring-mvc.xml配置
添加配置:
<!--AOP 当下面一行的配置也放在spring-mvc.xml本文件内时此配置可有可无
当下面一行配置放在spring-security.xml中 本配置必须有 开启注解动态代理
-->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
<!--配置开启security的注解支持 必须加上-->
<security:global-method-security secured-annotations="enabled"/>
没办法提示了,自己手动加: 复制后改下名字即可
2、在需要进行控制的Controller上添加@Secured注解
指定拥有哪些权限时方可访问本Controller,用户任意一个权限即可
@Secured({"ROLE_ADMIN"})
public class UserController
@Secured({"ROLE_ADMIN"})
public class RoleController
@Secured({"ROLE_ADMIN"})
public class PermissionController
@Secured({"ROLE_ADMIN","ROLE_USER"})
public class ProductController
3、更换默认403 forbidden界面
spring-security.xml里加一行配置
<security:access-denied-handler error-page="/failer.jsp"></security:access-denied-handler>
第三章:系统日志功能
第一节:AOP记录日志
1、日志表sys_log和实体Log
sql语句
create sequence log_seq;
CREATE TABLE sys_log(
id number PRIMARY KEY,
visitTime DATE,
username VARCHAR2(50),
ip VARCHAR2(30),
method VARCHAR2(200)
)
实体类
SysLog.java
@Data
public class SysLog {
private Long id;
private Date visitTime;//访问时间
private String username;//访问者用户名
private String ip;//访问者ip
private String method;//访问的全限定类名.方法
}
2、springmvc.xml配置文件中开启aop的自动代理
之前应该已经加过了
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
3、在web.xml中配置监听request对象的监听器
springmvc会自动将httpservletrequest放到IOC容器中 即springmvc不需要加此配置
其他框架不会 其他web层框架想要注入request就必须加此配置
<!--配置请求监听器:当请求发生时,在容器中创建请求对象-->
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
4、编写切面类(切面类内部有增强)
spring-mvc.xml得多扫描一个包了
LogAop代码实现
package cn.ahpu.log;
import cn.ahpu.domain.SysLog;
import cn.ahpu.domain.SysUser;
import cn.ahpu.service.LogService;
import cn.ahpu.utils.LogUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
/**
* @author 寒面银枪
* @create 2020-05-16 16:53
*
* 注解配置AOP
* 提供一个类配置为切面类
* 切面=切入点+通知
* 通知类型
* 前置增强:@Before
* 后置增强:@AfterReturning
* 最终增强:@After
* 异常增强:@AfterThrowing
* 环绕增强:@Around
*
*/
//注意xml里加上扫描log包
@Component
@Aspect
public class LogController {
@Autowired
LogService logService;
@Autowired
HttpServletRequest request;//只有springmvc放到IOC中了 换一个框架可能就没了
@Pointcut("execution(* cn.ahpu.controller.*.*(..))")
public void pointcut(){}
/**
* 环绕增强
* @param joinPoint 连接点对象--可以执行真实方法--只在环绕增强中使用
* 连接点就是拦截的方法
*/
@Around("pointcut()") //织入
public Object around(ProceedingJoinPoint joinPoint){
//创建日志对象
SysLog sysLog = new SysLog();
//将日志对象封装
//1.访问时间 visitTime
sysLog.setVisitTime(new Date());
//2.访问用户名 username 安全框架内得到 注意是安全框架的User 不是自己写SysUser
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
sysLog.setUsername(user.getUsername());
//3.访问ip 还是得得到request对象 仔细想想哪里有? IOC容器里肯定有 直接注入一下就行了嘛
String ipAddr = request.getRemoteAddr();
sysLog.setIp(ipAddr);
//4.访问全限定类名
//被拦截类的全限定类名
String className = joinPoint.getTarget().getClass().getName();
//方法名称
String methodName = joinPoint.getSignature().getName();
sysLog.setMethod(className+"."+methodName);
//将日志对象存储到数据库
LogUtils.print(sysLog);
logService.save(sysLog);
try {
//执行真实的方法--必须返回真实方法返回值 否则所有方法被拦截 返回值都不返回 就不会跳转了
return joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
}
5、Service代码实现
LogService
public interface LogService {
void save(SysLog sysLog);
}
@Service
public class LogServiceImpl implements LogService {
@Autowired
LogDao logDao;
@Override
public void save(SysLog log) {
logDao.save(log);
}
}
6、Dao代码实现
public interface LogDao {
@Insert("insert into sys_log values(log_seq.nextval,#{visitTime},#{username},#{ip},#{method})")
void save(SysLog log);
}
第二节 查询日志
1、页面入口
2、编写Controller
/**
* 查询所有日志 分页查询
*/
@RequestMapping("/findAll")
public ModelAndView findAll(
@RequestParam(value = "currPage",required = false,defaultValue = "1") Integer currPage,
@RequestParam(value = "pageSize",required = false,defaultValue = "5") Integer pageSize
){
PageInfo<SysLog> pageHelper = logService.findAllByPageHelper(currPage, pageSize);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("pageHelper", pageHelper);
modelAndView.setViewName("syslog-list");
return modelAndView;
}
3、编写service
public interface LogService {
void save(SysLog sysLog);
/**
* 查询所有日志
* @return
*/
List<SysLog> findAll();
/**
* 分页查询所有
* @param currPage
* @param pageSize
* @return
*/
PageInfo<SysLog> findAllByPageHelper(Integer currPage, Integer pageSize);
}
@Override
public PageInfo<SysLog> findAllByPageHelper(Integer currPage, Integer pageSize) {
//指定分页参数
PageHelper.startPage(currPage,pageSize);
//查询全部 分页参数已经被绑定到当前线程 拦截器根据参数帮你做到拦截
List<SysLog> logs = logDao.findAll();
//创建PageInfo对象 控制页面最多显示5个页码
PageInfo<SysLog> pageInfo = new PageInfo<>(logs, 5);
//返回
return pageInfo;
}
4、编写dao
@Select("select * from sys_log")
List<SysLog> findAll();
5、修改domain
@Data
public class SysLog {
private Long id;
private Date visitTime;//访问时间
private String visitTimeStr;
private String username;//访问者用户名
private String ip;//访问者ip
private String method;//访问的全限定类名.方法
public String getVisitTimeStr() {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
String timeStr = sdf.format(visitTime);
return timeStr;
}
}
6、修改页面
<table id="dataList"
class="table table-bordered table-striped table-hover dataTable">
<thead>
<tr>
<th class=""style="padding-right:"><input id="selall"
type="checkbox" class="icheckbox_square-blue"></th>
<th class="sorting_asc">ID</th>
<th class="sorting">访问时间</th>
<th class="sorting">访问用户</th>
<th class="sorting">访问IP</th>
<th class="sorting">访问方法</th>
</tr>
</thead>
<tbody>
<c:forEach items="${pageHelper.list}" var="syslog" varStatus="i">
<tr>
<td><input name="ids" type="checkbox"></td>
<td>${i.count}</td>
<td>${syslog.visitTimeStr }</td>
<td>${syslog.username }</td>
<td>${syslog.ip }</td>
<td>${syslog.method}</td>
</tr>
</c:forEach>
</tbody>
</table>
<!--数据列表/-->
<!--工具栏-->
<div class="pull-left">
<div class="form-group form-inline">
<div class="btn-group">
<button type="button" class="btn btn-default" title="刷新"
onclick="window.location.reload();">
<i class="fa fa-refresh"></i> 刷新
</button>
</div>
</div>
</div>
<div class="box-tools pull-right">
<div class="has-feedback">
<input type="text" class="form-control input-sm"
placeholder="搜索"> <span
class="glyphicon glyphicon-search form-control-feedback"></span>
</div>
</div>
<!--工具栏/-->
</div>
<!-- 数据表格 /-->
</div>
<!-- /.box-body -->
<!-- .box-footer-->
<div class="box-footer">
<div class="pull-left">
<div class="form-group form-inline">
第${pageHelper.pageNum} 页,
总共${pageHelper.pages} 页,共${pageHelper.total} 条数据。 每页
<select class="form-control" name="pageSize" id="pageSize" onchange="gotoPage(1)">
<%--前10个用循环写 方便--%>
<c:forEach begin="1" end="10" var="i">
<option value="${i}">${i}</option>
</c:forEach>
<option value="15">15</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
<option value="50">50</option>
</select> 条
</div>
</div>
<div class="box-tools pull-right">
<ul class="pagination" id="gotoLi">
<%--超链接里访问js函数 必须加前缀javascript:--%>
<li><a href="javascript:gotoPage(1)" aria-label="Previous">首页</a></li>
<%--prePage多方便--%>
<li><a href="javascript:gotoPage(${pageHelper.prePage})">上一页</a></li>
<%--页面上显示几个页码也简单可控了 实在太方便了--%>
<c:forEach begin="${pageHelper.navigateFirstPage}" end="${pageHelper.navigateLastPage}" var="i">
<li><a href="javascript:gotoPage(${i})">${i}</a></li>
</c:forEach>
<li><a href="javascript:gotoPage(${pageHelper.nextPage})">下一页</a></li>
<li><a href="javascript:gotoPage(${pageHelper.pages})" aria-label="Next">尾页</a></li>
</ul>
</div>
</div>
<script type="text/javascript">
//方法写在外面 会自动执行 注意先得给每个option加上value="xx" 不能没有value属性
//每页显示几条的数据回显 select option
$("#pageSize option[value=${pageHelper.pageSize}]").prop("selected","selected");
//跳转页面
function gotoPage(currPage) {
//页面的越界检查此处判断也很方便
if(currPage<1||currPage>${pageHelper.pages}) return;
var pageSize=$("#pageSize").val();
location.href="${pageContext.request.contextPath}/log/findAll?currPage="+currPage+"&pageSize="+pageSize;
}
</script>