优化CalledListRequest接口写的不是那么好,循环调用某个接口
优采云 发布时间: 2021-07-21 20:43
优化CalledListRequest接口写的不是那么好,循环调用某个接口
AOP 使用示例:log采集function
背景:目的是优化CalledListRequest接口。深入了解后,发现这个接口没有写得那么好,所以循环调用一个接口。导致一些简单的查询被重复执行。从而效率。那么这个接口涉及的业务逻辑太复杂了,不能直接改。相反,编写了一个新接口来替换它。但是为了做更彻底的测试。第一行采集 请求参数。然后测试一下。最后,这是发布和上线的最佳方式。
功能及原理介绍
采集这个在线接口(CalledListRequest)的请求参数。
原理:编写一个方法,将所有传入的参数插入到数据库的日志表中。
但为了减少侵入性(即不改动原接口的实现代码)。我在这里使用了 AOP 切入方法。同时用apollo做了一个switch(控制什么时候开始采集,什么时候关闭采集)
主要技能点之一是AOP的应用。之前实际上没有实际的工作来应用 AOP。这次是机会。
其实很简单,就是直接的核心代码。没有复杂的事情
核心代码
package com.centanet.bizcom.config.log;
import com.alibaba.fastjson.JSON;
import com.centanet.bizcom.config.apollo.ApolloConfig;
import com.centanet.bizcom.config.ddb.MultiTenantChanger;
import com.centanet.bizcom.mapper.BizMapper;
import com.centanet.bizcom.model.entity.LogCollection;
import com.centanet.bizcom.util.CityHelper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
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 javax.servlet.http.HttpServletRequest;
import java.util.Date;
/**
* 该类的功能是为了收集日志
* 方便切换接口时使用
* @Author: wbdengtt
* @Date: 2020/10/13 14:58
*/
//声明切面
@Aspect
// 交给Spring管理bean
@Component
public class LogCollectAspect {
// 注入logCollection 这个就是一个简单实体entity。
@Autowired
private LogCollection logCollection;
// 这是将实体存到数据库的mapper
@Autowired
private BizMapper bizMapper;
// 拦截CalledController.calledListRequest方法。通过这个配置。可以拦截更多东西,这个规则相信的可以看下面的参考文章
@Pointcut("execution(* com.centanet.bizcom.controller.CalledController.calledListRequest(..))")
public void myPointCut() {
// 这个其实就是一个切点,不需要方法内容
}
// 这个是具体实现拦截参数,并将参数日志写入到数据库的方法
@Before("myPointCut()")
public void logCollect(JoinPoint joinPoint) {
// 这个是在apoll配置的开关(就是一个String变量)。如果开了才进行下面的拦截。
boolean isLogCollect = "true".equalsIgnoreCase(ApolloConfig.getWebValue(CityHelper.getCityCode(),"isLogCollectionOpen"))
&& ApolloConfig.getWebValue(CityHelper.getCityCode(),"logCollectCity").contains(CityHelper.getCityen());
if (isLogCollect) {
// 设置logCollection的日期字段
logCollection.setRowDate(new Date());
// 获取当前HttpServletRequest 对象 这个是为了拿到各种我需要的信息。关于HttpServletRequest 下面有提供参考链接看相信的介绍
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
//设置logCollection的实体字段,这里是请求类型.城市
logCollection.setMethodName(request.getMethod()+"."+CityHelper.getCityen());
//request.getQueryString() 只能拿到get请求的参数。如果是post请求,得通过joinPoint才能拿到参数(这个不需要手动声明,应该是SpringAOP哪里给自动注入了)
logCollection.setMessage(JSON.toJSONString(joinPoint.getArgs()));
if (logCollection.getMessage() ==null){
logCollection.setMessage("没能拿到参数");
}
// request.getRequestURI()获取方法名
logCollection.setFullName(request.getRequestURI());
// 写入数据库 MultiTenantChanger是因为我有多个数据库,但是这里的操作其实就是讲实体装入数据库
MultiTenantChanger.setDataSourceType(CityHelper.getCityCode()+MultiTenantChanger.CENTA_BIZ);
bizMapper.insertLogCollection(logCollection);
MultiTenantChanger.removeRouteKey();
}
}
}
我在代码中添加了很多注释。应该更容易理解
参考文章:
连接点: