利用spring AOP实现操作日志功能

19 篇文章 0 订阅
15 篇文章 0 订阅

首先需要在spring配置文件中配置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:task="http://www.springframework.org/schema/task"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/task
        http://www.springframework.org/schema/task/spring-task.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/websocket
        http://www.springframework.org/schema/websocket/spring-websocket.xsd"
        >
        
    <aop:aspectj-autoproxy/>       <!-- aop支持 -->
    <mvc:annotation-driven conversion-service="conversionService"/>       <!-- mvc支持 -->
<!-- <mvc:resources mapping="/assets/**" location="/assets/"/>
<mvc:resources mapping="/404/**" location="/404/"/>
<mvc:resources mapping="/awxj/**" location="/awxj/"/>
<mvc:resources mapping="/CameraPhoto/**" location="/CameraPhoto/"/>
<mvc:resources mapping="/docs/**" location="/docs/"/>
<mvc:resources mapping="/html/**" location="/html/"/>
<mvc:resources mapping="/QrImages/**" location="/QrImages/"/>
<mvc:resources mapping="/uploadfile/**" location="/uploadfile/"/> -->

    <tx:annotation-driven transaction-manager="transactionManager"/>        <!-- 事务管理支持 -->
    <context:component-scan base-package="com.wxj233"/><!-- 注解支持,添加要扫描的包 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
    </bean>   <!-- 视图解析器 -->
    
    <!-- 定时任务注解支持 -->
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>

    <import resource="classpath:/hibernate_spring.cfg.xml"/><!-- 导入hibernate配置 -->
    <bean id="transactionManager"
            class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean><!-- 事务管理器 -->

    <bean id="conversionService"
            class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
            <property name="converters">
            <set>
                <ref bean="stringToEnumConverter"/>
                <ref bean="stringToIntegerLIstConverter"/>
            </set>
        </property>
    </bean><!-- 数据格式转换器 -->
<bean id="multipartResolver"
        class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean><!-- 文件上传支持 -->

	<websocket:handlers>
        <websocket:mapping path="/socket/qr.do" handler="qrWebSocket"/>
    </websocket:handlers>

</beans>

其中

xmlns:aop="http://www.springframework.org/schema/aop"

http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd


<aop:aspectj-autoproxy/>       <!-- aop支持 -->

为aop配置部分,
声明注解,我使用的是利用注解的方式插入切面,我声明了两个注解如下:
@AfterOperation注解和@BeforeOperation注解

package com.wxj233.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 使用该标签会自动在函数执行完成之后执行日志记录
 * @author wxj233
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterOperation {

	/**
	 * 描述
	 * @return
	 */
	String value() default "";
}
package com.wxj233.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 使用该标签会自动在函数执行完成之前执行日志记录
 * @author wxj233
 *
 */
@Retention(RetentionPolicy.RUNTIME)  //注解声明周期为源文件、class文件及运行时三个时间段都存在
@Target(ElementType.METHOD)  //注解仅用于方法上
public @interface BeforeOperation {

	/**
	 * 描述
	 * @return
	 */
	String value() default "";
}

声明切面如下:
 

package com.wxj233.AOP;

import java.lang.reflect.Method;
import java.util.Date;

import javax.servlet.http.HttpSession;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.wxj233.annotations.AfterOperation;
import com.wxj233.annotations.BeforeOperation;
import com.wxj233.entity.OperationRecord;
import com.wxj233.entity.User;
import com.wxj233.service.OperationRecordService;

@Component
@Aspect
public class OperationRecords {
	
	@Autowired
	HttpSession httpsession;
	@Autowired
	OperationRecordService operationRecordService;

	@Before("@annotation(com.wxj233.annotations.BeforeOperation)")
	public void beforeOperation(JoinPoint jp) {
		MethodSignature methodSignature = (MethodSignature)jp.getSignature();
		Method method = methodSignature.getMethod();
		String operationContent = method.getAnnotation(BeforeOperation.class).value();
		
		User user = (User) httpsession.getAttribute("user");
		if(user != null) {
			OperationRecord operationRecord = new OperationRecord();
			operationRecord.setUser(user);
			operationRecord.setDate(new Date());
			operationRecord.setOperationContent(operationContent);
			operationRecordService.operationRecordSave(operationRecord);
		}
	}
	
	@After("@annotation(com.wxj233.annotations.AfterOperation)")
	public void afterOperation(JoinPoint jp) {
		MethodSignature methodSignature = (MethodSignature)jp.getSignature();
		Method method = methodSignature.getMethod();
		String operationContent = method.getAnnotation(AfterOperation.class).value();
		
		User user = (User) httpsession.getAttribute("user");
		if(user != null) {
			OperationRecord operationRecord = new OperationRecord();
			operationRecord.setUser(user);
			operationRecord.setDate(new Date());
			operationRecord.setOperationContent(operationContent);
			operationRecordService.operationRecordSave(operationRecord);
		}
		
		
		//System.out.println(operationRecord.getId());
	}
}

在control方法上插入如下:
 

package com.wxj233.control;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.wxj233.annotations.AfterOperation;
import com.wxj233.bean.RespResult;
import com.wxj233.dto.FiledPropertyDto;
import com.wxj233.entity.FiledProperty;
import com.wxj233.service.FiledService;

/**
 * 字段
 * @author wxj233
 *
 */
@Controller
@RequestMapping("/filed")
public class FiledControl {
	
	@Autowired
	FiledService filedService;

	/**
	 * 添加字段
	 * @return
	 */
	@RequestMapping("/add")
	@ResponseBody
	@AfterOperation("添加字段")
	RespResult filedAdd(FiledProperty filedProperty, Integer parentid) {
		
		FiledProperty filed = filedService.addFiled(filedProperty, parentid);
		RespResult resp = new RespResult();
		if(filed != null) {
			resp.setFlag(true);
			resp.getData().put("filed", filed);
		}else {
			resp.setFlag(false);
		}
		
		return resp;
	}
	
	@RequestMapping("/edit")
	@ResponseBody
	@AfterOperation("编辑字段")
	RespResult filedEdit(FiledProperty filedProperty) {
		FiledPropertyDto newfiled = filedService.geteditFiledDto(filedProperty);
		RespResult resp = new RespResult();
		
		if(newfiled != null) {
			resp.setFlag(true);
			resp.getData().put("filed", newfiled);
		}else {
			resp.setFlag(false);
		}
		return resp;
	}
	
	@RequestMapping("/delete")
	@ResponseBody
	@AfterOperation("删除字段")
	RespResult filedDelete(Integer[] filedIds) {
		RespResult resp = new RespResult();
		
		if(filedIds.length == 0) {
			resp.setFlag(false);
			return resp;
		}
		
		if(filedService.deleteFileds(filedIds)) {
			resp.setFlag(true);
		}else {
			resp.setFlag(false);
		}
		return resp;
	}
}

实现效果如下:

用户所有的操作都被记录了下来,仅需要在控制器上加入一个自定义注解就能实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楼兰小石头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值