利用springaop实现日志输出

需求:利用aop思想实现日志输出,加了注解的方法忽略打印日志,下面请看具体实现。

1.编写切面

注意:注意查看execution访问的方法修饰符,默认是方法public方法,如果是private需要手动修改。



package com.bandweaver.tunnel.common.platform.log;

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

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
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.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 com.bandweaver.tunnel.common.biz.itf.OperationLogService;
import com.bandweaver.tunnel.common.biz.itf.SecurityLogService;
import com.bandweaver.tunnel.common.biz.pojo.OperationLog;
import com.bandweaver.tunnel.common.biz.pojo.SecurityLog;
import com.bandweaver.tunnel.common.biz.pojo.User;
import com.bandweaver.tunnel.common.platform.constant.Constants;
import com.bandweaver.tunnel.common.platform.util.ContextUtil;
import com.bandweaver.tunnel.common.platform.util.DateUtil;

/**
 * ClassName: LogAspect
 * 
 * @Description: 日志切面
 * @author shaosen
 * @date 2018年5月16日
 */
@Aspect
@Component
public class LogAspect extends Log {

	@Autowired
	private OperationLogService operationLogService;
	@Autowired
	private SecurityLogService securityLogService;

	/**
	 * @Description: 配置切入点
	 * @param
	 * @return void
	 * @throws @author shaosen
	 * @date 2018年5月16日
	 */
	@Pointcut("execution (public * com.bandweaver.tunnel.controller..*.*(..))")
	public void controllerAspect() {
	}

	/**
	 * @Description: 前置通知
	 * @param @param joinPoint
	 * @return void
	 * @throws @author shaosen
	 * @date 2018年5月16日
	 */
	@Before("controllerAspect()")
	public void doBefore(JoinPoint joinPoint) {

		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();

		IgnoreLog annotation = checkAnnotation(joinPoint);
		if (annotation != null)
		return;

		// url
		String url = request.getRequestURL().toString();
		// method
		String req_method = request.getMethod();
		// ip
		String req_ip = request.getRemoteAddr();
		// 请求人
		String req_user = null;
		if (SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO) != null) {
			User user = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
			req_user = user.getName();
		}
		// 类方法
		String method = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
		// 参数
		Object[] arguments = joinPoint.getArgs();
		String params = "";
		for (int i = 0; i < arguments.length; i++) {// 获取参数
			params = params + arguments[i] + (i == arguments.length - 1 ? "" : " , ");
		}
		Log.info("------------------operation_log--------------------------");
		// 操作日志
		Log.info("url = " + url);
		Log.info("req_method = " + req_method);
		Log.info("req_ip = " + req_ip);
		Log.info("req_user = " + req_user);
		Log.info("method = " + method);
		Log.info("params = {" + params + "}");

		OperationLog optLog = new OperationLog();
		optLog.setId(UUID.randomUUID().toString().replaceAll("-", ""));
		optLog.setUrl(url);
		optLog.setReqMethod(req_method);
		optLog.setReqIp(req_ip);
		optLog.setReqUser(req_user);
		optLog.setMethod(method);
		optLog.setParams(params);
		optLog.setCrtTime(DateUtil.getDate2String(new Date()));

		operationLogService.save(optLog);
		Log.info(" operation_log saved ! ");

		Set<String> security_req_role = ContextUtil.getLoginUserRole();
		Set<String> security_req_permission = ContextUtil.getLoginUserPermission();

		Log.info("------------------security_log--------------------------");
		// 安全日志
		Log.info("security_method = " + method);
		Log.info("security_req_user = " + req_user);
		if (security_req_role == null) {
			Log.info("security_req_role = " + null);
		} else {
			Log.info("security_req_role = " + security_req_role);
		}
		if (security_req_permission == null) {
			Log.info("security_req_permission = " + null);
		} else {
			Log.info("security_req_permission = " + security_req_permission);
		}

		SecurityLog scrtPojo = new SecurityLog();
		scrtPojo.setId(UUID.randomUUID().toString().replaceAll("-", ""));
		scrtPojo.setMethod(method);
		scrtPojo.setReqUser(req_user);

