利用Java Annotation 和 Spring AOP实现在Controller层面的操作日志记录

Annotation,Spring,AOP之类的概念这里就不在介绍了,网上的相关知识一搜在大堆,而且也是各大公司面试之必考内容。目前AOP技术的应用场景中应该很大一部分是用来实现操作日志记录的,由于每个公司几乎都有自己的开发框架,而且很多框架都对CRUD之类的操作进行了高度封装,Service层面几乎省去了90%的代码,这样利用AOP记录每个模块的CRUD操作变得有些麻烦,下面分享一种利用Annotation在Controller层面记录日志的方法:

1.首页创建一个Annotation类

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

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Traced {
	String name() default "";// 默认为空
}

2.创建核心AOP操作类:ControllerTraceAspect

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;


@Aspect
public class ControllerTraceAspect{
	protected Logger logger = LoggerFactory.getLogger(getClass());

	/**
	*所有查询方法
	*/
	@Around("execution(* org.tshark.core.orm.hibernate.EntityManager.search(..)) ")
	public Object searchAground(ProceedingJoinPoint pjp) throws Throwable {
		if (TraceContextHolderFactory.getTraceContextHolder().getContext() == null) {
			return pjp.proceed();
		} else {
			return doAround(null, getUserCode(), getRemoteHost(), pjp);
		}
	}

	//只对Controller进行pointcut
	@Pointcut("within(@org.springframework.stereotype.Controller *)")
	public void controllerPointcut() {

	}

	/**
	 * 对有@Traced标记的方法,记录其执行参数及返回结果.
	 */
	@Pointcut("@annotation(org.tshark.framework.trace.Traced)")
	public void tracedMethodPointcut() {
	}

	@Around("controllerPointcut() && tracedMethodPointcut()")
	public Object traceAround(ProceedingJoinPoint pjp) throws Throwable {
		return doAroundController(pjp);
	}

	private Object doAroundController(ProceedingJoinPoint pjp) throws Throwable {
		String methodName = pjp.getSignature().getName();
		Object[] args = pjp.getArgs();
		Class[] argsClazz = new Class[args.length];
		//Controller中所有方法的参数,前两个分别为:Request,Response
		argsClazz[0] = HttpServletRequest.class;
		argsClazz[1] = HttpServletResponse.class;
		//第三个为保存中的上传的Model
		if (args.length == 3) {
			argsClazz[2] = args[2].getClass();
		}
		Traced tracedAnnotation = AnnotationUtils.findAnnotation(pjp.getTarget().getClass().getDeclaredMethod(methodName, argsClazz),
				Traced.class);
		String traceName = tracedAnnotation.name();
		return doAround(traceName, getUserCode(), getRemoteHost(), pjp);
	}

	//获取当前登录用户
	private String getUserCode() {
		String userCode = "_system";
		Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		if (principal != null && principal instanceof UserDetails) {
			userCode = ((UserDetails) principal).getUsername();
		}
		return userCode;
	}

	//获取当前用户IP
	private String getRemoteHost() {
		String host = null;
		WebAuthenticationDetails authDetails = (WebAuthenticationDetails) SecurityContextHolder.getContext().getAuthentication()
				.getDetails();
		if (authDetails != null) {
			host = authDetails.getRemoteAddress();
		}
		return host;
	}

	private String getOperateContext(Object[] args) {
		StringBuffer strBuffer = new StringBuffer();
		for (int i = 0; i < args.length; i++) {
			if(i==2){//第三个参数为Model
				strBuffer.append(ToStringBuilder.reflectionToString(args[i]));
			}
		}
		return strBuffer.toString();
	}

	protected Object doAround(String traceName, String currUser, String host, ProceedingJoinPoint pjp) throws Throwable {
		//日志记录
	}
}

3.Spring 配置文件

web.xml中的配置

	<servlet>
		<servlet-name>TS-Dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath*:action-servlet.xml</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>TS-Dispatcher</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>

action-servlet.xml中的相关配置(以下配置必须放在 action-servlet.xml不能放在service的配置文件中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"
	default-lazy-init="true">

   	<context:component-scan base-package="org.tshark.**.action" />

	<aop:aspectj-autoproxy proxy-target-class="true" >
		<aop:include name="controllerAspect" />
	</aop:aspectj-autoproxy>

	<bean id="controllerAspect" class="org.tshark.framework.trace.ControllerTraceAspect" />

4.使用方法,在需要记录的Controller上加上 @Traced(name="基础管理>用户管理:新增或修改用户")

例如:
@Traced(name="基础管理>用户管理:新增或修改用户")
@RequestMapping(value = "/save", method = RequestMethod.POST)
public void save(HttpServletRequest request, HttpServletResponse response, UserModel userModel) throws Exception {

。。。

}

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值