springMVC自定义注解,用AOP来实现日志记录的方法

网友投稿 418 2023-02-25


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++) {

http:// 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);

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:包含如何开发http接口的词条
下一篇:基于JVM 中常见垃圾收集算法介绍
相关文章

 发表评论

暂时没有评论,来抢沙发吧~