Struts2拦截器记录系统操作日志

1、前言

  最近开发了一个项目,由于项目在整个开发过程中处于赶时间状态(每个项目都差不多如此)所以项目在收尾阶段发现缺少记录系统日志功能,以前系统都是直接写在每个模块的代码中,然后存入表单,在页面可以查看部分日志。这个系统并没有此要求,因此便想到了做一个系统通用的日志记录,主要记录数据有:操作的用户名、操作的远程IP地址、操作时间、操作对象、操作方法、操作的一些参数以及操作结果。由于系统框架是基于ssh框架的,所以最终考虑使用struts2的自带拦截器Interceptor来实现。

2、什么拦截器?

  拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。谈到拦截器,还有一个词大家应该知道——拦截器链(Interceptor Chain,在Struts 2中称为拦截器栈Interceptor Stack)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

拦截器的原理和大致流程
  1.ActionInvocation初始化时,根据配置,加载Action相关的所有Interc eptor。
   2. 通过ActionInvocation.invoke方法调用Action实现时,执行Interceptor。
Interceptor将很多功能从我们的Action中独立出来,大量减少了我们Action的代码,独立出来的行为具有很好的重用性。XWork、WebWork的许多功能都是有Interceptor实现,可以在配置文件中组装Action用到的Interceptor,它会按照你指定的顺序,在Action执行前后运行。

3、实现代码

package com.teraee.tasystem.interceptor;

import java.net.InetAddress;
import java.net.URLDecoder;
import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.teraee.tasystem.service.base.SysConfigManager;
import com.teraee.tasystem.service.base.SysOperationLogManager;
import com.teraee.tasystem.support.SpringUtil;
import com.teraee.tasystem.util.Log;
import com.teraee.tasystem.util.StringUtil;
import com.teraee.tasystem.util.SysOpConstant;

/**
 * 所有Action调用之前执行的拦截器
 *@author LH
 *@data 2018年3月7日
 */
@SuppressWarnings("serial")
public class OperationInterceptor extends AbstractInterceptor {

    private static Log log = Log.getLoger(new Object() {
        public Class getClassName() {
            return this.getClass();
        }
    }.getClassName());


    //无须记录Action调用日志的方法
    private static String[] unRecordLogResources={"validateTeaSnapNum",//校验教师创建的快照数量是否超过场景限制
                                                                            "validateServSnapNum",//校验应用服务创建的快照数量是否超过场景限制
                                                                            "getRoleList",//获取角色列表
                                                                            "initTaeCfg",//初始化登录配置
                                                                            "getIdvEnable",//IDV功能是否开启
                                                                            "getSysOpLogListByPage",//查询系统操作日志
                                                                            "getSysOpType",//得到系统操作方法
                                                                            "getStaticSwitch",//获取统计页面的开关状态
                                                                            "init",//登录初始化,
                                                                            "initEnv",//初始化登录环境
                                                                            "getInitUrl",//初始化登录环境
                                                                            "getAllUrl",//获取线上请求地址url
                                                                            "initCfgInfo",//正常登录
                                                                            "getURLfromConf",//获取配置文件信息
                                                                            "loginStatus",//检测用户登录状态
                                                                            "localAccountValidate",//本地账号验证模式
                                                                            "verifyLocal",//本地登录账号校验
                                                                            "verifyRemoteByQQ",//第三方登录远程同步并返回用户角色
                                                                            "verifyRemote",//用户登录同步到本地
                                                                            "buildTerLoginRelation"//添加终端登录关系
                                                                            };

    public String intercept(ActionInvocation invocation) throws Exception {
//      log.loger.info("operation intercept begin!");
        HttpServletRequest req = ServletActionContext.getRequest();
        String ipaddr = getRemoteIpAddr(req);//获取系统操作远程ip
        String userName = (String) req.getSession().getAttribute("usrName");//登录用户
        log.loger.info("ipaddr="+ipaddr+"userName="+userName);
        String actionClass = invocation.getProxy().getAction().getClass().getName();
        if(actionClass.indexOf("$") != -1){
            actionClass = actionClass.substring(0, actionClass.indexOf("$"));
        }
        if(actionClass.indexOf(".") != -1){
            actionClass = actionClass.substring(actionClass.lastIndexOf(".")+1);
        }
        String actionName = invocation.getProxy().getActionName();

        String url="";
        if(StringUtil.isNotBlank(req.getQueryString())){
            url = req.getRequestURI()+"?"+URLDecoder.decode(req.getQueryString(),"UTF-8");
        }else{
            url = req.getRequestURI();
        }

        log.loger.info("actionClass="+actionClass+" actionName="+actionName+" url="+url);
        Date startTime = new Date();
        try{
            //实际方法执行阶段
            invocation.invoke();
        }catch(Exception exception){

        }finally{
//          log.loger.info("operation intercept end!");
            if(!isNoRecordResource(actionName)){
//              log.loger.info("save action log start!");
                Date endTime = new Date();
                long costTime = endTime.getTime() - startTime.getTime();
                //生成一条用户操作记录
                SysOperationLogManager sysOperationLogManager = (SysOperationLogManager) SpringUtil.getObject("sysOperationLogManager");
                sysOperationLogManager.saveSysOperationLog(userName,actionClass,actionName,url,ipaddr,startTime,endTime,costTime,SysOpConstant.SYS_LOG_ACTION);
            }
        }
        return null;
    }

    //是否是无需记录的Action日志类型
    private  boolean isNoRecordResource(String actionName){
        String methodName = actionName.split("_")[1];
        for(int i=0;i<unRecordLogResources.length;i++){
             if(StringUtils.equals(methodName, unRecordLogResources[i])) {
                return true;
             }
        }
        return false;
    }


    protected String getRemoteIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }

         if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
             ip= request.getHeader("HTTP_X_FORWARDED_FOR");
         }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
            try {
                ip= InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return ip.split(",")[0];

    }
}
    <!-- 用户拦截器定义在该元素下 -->  
<interceptors>  
  <interceptor name="operationInterceptor" class="com.teraee.tasystem.interceptor.OperationInterceptor" />  
  <interceptor-stack name="defualtSecurityStackWithAuthentication">  
    <interceptor-ref name="defaultStack" />  
    <interceptor-ref name="operationInterceptor" />  
  </interceptor-stack>  
</interceptors>

4、效果截图

点击系统查询用户列表生成系统操作日志
进入拦截器获取到执行的方法名以及Action等
这里写图片描述
这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值