【Java EE 学习 76 下】【数据采集系统第八天】【通过AOP实现日志管理】【日志管理功能分析和初步实现】
一、日志管理相关分析
1.日志管理是一种典型的系统级别的应用,非常适合使用spring AOP实现。
2.使用日志管理的目的:对系统修改的动作进行记录,比如对权限、角色、用户的写操作、修改操作、删除操作等
3.确定使用的通知方式:使用环绕通知。复习一下环绕通知,所谓环绕通知实际上就是AOP代理对接口中声明方法的执行进行拦截,在执行方法之前或者之后进行一些操作,在日志管理功能模块中,我们对Service接口中声明的方法进行拦截,如果是对系统进行的修改操作的方法,则将方法执行之后就需要将相关信息保存下来方便以后查看,比如是谁登陆的系统进行的修改(最重要),执行的是什么方法,方法的参数是什么,执行成功额还是失败了,方法的返回值是什么,执行方法的时间是什么等等。
4.日志管理功能在系统中的体现:单击导航菜单中的"日志管理"超链接,查看所有的系统的变更历史记录。
二、日志实体和相关类的书写
1.根据一种的分析,得到了以下的日志实体
public class Log {
private String logId; //日志消息标识ID
private String operator=""; //操作人
private Date operatorDate=new Date(); //操作日期
private String operatorName; //操作的名称(方法名)
private String operateParams; //操作参数
private String operateResult=""; //操作结果(success|failure)
private String resultMessage=""; //结果消息
}
2.DAO类的书写和Service的书写略。
3.创建日志切面
日志切面提供了保存保存日志的详细方法(通知),该方法将会拦截目标方法的执行并且记录该方法执行过程中的详细信息。
package com.kdyzm.aspect; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import org.apache.struts2.ServletActionContext;
import org.aspectj.lang.ProceedingJoinPoint; import com.kdyzm.domain.Log;
import com.kdyzm.domain.User;
import com.kdyzm.service.LogService;
import com.kdyzm.utils.StringUtils; public class Logger {
private LogService logService;
public LogService getLogService() {
return logService;
}
public void setLogService(LogService logService) {
this.logService = logService;
}
//通知方法
public Object record(ProceedingJoinPoint joinPoint) throws Throwable{
Log log=new Log();
try{
//获取操作人
HttpServletRequest request=ServletActionContext.getRequest();
if(request!=null){
HttpSession session=request.getSession();
User user=(User) session.getAttribute("user");
if(user!=null){
log.setOperator(user.getUserId()+"-"+user.getEmail());//设置操作人
}
} //设置方法名
String methodName=joinPoint.getSignature().getName();
log.setOperatorName(methodName); //获取参数列表
Object[] params=joinPoint.getArgs();
log.setOperateParams(StringUtils.arr2String(params)); //操作结果和结果消息的获取
Object obj=joinPoint.proceed();
log.setOperateResult("SUCCESS"); if(obj!=null){
log.setResultMessage(obj.toString());
}
return obj; //返回执行结果
}catch(Exception e){
log.setOperateResult("FAILURE");
log.setResultMessage(e.getMessage());
}finally{
logService.saveLog(log);
}
return null;
}
}
4.配置spring配置文件applicationConext.xml
(1)首先将切面注入到spring容器
<bean id="logger" class="com.kdyzm.aspect.Logger">
<property name="logService" ref="logService"></property>
</bean>
(2)在aop配置中声明切入点表达式,表示对那些方法进行日志记录
注意这些方法都在事务通知上有定义,但是不能直接使用事务通知中的声明,因为还有不同之处:必须刨除掉logService中的所有方法,否则最后肯定会抛出堆栈溢出的异常。
分析原因:logService中的记录方法本身也是写操作(默认加上了事务),如果是写操作按照规则是需要写入日志表的,但是写入的时候又被AOP日志代理拦截,每次想写的时候都被日志AOP代理拦截,最终这种无限递归方式就会导致堆栈溢出,注意以下的切入点表达式的写法已经将logService刨除掉了。
<aop:pointcut
expression="(execution(* *..*Service.save*(..))
or execution(* *..*Service.update*(..))
or execution(* *..*Service.delete*(..))
or execution(* *..*Service.batch*(..))
or execution(* *..*Service.create*(..))
or execution(* *..*Service.new*(..))) and !bean(logService)"
id="loggerPointcut" />
(3)切面配置,声明使用哪个切面中的哪些方法使用何种通知方式在指定的切入点上织入到目标对象
<aop:aspect id="loggerAspect" ref="logger" order="1">
<aop:around method="record" pointcut-ref="loggerPointcut" />
</aop:aspect>
这里的意思是使用logger切面,使用切面中的record方法以环绕通知的方式在loggerPointcut指定的切入点上织入到目标对象(Service对象)。
5.显示所有日志列表
基本显示是没有什么问题的,但是这里使用了静态调用的方法,可以直接在jsp页面调用某个类的静态方法,这里由于可能会出现参数名称过长的问题,必须在在这里对显示的长度进行限制。
(1)com.kdyzm.utils.StringUtils类中定义静态方法setTagContentLimitLength,默认长度为15,也就是说最多只是显示15个字符。
//通过jsp页面的静态调用可以直接调用某个类的某个方法
public static String setTagContentLimitLength(String string){
int length=15;
System.out.println("访问了setTagContentLimitLength方法!"+string);
if(string !=null){
if(string.length()>length){
return string.substring(0,length)+"......";
}else{
return string;
}
}
return "";
}
(2)在jsp页面中调用,调用新式:<s:property value="@类的全名@方法名(参数列表)"/>
<s:iterator value="%{#logList}" status="st">
<tr>
<td><s:property value="operator" /></td>
<td><s:property value="operatorName" /></td>
<td><s:property value="@com.kdyzm.utils.StringUtils@setTagContentLimitLength(operateParams)" /></td>
<td><s:property value="operateResult" /></td>
<td><s:property value="resultMessage" /></td>
<td><s:date name="operatorDate" format="yyyy/MM/dd HH:mm:ss" /></td>
</tr>
</s:iterator>
(3)如果只是以上两步肯定还会报错,因为strutrs2默认禁用静态调用,需要在配置文件中开启,这里为了方便起见,直接使用了struts.properties进行了配置
struts.i18n.encoding=UTF-8
struts.action.extension=action,,
struts.serve.static.browserCache=false
struts.i18n.reload=true
struts.configuration.xml.reload=true
struts.devMode=true
struts.ui.theme=simple
struts.enable.DynamicMethodInvocation=true
struts.multipart.maxSize=2097152
struts.ognl.allowStaticMethodAccess=true
三、测试日志
1.新建调查之后查看日志:

