java aop注解日志记录_springMVC自定义注解,用AOP来实现日志记录的方法
需求背景
最近的一个项目,在项目基本完工的阶段,客户提出要将所有业务操作的日志记录到数据库中,并且要提取一些业务的关键信息(比如交易单号)体现在日志中。
为了保证工期,在查阅了资料以后,决定用AOP+自定义注解的方式来完成这个需求。
准备工作
自定义注解需要依赖的jar包有 aspectjrt-XXX.jar ,aspectjweaver-XXX.jar,XXX代表版本号。
自定义注解
在项目下单独建立了一个log包,来存放日志相关的内容
**.common.log.annotation //自定义注解存放位置
**.common.log.aop //aop工具类存放位置
在annotation包下面新建自定义注解类:
package **.common.log.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 XXXOperateLog {
/**
* 操作类型描述
* @return
*/
String operateTypeDesc() default "";
/**
* 操作类型
* @return
*/
long operateType() default -1;
/**
* 模块编码
* @return
*/
String moudleCode() default "M30";
/**
* 模块名称
* @return
*/
String moudleName() default "XX模块";
/**
* 业务类型
* @return
*/
String bussType() default "";
/**
* 业务类型描述
* @return
*/
String bussTypeDesc() default "";
}
在aop包下新建XXXOperateLogAop
package **.common.log.aop;
import ** ;//省略
@Aspect
@Component
public class XXXOperateLogAop{
@Autowired
SystemLogService systemLogService;
HttpServletRequest request = null;
Logger logger = LoggerFactory.getLogger(XXXOperateLogAop.class);
ThreadLocal time = new ThreadLocal();
//用于生成操作日志的唯一标识,用于业务流程审计日志调用
public static ThreadLocal tag = new ThreadLocal();
//声明AOP切入点,凡是使用了XXXOperateLog的方法均被拦截
@Pointcut("@annotation(**.common.log.annotation.XXXOperateLog)")
public void log() {
System.out.println("我是一个切入点");
}
/**
* 在所有标注@Log的地方切入
* @param joinPoint
*/
@Before("log()")
public void beforeExec(JoinPoint joinPoint) {
time.set(System.currentTimeMillis());
info(joinPoint);
//设置日志记录的唯一标识号
tag.set(UUID.randomUUID().toString());
request= ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
@After("log()")
public void afterExec(JoinPoint joinPoint) {
MethodSignature ms = (MethodSignature) joinPoint.getSignature();
Method method = ms.getMethod();
logger.debug("标记为" + tag.get() + "的方法" + method.getName()
+ "运行消耗" + (System.currentTimeMillis() - time.get()) + "ms");
}
//在执行目标方法的过程中,会执行这个方法,可以在这里实现日志的记录
@Around("log()")
public Object aroundExec(ProceedingJoinPoint pjp) throws Throwable {
Object ret = pjp.proceed();
try {
Object[] orgs = pjp.getArgs();
SystemLog valueReturn = null;
for (int i = 0; i < orgs.length; i++) {
if(orgs[i] instanceof SystemLog){
valueReturn = (SystemLog) orgs[i];
}
}
if(valueReturn==null){
valueReturn = new SystemLog();
}
if(valueReturn!=null&&request!=null){
MethodSignature ms = (MethodSignature) pjp.getSignature();
Method method = ms.getMethod();
//获取注解的操作日志信息
XXXOperateLog log = method.getAnnotation(XXXOperateLog.class);
String businessType = log.bussType();
String businessDesc = log.bussTypeDesc();
HashMap requestMap = ServletUtils.getParametersToHashMap(request) ;
//从参数中寻找业务类型
if(businessType.equals(""))
{
Object objBusinessType = requestMap.get("business_type");
businessType = objBusinessType == null ? "" : objBusinessType.toString();
}
//从执行结果的申请单中找业务类型
Object apply = request.getAttribute("apply") ;
if(apply != null){
JSONObject obj = JSONFactory.toJSONAbstractEntity(apply);
if(obj != null)
{
valueReturn.setOtherDesc("申请单号:"+obj.getString("apply_no"));
if(businessType.equals(""))
{
businessType = obj.getString("business_type");
}
}
}
//从方法的执行过程参数中找业务类型(一般是手动设置)
if(businessType.equals(""))
{
businessType = (String) request.getAttribute("business_type");
businessType = businessType == null ? "" : businessType;
}
if(!businessType.equals("") && businessDesc.equals(""))
{
businessDesc = XXXSysConstant.BUSINESS_TYPE.getName(businessType);
}
valueReturn.setBussType(XXXSysConstant.BUSINESS_TYPE.getNumber(businessType));
valueReturn.setBussTypeDesc(businessDesc);
valueReturn.setMoudleCode(log.moudleCode());
valueReturn.setMoudleName(log.moudleName());
valueReturn.setOperateResult(XXXSysConstant.YesOrNo.YES);
valueReturn.setOperateType(log.operateType());
valueReturn.setInputUserId(((UserContext)WebUtils.getSessionAttribute(request, "XXXuserContext")).getSysUser().getId());
valueReturn.setOperateTypeDesc(log.operateTypeDesc());
valueReturn.setRequestIp(getRemoteHost(request));
valueReturn.setRequestUrl(request.getRequestURI());
valueReturn.setServerIp(request.getLocalAddr());
valueReturn.setUids(tag.get());
//保存操作日志
systemLogService.saveSystemLog(valueReturn);
}else{
logger.info("不记录日志信息");
}
//保存操作结果
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
//记录异常日志
@AfterThrowing(pointcut = "log()",throwing="e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
try {
info(joinPoint);
Object[] orgs = joinPoint.getArgs();
SystemLog valueReturn = null;
for (int i = 0; i < orgs.length; i++) {
if(orgs[i] instanceof SystemLog){
valueReturn = (SystemLog) orgs[i];
}
}
if(valueReturn==null){
valueReturn = new SystemLog();
}
if(valueReturn!=null&&request!=null){
MethodSignature ms = (MethodSignature) joinPoint.getSignature();
Method method = ms.getMethod();
XXXOperateLog log = method.getAnnotation(XXXOperateLog.class);
String businessType = log.bussType();
String businessDesc = log.bussTypeDesc();
if(businessType.equals(""))
{
Object objBusinessType = ServletUtils.getParametersToHashMap(request).get("business_type");
businessType = objBusinessType == null ? "" : objBusinessType.toString();
businessDesc = XXXSysConstant.BUSINESS_TYPE.getName(businessType);
}
valueReturn.setBussType(XXXSysConstant.BUSINESS_TYPE.getNumber(businessType));
valueReturn.setBussTypeDesc(businessDesc);
valueReturn.setMoudleCode(log.moudleCode());
valueReturn.setMoudleName(log.moudleName());
valueReturn.setOperateType(log.operateType());
valueReturn.setOperateTypeDesc(log.operateTypeDesc());
valueReturn.setInputUserId(((UserContext)WebUtils.getSessionAttribute(request, "XXXuserContext")).getSysUser().getId());
valueReturn.setOperateResult(XXXSysConstant.YesOrNo.NO);
String errMes = e.getMessage();
if(errMes!=null && errMes.length()>800){
errMes = errMes.substring(0, 800);
}
valueReturn.setErrorMessage(errMes);
valueReturn.setRequestIp(getRemoteHost(request));
valueReturn.setRequestUrl(request.getRequestURI());
valueReturn.setServerIp(request.getLocalAddr());
valueReturn.setUids(tag.get());
systemLogService.saveSystemLog(valueReturn);
}else{
logger.info("不记录日志信息");
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
private void info(JoinPoint joinPoint) {
logger.debug("--------------------------------------------------");
logger.debug("King:\t" + joinPoint.getKind());
logger.debug("Target:\t" + joinPoint.getTarget().toString());
Object[] os = joinPoint.getArgs();
logger.debug("Args:");
for (int i = 0; i < os.length; i++) {
logger.debug("\t==>参数[" + i + "]:\t" + os[i].toString());
}
logger.debug("Signature:\t" + joinPoint.getSignature());
logger.debug("SourceLocation:\t" + joinPoint.getSourceLocation());
logger.debug("StaticPart:\t" + joinPoint.getStaticPart());
logger.debug("--------------------------------------------------");
}
/**
* 获取远程客户端Ip
* @param request
* @return
*/
private String getRemoteHost(javax.servlet.http.HttpServletRequest request){
String ip = request.getHeader("x-forwarded-for");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getRemoteAddr();
}
return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
}
}
修改配置文件spring-mvc.xml,添加如下配置
需要注意的是,上述配置必须放在同一个xml文件里面,要么spring-mvc.xml,要么spring-context.xml,否则可能不生效,暂时还未查明是为什么。
注解的使用
@XXXOperateLog(
bussType=XXXSysConstant.BUSINESS_TYPE.YYYY
,bussTypeDesc="业务类型描述"
,operateType = XXXSysConstant.LogOperateType.QUERY
,operateTypeDesc = "操作描述"
)
@RequestMapping(value = "/**/**/queryXXXXX4DataGrid.json", method = RequestMethod.POST)
public void queryXXXXX4DataGrid(HttpServletRequest request, HttpServletResponse arg1, Model model, Writer writer)
{
logger.info("==========验票查询(出库)交易信息 开始=====================");
try {
//do something for business
} catch (SystemException se) {
throw se;
} catch (BusinessException be) {
throw be;
} catch (Exception e) {
throw new SystemException(e);
}
}
以上这篇springMVC自定义注解,用AOP来实现日志记录的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。
java aop注解日志记录_springMVC自定义注解,用AOP来实现日志记录的方法相关推荐
- java注解定义常量_java自定义注解
1.Annotation的工作原理: JDK5.0中提供了注解的功能,允许开发者定义和使用自己的注解类型.该功能由一个定义注解类型的语法和描述一个注解声明的语法,读取注解的API,一个使用注解修饰的c ...
- 使用Java反射(Reflect)、自定义注解(Customer Annotation)生成简单SQL语句
使用Java反射(Reflect).自定义注解(Customer Annotation)生成简单SQL语句 这次给大家介绍一下在Java开发过程中 使用自定义注解开发: 主要知识点: ...
- java 日志切面_自定义注解+面向切面整合的日志记录模块(一)
java中的常见注解 jdk的自带注解 @Override:告诉编译器我重写了接口方法 @Deprecated:告诉编译器这个方法过时了,不建议使用,Ide会在方法上划横线 @SuppressWarn ...
- java自定义注解为空值_java自定义注解
1. Java注解(Annotation) Java注解是附加在代码中的一些元信息,用于一些工具在编译. 运行时进行解析和使用,起到说明.配置的功能. 注解相关类都包含在java.lang.annot ...
- Java接口防刷策略(自定义注解实现)
前言 本文一定要看完,前部分为逻辑说明及简单实现,文章最后有最终版解决方案(基于lua脚本),因为前部分是防君子不防小人,无法抵挡for循环调用. 目的 短信发送及短信验证码校验接口防刷 一方面防止用 ...
- java 外部覆盖内部配置,Spring 与自定义注解、外部配置化的结合使用
Spring 与自定义注解.外部配置化的结合使用 一.Java注解的简单介绍 注解,也叫Annotation.标注,是 Java 5 带来的新特性. 可使用范围 类.字段.方法.参数.构造函数.包等, ...
- 深入理解Java:注解(Annotation)自定义注解入门
要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 元注解: 元注解的作用就是负责注解其他注解.Java5. ...
- java 自定义注解 生成json_SpringBoot:自定义注解实现后台接收Json参数
0.需求 在实际的开发过程中,服务间调用一般使用Json传参的模式,SpringBoot项目无法使用@RequestParam接收Json传参 只有@RequestBody支持Json,但是每次为了一 ...
- java 扫描自定义注解_利用spring 自定义注解扫描 找出使用自定义注解的类
我们常常有扫描项目里带有指定注解的class, 下面是利用spring扫描自定义注解的方法, 还是比较灵活的 我这里将扫描到的class放到map, 你可以放到其他地方,以便后期使用 import l ...
最新文章
- 电脑开机老是显示explorer.exe文件损坏
- 基于Python的卷积神经网络和特征提取
- c语言 文件 long double 读取,读取*.wav音频文件
- 关于几种排序算法的时间性能比较
- c语言编译 64位,cmake – 编译32位和64位
- 如何使用SAP APF里的过滤器
- python用户交互、基本数据类型、运算符
- WinForm窗体自适应分辨率
- java中json对象去重复_如何忽略Java中JSON对象的多个属性?
- python统计数据分析基础教程_Python数据分析基础教程:NumPy学习指南(第2版)
- Linux 命令源码 —— cat
- python写sql语句_python3将变量写入SQL语句的实现方式
- 火狐—火狐浏览器中的“HttpWatch”
- 携程机票业务数据仓库实践
- python str.split以及str.split字符串分割函数
- 解决React Hooks useEffect控制台报错:内存泄漏
- 杭电oj基础题目(1106、1108、1163、1164、1170、1194、1197)
- 云会议是什么?如何提升云会议的协同能力?
- The 2020 ICPC Asia Yinchuan Regional Programming Contest 银川 B. The Great Wall 题解
- 2019年中国自动驾驶行业报告:互联网企业与整车厂商互有优势
热门文章
- 怎么把截屏的一部分内容涂掉_电脑怎么录屏?录屏软件的使用技巧
- 制造业如何应用大数据
- 医疗大数据服务平台技术架构有哪些
- 软硬件兼容性问题学习笔记
- 安卓蓝牙键盘切换输入法_Windows10添加中文美式键盘,传统语言栏,采用ctrl+shift切换输入法...
- java 快排_秋招|字节跳动Java后台已上岸,发个面经回馈牛油
- php函数end,PHP end()函数
- flask连接mysql数据库_Flask与Mysql数据库建立连接
- 好程序员web前端干货之web前端开发框架汇总
- Linux守护进程的启动方法