SpringBoot使用自定义注解+拦截器 实现日志记录

一.自定义注解

 
package com.xiaojukeji.common.annotation;

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

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface SystemLogAnnotation {
	String value();
}


(1)@Target注解是标注这个类它可以标注的位置,常用的元素类型(ElementType):

public enum ElementType { 
	/** Class, interface (including annotation type), or enum declaration */ 
	// TYPE类型可以声明在类上或枚举上或者是注解上 
	TYPE, 
	
	/** Field declaration (includes enum constants) */ 
	// FIELD声明在字段上 
	FIELD, 
	
	/** Method declaration */ 
	// 声明在方法上 
	METHOD, 
	
	/** Formal parameter declaration */ 
	// 声明在形参列表中 
	PARAMETER, 
	
	/** Constructor declaration */ 
	// 声明在构造方法上 
	CONSTRUCTOR, 
	
	/** Local variable declaration */ 
	// 声明在局部变量上 
	LOCAL_VARIABLE, 
	
	/** Annotation type declaration */ 
	ANNOTATION_TYPE, 
	
	/** Package declaration */ 
	PACKAGE, 
	
	/** * Type parameter declaration * * @since 1.8 */ 
	TYPE_PARAMETER, 
	
	/** * Use of a type * * @since 1.8 */ 
	TYPE_USE
}

(2)@Retention注解表示的是本注解(标注这个注解的注解保留时期)

public enum RetentionPolicy { 
	/** 
	 * Annotations are to be discarded by the compiler. 
	 */ 
	// 源代码时期 
	SOURCE, 
	
	/** 
	 * Annotations are to be recorded in the class file by the compiler 
	 * but need not be retained by the VM at run time. This is the default 
	 * behavior. 
	 */ 
	// 字节码时期, 编译之后 
	CLASS, 
	
	/** 
	 * Annotations are to be recorded in the class file by the compiler and 
	 * retained by the VM at run time, so they may be read reflectively. 
	 * 
	 * @see java.lang.reflect.AnnotatedElement 
	 */ 
	// 运行时期, 也就是一直保留, 通常也都用这个 
	RUNTIME
}

(3) @Documented 是否生成文档的标注, 也就是生成接口文档是, 是否生成注解文档

二.拦截器类

package com.xiaojukeji.ecm.interceptor;
import java.lang.reflect.Method;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import nl.bitwalker.useragentutils.UserAgent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.xiaojukeji.common.annotation.SystemLogAnnotation;
import com.xiaojukeji.dao.model.SystemLog;
import com.xiaojukeji.ep.ip.common.model.AdUser;
import com.xiaojukeji.ep.ip.common.utils.ContextHolder;
import com.xiaojukeji.service.ERPService;
import com.xiaojukeji.service.SystemLogService;

/** 
 * <p>Description: [ecm用户操作日志拦截器]</p> 
 * Created on 2017年11月23日 下午12:05:35 
 * @author  <a href="mailto: 15175223269@163.com">全冉</a> 
 * @version 1.0  
 * Copyright (c) 2017 全冉公司 
 */
public class EcmSysemLogInterceptor extends HandlerInterceptorAdapter { //此处不继承这个适配器,用implements HandlerInterceptor也行		
	@Autowired	
	private ERPService erpService;		
	
	@Resource	
	private SystemLogService systemLogService;	
	
	/**	 
	 * 在请求处理之前进行调用(Controller方法调用之前),只有返回true才会继续向下执行,返回false取消当前请求	 
	 */	
	@Override	
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,			
			Object handler) throws Exception {		
		// 将handler强转为HandlerMethod        
		HandlerMethod handlerMethod = (HandlerMethod) handler;        
		// 从方法处理器中获取出要调用的方法       
		Method method = handlerMethod.getMethod();        
		// 获取出方法上的Access注解        
		SystemLogAnnotation systemLogAnnotation = method.getAnnotation(SystemLogAnnotation.class);        
		if (systemLogAnnotation == null) {        	
			// 如果注解为null, 说明不需要拦截, 直接放过        	
			return true;        
		}        
		if (systemLogAnnotation != null) {        	
			// 如果自定义注解不为空, 则取出配置值        	
			String value = systemLogAnnotation.value();        	
			// 保存操作日志        	
			addSystemLog(value);        	
			return true;        
		}		
		return false;	
	}	
	
	/**	 
	 * <p>Discription:[保存操作日志]</p>	 
	 * Created on 2017年11月20日 下午3:07:33	 
	 * @param operationContent 操作内容	 
	 * @author:[全冉]	 
	 */	
	public void addSystemLog(String operationContent) {		
		// 获取此次请求的request对象		
		HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();			
		// 员工号		
		String employeeNum = adUser.getEmplID();		
		// 员工姓名		
		String employeeName = adUser.getEmplName();		
		// 邮箱		
		String employeeEmail = adUser.getEmailAddr();		
		// 浏览器标标识		
		String webIdentifiy = getBrowserInfo(request);				
		SystemLog systemLog = new SystemLog();		
		systemLog.setEmployeeNum(employeeNum);		
		systemLog.setEmployeeName(employeeName);		
		systemLog.setEmployeeEmail(employeeEmail);		
		systemLog.setOperationContent(operationContent);		
		systemLog.setWebIdentifiy("浏览器" + webIdentifiy);				
		systemLogService.save(systemLog);	
	}		
	
	/**	 
	 * <p>Discription:[根据request获取前台浏览器标识]</p>	 
	 * Created on 2017年11月20日 下午7:30:08	 
	 * @param request request对象	 
	 * @return String 浏览器标识	 
	 * @author:[全冉]	 
	 */	
	private static String getBrowserInfo(HttpServletRequest request) {		
		UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));		
		String browserInfo = userAgent.getBrowser().toString();		
		return browserInfo;	
	}
	
	/**	 
	 * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)	 
	 */	
	@Override
	public void afterCompletion(HttpServletRequest arg0,			
			HttpServletResponse arg1, Object arg2, Exception arg3)			
					throws Exception {	
		
	}	
	/**	 
	 * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)	 
	 */	
	@Override	
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,			
			Object arg2, ModelAndView arg3) throws Exception {	
		
	}
		
}