		if (security_req_role == null) {
			scrtPojo.setReqRole(null);
		} else {
			scrtPojo.setReqRole(ContextUtil.getLoginUserRole().toString());
		}
		if (security_req_permission == null) {
			scrtPojo.setReqPermission(null);
		} else {
			scrtPojo.setReqPermission(ContextUtil.getLoginUserPermission().toString());
		}

		scrtPojo.setCrtTime(new Date());
		securityLogService.save(scrtPojo);
		Log.info(" security_log saved ! ");

	}

	/**
	 * @Description: 获取注解
	 * @param @param joinPoint
	 * @param @return   
	 * @return IgnoreLog  
	 * @throws
	 * @author shaosen
	 * @date 2018年5月17日
	 */
	private IgnoreLog checkAnnotation(JoinPoint joinPoint) {

		Signature signature = joinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = methodSignature.getMethod();

		if (method != null) {
			return method.getAnnotation(IgnoreLog.class);
		}
		return null;
	}

	/**
	 * @Description: 使用这个注解可以得到执行方法之后的返回信息
	 * @param @param object
	 * @return void
	 * @throws @author shaosen
	 * @date 2018年5月16日
	 */
	@AfterReturning(returning = "object", pointcut = "controllerAspect()")
	public void doAfterReturning(Object object) {
		Log.info("response={" + object.toString() + "}");
	}

}

2.编写自定义注解,通过在方法上加注解来实现忽略日志输出。

package com.bandweaver.tunnel.common.platform.log;

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;

/**
 * ClassName: IgnoreLog
 * @Description: 忽略打印日志
 * @author shaosen
 * @date 2018年5月17日
 */
