利用spring AOP實現操作日誌功能

首先需要在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;
	}
}

實現效果如下:

用戶所有的操作都被記錄了下來,僅需要在控制器上加入一個自定義註解就能實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章