spring boot 与 iview 前后端分离架构之行为日志的实现(三十四)
行为日志
在我们系统开发中,我们希望对用户的某些行为做一些日志的记录,本章就作为抛砖引玉给大家讲解下如何做到日志的拦截。
后端改造
BehaviorLogDao.xml改造
<?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.github.bg.admin.core.dao.BehaviorLogDao">
<resultMap id="BaseResultMap" type="com.github.bg.admin.core.entity.BehaviorLog">
<id column="behaviorLogId" jdbcType="BIGINT" property="behaviorLogId" />
<result column="actionMethod" jdbcType="VARCHAR" property="actionMethod" />
<result column="actionDate" jdbcType="TIMESTAMP" property="actionDate" />
<result column="actionUser" jdbcType="VARCHAR" property="actionUser" />
<result column="actionUserId" jdbcType="VARCHAR" property="actionUserId" />
</resultMap>
<!-- 获取行为日志列表 -->
<select id="queryBehaviorLogList" resultMap="BaseResultMap">
select * from t_behavior_log where 1=1
<if test="search!=null and search != ''">
and (
actionMethod like concat('%',#{search},'%') or
actionUser like concat('%',#{search},'%')
)
</if>
</select>
</mapper>
BehaviorLogDao改造
package com.github.bg.admin.core.dao;
import com.github.bg.admin.core.entity.BehaviorLog;
import org.apache.ibatis.annotations.Param;
import tk.mybatis.mapper.common.Mapper;
import java.util.List;
public interface BehaviorLogDao extends Mapper<BehaviorLog> {
/**
* 功能描述:获取行为日志列表
*
* @param search 模糊匹配日志的用户名字和响应方法
* @return 返回查询结果
*/
List<BehaviorLog> queryBehaviorLogList(@Param("search") String search);
}
BehaviorLogService的实现
package com.github.bg.admin.core.service;
import com.github.bg.admin.core.constant.SystemStaticConst;
import com.github.bg.admin.core.dao.BehaviorLogDao;
import com.github.bg.admin.core.entity.Page;
import com.github.bg.admin.core.entity.ReturnInfo;
import com.github.bg.admin.core.util.PageUtil;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
/**
* @author linzf
* @since 2019/5/20
* 类描述:行为日志的service
*/
@Service
public class BehaviorLogService {
@Autowired
private BehaviorLogDao behaviorLogDao;
/**
* 功能描述:获取行为日志列表
*
* @param search 模糊匹配日志的用户名字和响应方法
* @param pageSize 每页显示的记录的条数
* @param current 当前访问第几页
* @param orderKey 排序字段
* @param orderByValue 排序方式,降序还是升序
* @return 返回查询结果
*/
public ReturnInfo queryBehaviorLogList(String search, int pageSize, int current, String orderKey, String orderByValue) {
PageHelper.startPage(current, (pageSize > 0 && pageSize <= 500) ? pageSize : 20,(orderKey != null && !"".equals(orderKey)) ? ((orderByValue != null && !"".equals(orderByValue)) ? (orderKey + " " + orderByValue) : orderKey) : "");
HashMap<String, Object> res = PageUtil.getResult(behaviorLogDao.queryBehaviorLogList(search));
return new ReturnInfo(SystemStaticConst.SUCCESS, "获取日志列表数据成功!", new Page(pageSize, current, (long) res.get("total"), (List) res.get("rows")));
}
}
BehaviorLogController的实现
package com.github.bg.admin.core.controller;
import com.github.bg.admin.core.entity.ReturnInfo;
import com.github.bg.admin.core.service.BehaviorLogService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @author linzf
* @since 2019/5/20
* 类描述:行为日志的controller
*/
@RestController
@RequestMapping("/behaviorLog")
public class BehaviorLogController {
@Autowired
private BehaviorLogService behaviorLogService;
/**
* 功能描述:获取行为日志列表
*
* @param search 模糊匹配日志的用户名字和响应方法
* @param pageSize 每页显示的记录的条数
* @param current 当前访问第几页
* @param orderKey 排序字段
* @param orderByValue 排序方式,降序还是升序
* @return 返回查询结果
*/
@ApiOperation(value = "获取行为日志列表")
@PostMapping("queryBehaviorLogList")
private ReturnInfo queryBehaviorLogList(@RequestParam(name = "search", required = false) String search,
@RequestParam(name = "pageSize") int pageSize,
@RequestParam(name = "current") int current,
@RequestParam(name = "orderKey",required = false) String orderKey,
@RequestParam(name = "orderByValue",required = false) String orderByValue){
return behaviorLogService.queryBehaviorLogList(search, pageSize, current, orderKey, orderByValue);
}
}
AuthInterceptor拦截器的改造
package com.github.bg.admin.core.filter;
import com.github.bg.admin.core.auth.ReleaseUrl;
import com.github.bg.admin.core.constant.SystemStaticConst;
import com.github.bg.admin.core.dao.BehaviorLogDao;
import com.github.bg.admin.core.entity.BehaviorLog;
import com.github.bg.admin.core.entity.User;
import com.github.bg.admin.core.util.RedisCache;
import com.github.bg.admin.core.util.StringUtils;
import com.github.bg.admin.core.util.WriteUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
/**
* @author linzf
* @since 2019-05-14
* 类描述:拦截器实现权限的拦截
*/
public class AuthInterceptor implements HandlerInterceptor {
private Logger log = LoggerFactory.getLogger(AuthInterceptor.class);
/**
* 日志的dao
*/
@Autowired
private BehaviorLogDao behaviorLogDao;
/**
* 操作redis的实现类
*/
@Autowired
private RedisCache redisCache;
/**
* 获取放行的权限的接口
*/
@Autowired
private ReleaseUrl releaseUrl;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
String token = httpServletRequest.getHeader("x-access-token");
String actionUrl = httpServletRequest.getServletPath();
if (SystemStaticConst.ACTION_TYPE_OPTIONS.equals(httpServletRequest.getMethod())) {
return true;
}
BehaviorLog behaviorLog = new BehaviorLog();
behaviorLog.setActionDate(new Date());
behaviorLog.setActionMethod(actionUrl);
/**
* 判断当前的响应地址是否可以放行
*/
String releasePath = releaseUrl.getReleaseUrl();
if (releasePath.indexOf(actionUrl) == -1) {
if (token == null || "".equals(token) || "null".equals(token)) {
WriteUtil.write(httpServletResponse, SystemStaticConst.NOT_LOGIN, "用户未登录");
return false;
}
/**
* 判断当前的用户是否有权限访问当前节点
*/
log.debug("token:{}", token);
String powerPath = StringUtils.getObjStr(redisCache.getString(token));
if ("".equals(powerPath)) {
WriteUtil.write(httpServletResponse, SystemStaticConst.AUTH_TOKEN_EXPIRE, "token过期");
return false;
}
if (powerPath.indexOf(actionUrl) == -1) {
WriteUtil.write(httpServletResponse, SystemStaticConst.AUTH_FAIL, "用户无权限,请联系系统管理员");
return false;
}
/**
* 根据token来获取当前登录的用户的信息
*/
User user = redisCache.getObject(token + "_USER", User.class);
if (user == null) {
behaviorLog.setActionUser("");
behaviorLog.setActionUserId("");
behaviorLogDao.insert(behaviorLog);
WriteUtil.write(httpServletResponse, SystemStaticConst.NOT_LOGIN, "用户未登录");
return false;
} else {
behaviorLog.setActionUser(user.getNickName());
behaviorLog.setActionUserId(user.getUserId());
behaviorLogDao.insert(behaviorLog);
}
} else {
behaviorLog.setActionUser("");
behaviorLog.setActionUserId("");
behaviorLogDao.insert(behaviorLog);
}
return true;
}
}
前端改造
在前端工程的sys目录底下创建一个behavior目录,接着在底下创建behaviorList.vue,代码如下:
behaviorList.vue实现
<template>
<div>
<Card title="日志查询">
<div>
<div style="display:inline-block;float:right;">
<Input v-model="search" suffix="ios-search" placeholder="请输入需要查询的信息" style="width: auto"
:search=true @on-search="handleSearch"/>
</div>
</div>
<div style="clear: both;"></div>
<div style="margin-top: 10px;">
<Table ref="behaviorTable" @on-sort-change="onSortChange" :columns="columns" :data="behaviorData" :height="tableHeight">
</Table>
</div>
<div style="margin-top: 10px;">
<Page show-elevator show-sizer show-total :total="total" :current="current"
:page-size="pageSize" @on-change="changePage" @on-page-size-change="changePageSize"/>
</div>
</Card>
</div>
</template>
<script>
import {queryBehaviorLogList} from '../../../api/sys/behavior/behavior.api';
export default {
data(){
return {
search:'',
key:'actionDate',
order:'desc',
total: 0,
current: 1,
pageSize: 10,
columns:[
{
title: '请求方法',
key: 'actionMethod',
sortable: true
},
{
title: '请求人',
key: 'actionUser',
sortable: true
},
{
title: '请求时间',
key: 'actionDate',
sortable: true,
render: (h, params) => {
return h('div',
this.formatDate(new Date(params.row.actionDate), 'yyyy/MM/dd hh:mm:ss')
)
}
}
],
behaviorData:[],
tableHeight:200
}
},
methods:{
handleSearch(){
let current = this.current
let pageSize = this.pageSize
let search = this.search
let orderKey = this.key
let orderByValue = this.order
const _this = this;
queryBehaviorLogList({
current,
pageSize,
search,
orderKey,
orderByValue
}).then(res => {
if (res.code == 200) {
this.$Message.success('获取日志列表成功')
_this.total = res.obj.total
_this.behaviorData = res.obj.rows
} else {
this.$Message.error('获取日志列表失败' + ',' + res.msg)
}
});
},
onSortChange(sort){
if(sort.order=='normal'){
this.order = '';
}else{
this.key = sort.key;
this.order = sort.order;
}
this.handleSearch();
},
changePage(current) {
this.current = current;
this.handleSearch();
},
changePageSize(pageSize) {// 改变每页记录的条数
this.pageSize = pageSize;
this.handleSearch();
}
},
mounted() {
// 初始化完成组件的时候执行以下的逻辑
this.handleSearch();
this.tableHeight = window.innerHeight - this.$refs.behaviorTable.$el.offsetTop - 270
}
}
</script>
router中增加日志的配置
在router目录的router.js中增加以下的配置
{
path: 'behaviorList',
name: 'behaviorList',
meta: {
icon: 'ios-browsers',
title: '行为日志',
code:'system-manage-behavior',
requireAuth: true //表示当前响应的请求是否需要进行登录拦截验证【true:需要;false:不需要】
},
component: resolve => {
require(['../view/sys/behavior/behaviorList.vue'], resolve);
}
}
运行项目
最后我们将我们的项目运行起来,然后登录成功以后我们访问我们的行为日志模块,这时候我们就可以看到如下的页面,在这边我们可以看到所有的操作的行为日志,大家可以根据资质的需求去改造行为日志的记录。
上一篇文章地址:spring boot + iview 前后端分离架构之基于socketIo的消息推送的实现(三十三)
下一篇文章地址:spring boot 与 iview 前后端分离架构之权限注解的实现(三十五)