• 前言

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

  • 什么拦截器?

  拦截器是动态拦截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执行前后运行。

  • 项目实现拦截器代码
 package com.mnsn.utils;

 import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.Calendar;
import java.util.Map;
import java.util.Set; import org.apache.struts2.ServletActionContext; import com.mnsn.project.user.User;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.interceptor.PreResultListener; /**
* 系统日志拦截器
* @AUTHER LiuLonglong
* @Motto Goals determine what you are going to be.
* @URL http://www.cnblogs.com/mvilplss/
* @Time 下午04:09:37
* @Version
*/
public class Dolog implements Interceptor { private static final long serialVersionUID = 1L; public String intercept(ActionInvocation ai) throws Exception { ai.addPreResultListener(new PreResultListener() { public void beforeResult(ActionInvocation ai, String arg1) {
try {
StringBuffer sb = new StringBuffer();
sb.append(MyUtils.getDataYmdhms2() + ":");
Map<String, Object> session = ai.getInvocationContext().getSession();
User user = (User) session.get("loginUser");
if (user != null) {
sb.append("操作人:" + user.getName());
} else {
sb.append("操作人:系统未获取");
}
sb.append("类名:" + ai.getAction() + " ");
sb.append("方法名:" + ai.getInvocationContext().getName()+ " ");
Map<String, Object> map = ai.getInvocationContext().getParameters();
Set<String> keys = map.keySet();
sb.append("参数:");
for (String key : keys) {
sb.append(key + "=" + ((Object[]) map.get(key))[0]+ "#");
}
sb.append(" ");
sb.append("执行结果:" + ai.getResultCode() + " ");
String appPath = ServletActionContext.getServletContext().getRealPath("/");
saveLog(appPath + "operLog", sb.toString());
} catch (Exception e) {
e.printStackTrace();
} }
}); return ai.invoke();
} public static void saveLog(String dir, String content) {
try {
File path = new File(dir);
if (!path.exists()) {
path.mkdir();
}
File LogDir = new File(path + "/"
+ (Calendar.getInstance().get(Calendar.MONTH) + 1));
if (!LogDir.exists()) {
LogDir.mkdir();
}
File file = new File(LogDir + "/"
+ Calendar.getInstance().get(Calendar.DAY_OF_MONTH)
+ ".log");
if (!file.exists()) {
file.createNewFile();
}
BufferedWriter br = new BufferedWriter(new FileWriter(file, true));
br.write(content);
br.newLine();
br.flush();
br.close(); File LogDirOld = new File(
path
+ "/"
+ (Calendar.getInstance().get(Calendar.MONTH) - 2 > 0 ? (Calendar
.getInstance().get(Calendar.MONTH) - 2)
: Calendar.getInstance()
.get(Calendar.MONTH) + 10));
if (LogDirOld.exists()) {
File[] fileOlds = LogDirOld.listFiles();
for (File f : fileOlds) {
f.delete();
}
LogDirOld.delete();
}
} catch (Exception e) {
e.printStackTrace();
} } public void destroy() { } public void init() { }
}
  • 项目部分配置
<!-- 配置拦截器 -->
<interceptors>
<interceptor name="dolog" class="com.mnsn.utils.Dolog"></interceptor>
<interceptor-stack name="defaultStack">
<interceptor-ref name="dolog"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
  • 执行结果

取自于文件:C:\Program Files (x86)\tomcat-6.0.43-myeclipse\webapps\qzdl\operLog\3\10.log

20150310173309:操作人:系统未获取类名:com.mnsn.project.user.UserAction@b2c940 方法名:login 参数:loginname=ss#password=ss#x=31#y=11# 执行结果:pass
20150310173313:操作人:钦州老大类名:com.mnsn.project.user.UserAction@1a2157e 方法名:list 参数: 执行结果:list
20150310173322:操作人:钦州老大类名:com.mnsn.project.user.UserAction@108a2d1 方法名:delete 参数:users[0].id=402881ec4b38cf8f014b38d4510f0001# 执行结果:toList
20150310173323:操作人:钦州老大类名:com.mnsn.project.user.UserAction@13e3101 方法名:list 参数: 执行结果:list
20150310173326:操作人:钦州老大类名:com.mnsn.project.user.UserAction@158a9b 方法名:toOper 参数:user.id=402881fd4becf4d5014becf8253c0000# 执行结果:oper
20150310173328:操作人:钦州老大类名:com.mnsn.project.user.UserAction@174edfd 方法名:update 参数:toWhere=#user.createtime=2015-03-06 10:44:20.0#user.group.id=402881ef4a9f4536014a9f69be6c0005#user.id=402881fd4becf4d5014becf8253c0000#user.job=部门主管#user.loginname=wml#user.mobilephone=18758010019#user.name=王明路#user.office_telephone=0571-6856156#user.password=123456#user.remark=此人为部门管理员#user.unit.id=402881fd4becf4d5014bed053ce80001# 执行结果:toList
20150310173328:操作人:钦州老大类名:com.mnsn.project.user.UserAction@11efcc2 方法名:list 参数: 执行结果:list
  • 总结

  struts2的拦截器相对aspect来说还是比较容易上手和理解的,对于要求一般的系统操作日志可以采用拦截器,而aspect重要用于细粒度的控制方法的出口和入口,实现逻辑层的增强,例如声明式事物。

  • 备注

  本文在工作繁忙中码出来的,如有错误在所难免,望读者指出,谢谢!

