spring boot+iview 前后端分离架构之行为日志的实现(三十四)

 

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 前后端分离架构之行为日志的实现(三十四)
上一篇文章地址:spring boot + iview 前后端分离架构之基于socketIo的消息推送的实现(三十三)
下一篇文章地址:spring boot 与 iview 前后端分离架构之权限注解的实现(三十五)

 

上一篇:一篇文章教会你在 iview 的表格中动态生成图表


下一篇:iView 日期时间选择器设置开始时间至结束时间限制