2.将新建的调查删除掉之后:

【Java EE 学习 76 下】【数据采集系统第八天】【通过AOP实现日志管理】【日志管理功能分析和初步实现】的更多相关文章
- 【Java EE 学习 69 下】【数据采集系统第一天】【实体类分析和Base类书写】
之前SSH框架已经搭建完毕,现在进行实体类的分析和Base类的书写.Base类是抽象类,专门用于继承. 一.实体类关系分析 既然是数据采集系统,首先调查实体(Survey)是一定要有的,一个调查有多个 ...
- 【Java EE 学习 74 下】【数据采集系统第六天】【使用Jfreechart的统计图实现】【将JFreechart整合到项目中】
之前说了JFreechart的基本使用方法,包括生成饼图.柱状统计图和折线统计图的方法.现在需要将其整合到数据采集系统中根据调查结果生成三种不同的统计图. 一.统计模型的分析和设计 实现统计图显示的流 ...
- 【Java EE 学习 67 下】【OA项目练习】【SSH整合JBPM工作流】【JBPM项目实战】
一.SSH整合JBPM JBPM基础见http://www.cnblogs.com/kuangdaoyizhimei/p/4981551.html 现在将要实现SSH和JBPM的整合. 1.添加jar ...
- 【Java EE 学习 79 下】【动态SQL】【mybatis和spring的整合】
一.动态SQL 什么是动态SQL,就是在不同的条件下,sql语句不相同的意思,曾经在“酒店会员管理系统”中写过大量的多条件查询,那是在SSH的环境中,所以只能在代码中进行判断,以下是其中一个多条件查询 ...
- 【Java EE 学习 76 上】【数据采集系统第八天】【角色授权】【用户授权】【权限的粗粒度控制】【权限的细粒度控制】
一.角色管理 单击导航栏上的"角色管理"超链接,跳转到角色管理界面,在该界面上显示所有角色,并提供角色的增加和删除.修改超链接. 1.增加新角色(角色授权) 流程:单击增加新角色超 ...
- 【Java EE 学习 77 下】【数据采集系统第九天】【使用spring实现答案水平分库】【未解决问题:分库查询问题】
之前说过,如果一个数据库中要存储的数据量整体比较小,但是其中一个表存储的数据比较多,比如日志表,这时候就要考虑分表存储了:但是如果一个数据库整体存储的容量就比较大,该怎么办呢?这时候就需要考虑分库了, ...
- 【Java EE 学习 75 下】【数据采集系统第七天】【二进制运算实现权限管理】【使用反射初始化权限表】【权限捕获拦截器动态添加权限】
一.使用反射动态添加权限 在该系统中,我使用struts2的时候非常规范,访问的Action的形式都是"ActionClassName_MethodName.action?参数列表" ...
- 【Java EE 学习 72 下】【数据采集系统第四天】【移动/复制页分析】【使用串行化技术实现深度复制】
一.移动.复制页的逻辑实现 移动.复制页的功能是在设计调查页面的时候需要实现的功能.规则是如果在同一个调查中的话就是移动,如果是在不同调查中的就是复制. 无论是移动还是复制,都需要注意一个问题,那就是 ...
- 【Java EE 学习 71 下】【数据采集系统第三天】【分析答案实体】【删除问题】【删除页面】【删除调查】【清除调查】【打开/关闭调查】
一.分析答案实体 分析答案实体主要涉及到的还是设计上的问题,技术点几乎是没有的.首先需要确定一下答案的格式才能最终确定答案实体中需要有哪些属性. 答案格式的设计是十分重要的,现设计格式如下: 在表单中 ...
随机推荐
- 【原】聊一聊 url 编码问题
最近项目中遇到需要编码的一个问题,在encode和encodeURIComponent上绕了个小圈,所以打算总结一下js的编码问题,网上也有很多类似的文章,不过呢,总结出来的东西才是自己滴 为什么需要 ...
- Généralement c'est un mélange qui me devient personnellement
Parmi mes plus grands problèmes personnels avec maisons de rue conventionnelles est en fait ils sont ...
- [Unity3D]UI界面之瞄准镜设置说明
9空格设计 : 比如说4个角的图案固定,拉伸的时候不受影响 通过设置 左上右下来: 通过创建Image对象,将设置好的图片关联到Source Image 调整瞄准镜跟随飞机, 注意这里设置的Z轴向量是 ...
- yii2 开源插件与系统
yii2干货集:https://github.com/forecho/awesome-yii2 商城 samdark/yii2-shop composer global require "f ...
- beaglebone black 安装QNX过程
首先去http://community.qnx.com/sf/go/projects.bsp/frs.texas_instruments_am335_beaglebo 把下面4个下载下来.
- Linux 平台GCC使用小结
gcc -Wall [-I search_headfile_path] [-L search_lib_path] sourcefile -lNAME -o exe-name -Wall选项打开所有最常 ...
- webstorm ES6 转 ES5
一句话总结:用WebStorm自带的File Watcher功能+Babel实现自动转换ECMAScript 6代码为ES5代码 1. 新建一个Empty Project,然后在src目录下新建了一个 ...
- noi前机房日常
2015/6/16 上午a了一道省选分组赛day1t2,并在cf100553H双倍经验,好评 bzoj3152(ctsc2013)贪心,用priority_queue要清空 bx2k上午交了几十题,他 ...
- C#操作日志
首先引用NLog的dll文件 using System.IO; using NLog; -------------------------------------------------------- ...
- bzoj4349: 最小树形图
最小树形图模板题…… 这种\(O(nm)\)的东西真的能考到么…… #include <bits/stdc++.h> #define N 60 #define INF 1000000000 ...