三.将拦截器注册到拦截器链

package com.xiaojukeji.ecm.interceptor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/** 
 * web MVC 适配器 * 配置拦截器、处理静态资源、配置消息转换等 
 * Created by camelot on 2017/10/17. 
 */
@Component
public class EcmWebMvcConfig extends WebMvcConfigurerAdapter {	
	
	@Bean    
	public EcmSysemLogInterceptor ecmSysemLogInterceptor(){        
		return new EcmSysemLogInterceptor();    
	}	    
	
	/**     
	 * 注册拦截器     
	 * @param registry 拦截器注册中心     
	 */    
	 @Override    
	 public void addInterceptors(InterceptorRegistry registry) {    	 
		 // 注册ecm系统操作日志拦截器(凡加了自定义注解的方法都会添加用户操作日志),拦截所有请求    	 
		 registry.addInterceptor(ecmSysemLogInterceptor()).addPathPatterns("/**");// 拦截器里有@Autowire或者@Resource注入的属性就这么用
		 // 注册ecm系统请求拦截器(不拦截登录、注销、回调请求,其他都拦截)        
		 registry.addInterceptor(new EcmRequestInterceptor()).addPathPatterns("/**");
		 // 连接器里没有@Autowire或者@Resource注入的属性就这么用        
		 super.addInterceptors(registry);    
	}    
	 
	 /**     
	  * 静态资源处理     
	  * 将请求的如css、html等静态资源定位到项目指定位置     
	  * @param registry     
	  */    
	 @Override    
	 public void addResourceHandlers(ResourceHandlerRegistry registry) {        
		 super.addResourceHandlers(registry);    
	}
}

四.在想记录用户日志的方法上,加自定义注解

package com.xiaojukeji.ecm.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.xiaojukeji.common.annotation.SystemLogAnnotation;
import com.xiaojukeji.ep.ip.common.model.AdUser;
import com.xiaojukeji.ep.ip.common.utils.ContextHolder;
import com.xiaojukeji.service.GiftVisitorService;

/** 
 * <p>Description: [gift服务器 相关API接口]</p> 
 * Created on 2017年11月8日 上午10:45:09 
 * @author  <a href="mailto: 15175223269@163.com">全冉</a> 
 * @version 1.0  
 * Copyright (c) 2017 全冉公司 
 */
@Api(value = "gift服务器 相关接口", description = "gift服务器 相关接口")
@RestController@RequestMapping("/gift")
public class GiftVisitorController {    
	@Autowired    
	private GiftVisitorService giftVisitorService;    
	
	/**     
	 * <p>Discription:[选择文件上传到gift服务器]</p>    
	 * Created on 2017年11月8日 上午10:54:30     
	 * @param request 要上传的文件     
	 * @return String 返回此文件在gift服务器的路径,路径若为空字符串,则需要异常处理     
	 * @author:[全冉]     
	 */    
	@ApiOperation("选择文件上传到gift服务器[quanran@camelotchina.com]")    
	@PostMapping(value = "/upload", consumes = "multipart/*", headers = "content-type=multipart/form-data")    
	@SystemLogAnnotation(value = "上传文件")    
	public String upload(@ApiParam(value = "上传的文件", required = true) MultipartFile multipartFile, 
			HttpServletRequest request) {		
		// 生成随机fileKey 		
		String fileKey = UUID.randomUUID().toString();		
		// 获取后缀		
		String fileName = multipartFile.getOriginalFilename();		
		String suffix = fileName.substring(fileName.indexOf("."));    
	}
}

五.启动项目,请求GiftVisitorController 的upload方法,在进入到此方法前,就会对此请求路径进行拦截,将此用户上传文件的操作插入到了数据库中。


另一篇参考地址,可以和我写得相互验证:http://www.jianshu.com/p/43c97352aa1e




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值