Struts2拦截器记录系统操作日志的更多相关文章

  1. 运用Unity结合PolicyInjection实现拦截器[结合操作日志实例]

    上一篇文章我们通过Unity自身Unity.InterceptionExtension.IInterceptionBehavior实现一个有系统关异常日志记录:解决代码中到处充满的异常记录的代码: 本 ...

  2. 防止未登录用户操作—struts2拦截器简单实现(转)

    原文地址:http://blog.csdn.net/zhutulang/article/details/38351629 尊重原创,请访问原地址 一般,我们的web应用都是只有在用户登录之后才允许操作 ...

  3. 从struts2拦截器到自定义拦截器

    拦截器可谓struts2的核心了,最基本的bean的注入就是通过默认的拦截器实现的,一般在struts2.xml的配置中,package内直接或间接继承了struts-default.xml,这样st ...

  4. struts2 拦截器

    拦截器:对Action的访问.可以拦截到Action中某个方法.与过滤器不同,过滤器过滤的是请求.过滤JSP.html.但是拦截器不能拦截jsp.html的访问. Struts2 拦截器在访问某个 A ...

  5. Struts2拦截器的使用 (详解)

    Struts2拦截器的使用 (详解) 如何使用struts2拦截器,或者自定义拦截器.特别注意,在使用拦截器的时候,在Action里面必须最后一定要引用struts2自带的拦截器缺省堆栈default ...

  6. 基于SSH2框架Struts2拦截器的登录验证实现(转)

        大象在这里假设你已经弄清楚了Struts2拦截器的基本概念,可以进入实际运用了.那么我们在之前的基础上只需要做下小小的改变,就可以使用Struts2的拦截器机制实现登录的验证.     修改数 ...

  7. Struts2拦截器配置实例

    拦截器介绍 拦截器 的使用 ,源自Spring AOP(面向切面编程)思想 拦截器 采用 责任链 模式 * 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链. * 责任链每一个节 ...

  8. struts2拦截器interceptor的配置方法及使用

    转: struts2拦截器interceptor的配置方法及使用 (2015-11-09 10:22:28) 转载▼ 标签: it 365 分类: Struts2  NormalText Code  ...

  9. Struts2拦截器详解

    一.Struts2拦截器原理: Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的    拦截器对象,然后串成一个列 ...

随机推荐

  1. ArrayList源码解析(三)

    1.isEmpty()  如果此列表中没有元素,则返回 true /** * Returns <tt>true</tt> if this list contains no el ...

  2. JavaScript 闭包究竟是什么

    用JavaScript一年多了,闭包总是让人二丈和尚摸不着头脑.陆陆续续接触了一些闭包的知识,也犯过几次因为不理解闭包导致的错误,一年多了 资料也看了一些,但还是不是非常明白,最近偶然看了一下 jQu ...

  3. 009一对一 主键关联映射_单向(one-to-one)

    009一对一  主键关联映射_单向(one-to-one) ²  两个对象之间是一对一的关系,如Person-IdCard(人—身份证号) ²  有两种策略可以实现一对一的关联映射 主键关联:即让两个 ...

  4. 项目管理之 Objective-C 编码规范

    目录: 一.格式化代码 二.命名 命名要求 1. 类的命名: 规则: 大驼峰命名法,每个单词的首字母都采用大写字母.一般添加业务前缀.后缀一般是当前类的种类. ViewController:后缀:Vi ...

  5. Hadoop集群搭建(非HA)

    1.准备Linux环境 1.0先将虚拟机的网络模式选为NAT 1.1修改主机名 vi /etc/sysconfig/network NETWORKING=yes HOSTNAME=itcast ### ...

  6. MyBatis7:MyBatis插件及示例----打印每条SQL语句及其执行时间

    Plugins 摘一段来自MyBatis官方文档的文字. MyBatis允许你在某一点拦截已映射语句执行的调用.默认情况下,MyBatis允许使用插件来拦截方法调用 Executor(update.q ...

  7. java基础(十一章)

    一.理解什么是类和对象               万事万物皆对象 1.属性--对象具有的特征(特点) 2.方法--对象可执行的操作(能干什么事) 3.对象的定义: 是一个客观存在的,看的见或摸得着的 ...

  8. [Leetcode] Binary search--436. Find Right Interval

      Given a set of intervals, for each of the interval i, check if there exists an interval j whose st ...

  9. DNS全局负载均衡(GSLB)基本原理

    原理 DNS全局负载均衡通过智能DNS解析来实现,通常在不同的地区设立多个数据中心,每个数据中心又使用多个运营商的线路.目前很多DNS服务商都提供了智能DNS服务,智能DNS通常是利用各运营商分省IP ...

  10. JQuery源码阅读记录

    新建html文件,在浏览器中打开文件,在控制台输入consoole.log(window);新建html文件,引入JQuery后在浏览器中打开,在控制台同样输入consoole.log(window) ...