利用spring AOP实现操作日志功能
程序员文章站
2022-07-12 14:50:30
...
首先需要在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;
}
}
实现效果如下:
用户所有的操作都被记录了下来,仅需要在控制器上加入一个自定义注解就能实现。
上一篇: 梯度下降与最小二乘