转载;https://blog.csdn.net/ma451152002/article/details/77234236
Jeecg中通过Spring_AOP+
注解方式实现日志的管理
一、设计思路
通过spring的aop切面功能,拦截到请求的所有的符合切面表达式的方法,判断是否含有注解标志,生成日志对象,然后通过aop的后置通知进行日志的持久化。
二、代码实现
1、工程结构:
2、pom.xml增加aop依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>
4.1.
7.RELEASE</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>
1.5.
3</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>
1.8.
4</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>
1.0</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>
3.2.
4</version>
</dependency>
3、定义我们的Log实体对象
package aop;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.GenericGenerator;
import org.jeecgframework.core.common.entity.IdEntity;
@Entity
@Table(name=
"assess_log_test")
@DynamicInsert(true)
@DynamicUpdate(true)
@SuppressWarnings("serial")
public class Log implements java.io.Serializable{
/**
* 日志id
*/
private String id;
/**
* 当前操作人id
*/
private String loginAccount;
/**
* 当前操作人ip
*/
private String loginIp;
/**
* 操作请求的链接
*/
private String actionUrl;
/**
* 执行的模块
*/
private String module;
/**
* 执行的方法
*/
private String method;
/**
* 执行操作时间
*/
private Long actionTime;
/**
* 描述
*/
private String description;
/**
* 执行的时间
*/
private Date gmtCreate;
/**
* 该操作状态,1表示成功,-1表示失败!
*/
private Short state;
@Id
@GeneratedValue(generator =
"paymentableGenerator")
@GenericGenerator(name=
"paymentableGenerator",strategy=
"uuid")
@Column(name=
"id",nullable=
false,length=
32)
public String getId() {
return id;
}
@Column(name=
"login_account",length=
32)
public String getLoginAccount() {
return loginAccount;
}
@Column(name=
"login_ip",length=
32)
public String getLoginIp() {
return loginIp;
}
@Column(name=
"action_url",length=
100)
public String getActionUrl() {
return actionUrl;
}
@Column(name=
"module",length=
32)
public String getModule() {
return module;
}
@Column(name=
"method",length=
32)
public String getMethod() {
return method;
}
@Column(name=
"action_time")
public Long getActionTime() {
return actionTime;
}
@Column(name=
"description",length=
200)
public String getDescription() {
return description;
}
@Column(name=
"gmt_create")
public Date getGmtCreate() {
return gmtCreate;
}
@Column(name=
"state")
public Short getState() {
return state;
}
public void setId(String id) {
this.id =
id;
}
public void setLoginAccount(String loginAccount) {
this.loginAccount =
loginAccount;
}
public void setLoginIp(String loginIp) {
this.loginIp =
loginIp;
}
public void setActionUrl(String actionUrl) {
this.actionUrl =
actionUrl;
}
public void setModule(String module) {
this.module =
module;
}
public void setMethod(String method) {
this.method =
method;
}
public void setActionTime(Long actionTime) {
this.actionTime =
actionTime;
}
public void setDescription(String description) {
this.description =
description;
}
public void setGmtCreate(Date gmtCreate) {
this.gmtCreate =
gmtCreate;
}
public void setState(Short state) {
this.state =
state;
}
@Override
public String toString() {
return "Log [id=" + id +
", loginAccount=" +
loginAccount
+
", loginIp=" + loginIp +
", actionUrl=" +
actionUrl
+
", module=" + module +
", method=" + method +
", actionTime="
+ actionTime +
", description=" + description +
", gmtCreate="
+ gmtCreate +
", state=" + state +
"]";
}
}
4.定义注解对象
package aop;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 日志记录
*
* @author mgj
* @date 2017-8-11 上午10:53:19
*/
@Target({ElementType.PARAMETER,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemLog {
String module() default "";
String methods() default "";
}
5.定义aop界面拦截方法
package aop;
import java.lang.reflect.Method;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecgframework.core.util.ResourceUtil;
import org.jeecgframework.core.util.StringUtil;
import org.jeecgframework.web.system.pojo.base.TSUser;
import org.jeecgframework.web.system.service.SystemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import antlr.StringUtils;
@Component
@Aspect
public class LogAopAction {
private long BEGIN_TIME;
private long END_TIME;
private Log log =
new Log();
@Autowired
private SystemService systemService;
//@Pointcut("execution(* vote.backmanage.teachermanage.controller.AssessTeacherInfoController.*(..))")
//@Pointcut("execution(* vote.backmanage.teachermanage.controller.*.*(..))")
//@Pointcut("execution(* vote.backmanage.teachermanage.controller..*.*(..))")
@Pointcut(
"execution(* vote.backmanage.teachermanage.controller..*.*(..))")
public void controllerAspect(){}
@Before("controllerAspect()")
public void doBefore(){
BEGIN_TIME =
new Date().getTime();
}
@AfterReturning("controllerAspect()")
public void doAfter(){
if (log.getState() ==
1 || log.getState() == -
1) {
log.setActionTime(END_TIME -
BEGIN_TIME);
log.setGmtCreate(new Date(BEGIN_TIME));
System.out.println(log);
System.out.println(
"存入到数据库");
systemService.save(log);
}else {
System.out.println(log);
System.out.println(
"不存到数据库里");
}
}
@After("controllerAspect()")
public void after(){
END_TIME =
new Date().getTime();
}
@Around("controllerAspect()")
public Object around(ProceedingJoinPoint pjp) throws Throwable{
HttpServletRequest request =
((ServletRequestAttributes)RequestContextHolder.getRequestAttributes())
.getRequest();
//获得当前用户
TSUser user =
ResourceUtil.getSessionUserName();
String name =
user.getRealName();
log.setLoginAccount(name);
//拦截的实体类
Object target =
pjp.getTarget();
//拦截的方法名
String methodName =
pjp.getSignature().getName();
//拦截的方法参数
Object[] args =
pjp.getArgs();
//拦截的放参数类型
Signature sig =
pjp.getSignature();
MethodSignature msig =
null;
if (!
(sig instanceof MethodSignature)) {
throw new IllegalArgumentException(
"该注解只能用于方法");
}
msig =
(MethodSignature)sig;
Class[] parameterTypes =
msig.getMethod().getParameterTypes();
Object object =
null;
Method method =
null;
try{
method =
target.getClass().getMethod(methodName, parameterTypes);
}catch (Exception e) {
e.printStackTrace();
}
if (
null !=
method) {
if (method.isAnnotationPresent(SystemLog.
class)) {
//判断是否包含我们自定义的注解
SystemLog systemlog = method.getAnnotation(SystemLog.
class);
log.setModule(systemlog.module());
log.setMethod(systemlog.methods());
log.setLoginIp(getIp(request));
log.setActionUrl(request.getRequestURI());
try {
object =
pjp.proceed();
log.setDescription("执行成功");
log.setState((short)
1);
} catch (Exception e) {
log.setDescription("执行失败");
log.setState((short)-
1);
e.printStackTrace();
}
}else {
//不包自定义注解
object =
pjp.proceed();
log.setDescription("此操作不包含注解");
log.setState((short)
0);
}
}else {
//不需要拦截
object =
pjp.proceed();
log.setDescription("不需要拦截直接运行");
log.setState((short)
0);
}
return object;
}
/**
* 获得ip地址
* @param request
* @return
* @author mgj
* @date 2017-8-11 下午2:19:51
*/
private String getIp(HttpServletRequest request){
if (request.getHeader(
"x-forwarded-for") ==
null) {
return request.getRemoteAddr();
}
return request.getHeader(
"x-forwarded-for");
}
}
6.增加aop自动扫描配置
(1)打开spring-
mvc.xml文件,增加aop上下文
如下:
<?xml version=
"1.0" encoding=
"UTF-8"?>
<beans xmlns=
"http://www.springframework.org/schema/beans"
xmlns:mvc=
"http://www.springframework.org/schema/mvc"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:p=
"http://www.springframework.org/schema/p"
xmlns:context=
"http://www.springframework.org/schema/context"
xmlns:aop=
"http://www.springframework.org/schema/aop"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http:
//www.springframework.org/schema/beans/spring-beans-3.0.xsd
http:
//www.springframework.org/schema/context
http:
//www.springframework.org/schema/context/spring-context-3.0.xsd
http:
//www.springframework.org/schema/mvc
http:
//www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http:
//www.springframework.org/schema/aop
http:
//www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
(2)增加aop自动扫描并实例化bean
<aop:aspectj-autoproxy proxy-target-
class=
"true" />
<bean id=
"logAopAction" class=
"aop.LogAopAction"></bean>
7.持久化Log实体的xml配置,使用自动扫描class的形式进行配置。打开spring-mvc-hibernate.xml文件,增加<value>aop.</value>
<bean id=
"sessionFactory"
class=
"org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name=
"dataSource" ref=
"dataSource" />
<property name=
"entityInterceptor" ref=
"hiberAspect" />
<property name=
"hibernateProperties">
<props>
<!--<prop key=
"hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> -->
<prop key=
"hibernate.dialect">${hibernate.dialect}</prop>
<prop key=
"hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key=
"hibernate.show_sql">
true</prop>
<prop key=
"hibernate.format_sql">
false</prop>
<prop key=
"hibernate.temp.use_jdbc_metadata_defaults">
false</prop>
</props>
</property>
<!-- 注解方式配置 -->
<property name=
"packagesToScan">
<list>
<value>org.jeecgframework.web.system.pojo.*</value>
<value>org.jeecgframework.web.demo.entity.*</value>
<value>org.jeecgframework.web.test.entity.*</value>
<value>org.jeecgframework.web.cgform.entity.*</value>
<value>org.jeecgframework.web.cgreport.entity.*</value>
<value>aop.</value>
</list>
</property>
</bean>
8.使用注解方式,配置日志,在访问的controller方法上,增加@SystemLog(module=
"区教师库登录",methods=
"区教师库的assessTeacherInfo()方法")配置
/**
* 教师库管理列表 页面跳转
*
* @return
*/
@RequestMapping(params =
"assessTeacherInfo")
@SystemLog(module=
"区教师库登录",methods=
"区教师库的assessTeacherInfo()方法")
public ModelAndView assessTeacherInfo(HttpServletRequest request) {
return new ModelAndView(
"vote/backmanage/teachermanage/assessTeacherInfoList");
}
9.效果
三、注意事项
1.增加aop自动扫描包时,必须写到spring-mvc.xml内,不可写到spring-mvc-aop.xml文件中。因为spring-mvc.xml会比spring-mvc-
aop.xml文先执行。
2.持久化Log实体,使用自动扫描class的形式进行配置时,规则如下
(1)<value>aop.</value>,会解析为aop
/*.class 或者 aop/xxx/*.class。即aop的包以及子包下的所有class。
(2)<value>aop</value>,会解析为aop/*.class 。即aop的包下的所有class。
(3)<value>aop.*</value>,会解析为 aop/xxx/*.class。即aop的子包下的所有class。
四、思考
1.需要深刻理解spring_mvc.xml文件的执行顺序。
2.需要深刻理解使用自动扫描class的形式的配置规则。
---------------------------------------------------------------------------
附录:
Log实体创建的mysql脚本:
drop table if exists assess_log_test;
create table assess_log_test (
id varchar(32) not null COMMENT '主键id',
login_account varchar(32) default null comment '当前操作人',
login_ip varchar(32) default null comment '登录ip',
action_url varchar(100) default null comment '请求url',
module varchar(32) default null comment '执行模块',
method varchar(32) default null comment '执行方法',
action_time bigint default 0 comment '执行操作时间',
description varchar(200) default null comment '描述',
gmt_create datetime default null comment '执行时间',
state smallint(6) default null comment '操作状态',
primary key (id)
)engine=innodb default charset=utf8 comment '操作日志表';
转载于:https://www.cnblogs.com/Jeely/p/11310490.html
相关资源:JAVA上百实例源码以及开源项目