Jeecg中通过Spring_AOP+注解方式实现日志的管理

来源:互联网 发布:matlab2014b for mac 编辑:程序博客网 时间:2024/06/16 16:45
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;}@Overridepublic 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)@Documentedpublic @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@Aspectpublic class LogAopAction {private long BEGIN_TIME;private long END_TIME;private Log log = new Log();@Autowiredprivate 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/mvchttp://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 '操作日志表';




阅读全文
0 0
原创粉丝点击