@Target({ElementType.PARAMETER, ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
public @interface IgnoreLog {
	
}

3.控制层代码,login方法上加了@IgnoreLog注解,logout上没有加,因为当登录的时候是没有日志输出的,而登出的时候是有日志输出的。

package com.bandweaver.tunnel.controller.common;


import com.alibaba.fastjson.JSONObject;
import com.bandweaver.tunnel.common.biz.dto.UserDTO;
import com.bandweaver.tunnel.common.platform.constant.Constants;
import com.bandweaver.tunnel.common.platform.constant.StatusCodeEnum;
import com.bandweaver.tunnel.common.platform.exception.BandWeaverException;
import com.bandweaver.tunnel.common.platform.log.IgnoreLog;
import com.bandweaver.tunnel.common.platform.log.Log;
import com.bandweaver.tunnel.common.platform.log.OLog;
import com.bandweaver.tunnel.common.platform.log.SLog;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.bandweaver.tunnel.common.biz.pojo.User;
import com.bandweaver.tunnel.common.platform.util.CommonUtil;

import java.util.Set;

@Controller
@ResponseBody
@RequestMapping("/login")
public class LoginController {


    /** 登录并返回用户
     * @param user
     * @return
     */
	@IgnoreLog
    @RequestMapping(value = "/auth", method = RequestMethod.POST, produces = "application/json; charset=UTF-8")
    public JSONObject login (User user){
        Subject subject= SecurityUtils.getSubject();
        UsernamePasswordToken token=new UsernamePasswordToken(user.getName(), user.getPassword());
        token.setRememberMe(true); 
        
        	//在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查    
            //每个Realm都能在必要时对提交的AuthenticationTokens作出反应    
            //所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法 
        	Log.info(" user[" + user.getName() + "]do login checking");    
            subject.login(token);
            Log.info(" user[" + user.getName() + "]authentication success");
            
            Session session=subject.getSession();
            session.setTimeout(3600000);
            Log.info(" sessionId:"+session.getId());
            Log.info(" sessionHost:"+session.getHost());
            Log.info(" sessionTimeout:"+session.getTimeout());
            Log.info(" sessionAttribute:" + session.getAttribute("userInfo").toString());
            Log.info(" sessionLastAccessTime:" + session.getLastAccessTime().toString());
            Log.info(" sessionStartTimestamp:" + session.getStartTimestamp().toString());

            UserDTO userDTO = new UserDTO((User)session.getAttribute(Constants.SESSION_USER_INFO));
            userDTO.setRoles((Set<String>)session.getAttribute(Constants.SESSION_USER_ROLE));
            userDTO.setPermissions((Set<String>)session.getAttribute(Constants.SESSION_USER_PERMISSION));
            return CommonUtil.returnStatusJson(StatusCodeEnum.S_10002, userDTO);
       
    }

    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public JSONObject Logout(){
        try {
            Subject currentUser = SecurityUtils.getSubject();
            currentUser.logout();

            return CommonUtil.returnStatusJson(StatusCodeEnum.S_10003);
        } catch (Exception e){

            return CommonUtil.returnStatusJson(StatusCodeEnum.E_400);
        }
    }


}

4.控制台输出结果如下,注意登录时输出的日志是自定义realm里的日志,并不是我logAspect类里的日志

[INFO ] 2018-05-17 15:44:59,589 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
 user[admin]do login checking
[INFO ] 2018-05-17 15:44:59,603 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
 user[admin]authentication success
[INFO ] 2018-05-17 15:44:59,604 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
 sessionId:BA2C1804E92DDF97A45C53DCE3087B6E
[INFO ] 2018-05-17 15:44:59,604 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
 sessionHost:0:0:0:0:0:0:0:1
[INFO ] 2018-05-17 15:44:59,604 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
 sessionTimeout:3600000
[INFO ] 2018-05-17 15:44:59,605 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
 sessionAttribute:User{id=1, name='admin', password='123456'}
[INFO ] 2018-05-17 15:44:59,606 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
 sessionLastAccessTime:Thu May 17 15:27:24 CST 2018
[INFO ] 2018-05-17 15:44:59,607 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
 sessionStartTimestamp:Thu May 17 15:27:24 CST 2018
[INFO ] 2018-05-17 15:44:59,608 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
response={{"msg":"登录成功","code":"10002","data":{"id":1,"name":"admin","permissions":["admin.*"],"roles":["admin"]}}}
[INFO ] 2018-05-17 15:45:06,972 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
------------------operation_log--------------------------
[INFO ] 2018-05-17 15:45:06,973 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
url = http://localhost:8080/MaxTunnel-Web/login/logout
[INFO ] 2018-05-17 15:45:06,974 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
req_method = GET
[INFO ] 2018-05-17 15:45:06,974 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
req_ip = 0:0:0:0:0:0:0:1
[INFO ] 2018-05-17 15:45:06,975 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
req_user = admin
[INFO ] 2018-05-17 15:45:06,976 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
method = com.bandweaver.tunnel.controller.common.LoginController.Logout
[INFO ] 2018-05-17 15:45:06,977 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
params = {}
[INFO ] 2018-05-17 15:45:06,987 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
 operation_log saved ! 
[INFO ] 2018-05-17 15:45:06,987 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
------------------security_log--------------------------
[INFO ] 2018-05-17 15:45:06,988 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
security_method = com.bandweaver.tunnel.controller.common.LoginController.Logout
[INFO ] 2018-05-17 15:45:06,988 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
security_req_user = admin
[INFO ] 2018-05-17 15:45:06,989 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
security_req_role = [admin]
[INFO ] 2018-05-17 15:45:06,989 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
security_req_permission = [admin.*]
[INFO ] 2018-05-17 15:45:06,995 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
 security_log saved ! 
[INFO ] 2018-05-17 15:45:06,997 method:com.bandweaver.tunnel.common.platform.log.Log.info(Log.java:42)
response={{"msg":"登出成功","code":"10003","data":{}}}





阅读更多
文章标签: springAOP Aspect Log
个人分类: log spring
想对作者说点什么? 我来说一句

基于注解实现SpringAop

2017年12月15日 2KB 下载

springAOP所需jar包

2010年04月22日 4.38MB 下载

proxy1demo

2015年12月29日 4.86MB 下载

没有更多推荐了,返回首页

不良信息举报

利用springaop实现日志输出

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