我是靠谱客的博主 温柔吐司,最近开发中收集的这篇文章主要介绍SpringAOP&&定时任务简单实现接口访问入表和定时任务接口重试,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

# SpringAOP&&定时任务简单实现接口访问入表和定时任务接口重试 #

  • Spring aop
  • Spring 定时任务
  • 代理模式深化

1.表设计

hgwqzcv.png

2.Aop主要代码

@Aspect
@Component
public class AopUtils implements Ordered {
//当前
private static final Logger logger = LoggerFactory.getLogger(AopUtils.class);
public static String
AOPLOG_NO_RETREN_VALUE = "NONE RETURN";
@Value("${接口地址.url}")
private String url;
@Autowired
private RequestInfoDao requestInfoDao;
/**
*
API 接口日志访问记录
* 环绕通知实现
* @param jp
* @return
*/
@Around("execution(* com.*.*.modules.*.service.CommonService.*(..))")
public Object logApiMethod(ProceedingJoinPoint jp) throws Throwable {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
Object rvt = null;
RequestInfo requestInfo = new RequestInfo();
//配合后面的定时任务重试接口机制
if(sra == null) {
try {
rvt = jp.proceed(jp.getArgs());
String params = "";
List<Object> filterArgs = Lists.newArrayList();
try {
if(jp.getArgs()!=null) {
Arrays.stream(jp.getArgs()).forEach(arg -> {
if (!(arg instanceof HttpServletRequest || arg instanceof HttpServletResponse)) {
filterArgs.add(arg);
}
});
}
params = (filterArgs.size()==0)? "":JsonMapper.toJsonString(filterArgs);
}catch (Exception e) {
params = filterArgs+"";
}
String returnValue = "";
try {
returnValue = rvt==null ? "": JsonMapper.toJsonString(rvt);
}catch (Exception e) {
returnValue = "返回值过长不显示";
}
requestInfo.setParam(params);
requestInfo.setReturnValue(returnValue);
requestInfo.setUpdateDate(new Date());
User user = new User("接口重试");
requestInfo.setUpdateBy(user);
requestInfo.setResult(true);
requestInfo.setErrorResson(null);
requestInfoDao.updateByParams(info);
return rvt;
} catch (Throwable var6) {
requestInfo.setResult(false);
requestInfo.setErrorResson("线上接口访问异常:"+var6.getMessage());
logger.error("线上接口访问异常:", var6);
}
}
HttpServletRequest request = sra.getRequest();
requestInfo.setResult(true);
try {
rvt = jp.proceed(jp.getArgs());
} catch (Throwable var6) {
requestInfo.setResult(false);
requestInfo.setErrorResson("线上接口访问异常:"+var6.getMessage());
logger.error("线上接口访问异常:", var6);
}
String methodName = jp.getSignature().getName();
//参数写成一个集合数组,接口重试的时候需要转换
String params = "";
List<Object> filterArgs = Lists.newArrayList();
try {
if(jp.getArgs()!=null) {
Arrays.stream(jp.getArgs()).forEach(arg -> {
if (!(arg instanceof HttpServletRequest || arg instanceof HttpServletResponse)) {
filterArgs.add(arg);
}
});
}
params = (filterArgs.size()==0)? "":JsonMapper.toJsonString(filterArgs);
}catch (Exception e) {
params = filterArgs+"";
}
String returnValue = "";
if(isShowReturnValue(methodName)) {
try {
returnValue = rvt==null ? "": JsonMapper.toJsonString(rvt);
}catch (Exception e) {
returnValue = "返回值过长不显示";
}
}else {
returnValue = "不显示返回值";
}
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String requestURI = httpServletRequest.getRequestURI();
String beanName = jp.getThis().getClass().getSimpleName();
int num = beanName.indexOf("$$");
beanName = beanName.substring(0, 1).toLowerCase() + beanName.substring( 1, num);
requestInfo.setId(IdGen.uuid());
requestInfo.setBeanName(beanName);
requestInfo.setMethod(methodName);
requestInfo.setParam(params);
requestInfo.setRequestUrl(url+requestURI);
requestInfo.setReturnValue(returnValue);
requestInfo.setCreateDate(new Date());
requestInfo.setUpdateDate(new Date());
//接口是否可重复
Method aopMethod = ((MethodSignature)jp.getSignature()).getMethod();
Method m = jp.getTarget().getClass().getDeclaredMethod(methodName, aopMethod.getParameterTypes());
InterfaceRepeatFlag interfaceRepeatFlag = m.getAnnotation(InterfaceRepeatFlag.class);
if (interfaceRepeatFlag == null){
requestInfo.setRepeatFlag(false);
}else {
requestInfo.setRepeatFlag(interfaceRepeatFlag.value());
}
User user = new User();
user.setId("接口调用");
requestInfo.setCreateBy(user);
requestInfo.setUpdateBy(user);
if(requestInfoDao != null) {
requestInfoDao.insert(requestInfo);
}
return rvt;
}
private boolean isShowReturnValue(String methodName) {
List<String> debugRoles = Arrays.asList(AOPLOG_NO_RETREN_VALUE.split(","));
for(String debugRole : debugRoles) {
if(!StringUtils.isBlank(methodName)
&& methodName.indexOf(debugRole) == 0){
return false;
}
}
return true;
}
@Override
public int getOrder() {
return 1001;
}
}

3.定时任务配置

<bean name="schedulerFactory"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!-- 定义数据源 ,数据源里面需要Quzrtz集群所需要的表 -->
<property name="dataSource">
<ref bean="dataSource" />
</property>
<!-- 指定spring容器的key,如果不设定在job中的jobmap中是获取不到spring容器的 -->
<property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
<!-- 指定spring的配置相关信息 -->
<property name="configLocation" value="classpath:quartz.properties" />
<!-- 指定触发器,可以指定多个 -->
<property name="triggers">
<list>
<ref bean="interfaceJobTrigger"/>
</list>
</property>
</bean>
<!-- 定义任务 -->
<bean id="interfaceJob" class="com.*.*.modules.quzrtz.service.interfaceJob"/>
<bean id="interfaceJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<!-- 上面的任务的代理类(自己实现) -->
<value>com.*.*.modules.quzrtz.scheduler.InterfaceJobSchedule</value>
</property>
<property name="description">
<value>定时任务接口重试</value>
</property>
<property name="jobDataAsMap">
<map>
<!--实际的任务BeanName,填上EventMonitorService的BeanName -->
<entry key="targetObject" value="interfaceJob" />
<!-- 执行Bean中的哪个方法 -->
<entry key="targetMethod" value="repeatInterface" />
</map>
</property>
</bean>
<bean id="interfaceJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<!-- 任务代理Bean name -->
<ref bean="interfaceJobDetail" />
</property>
<property name="description">
<!-- 任务代理Bean name -->
<value>定时任务接口重试</value>
</property>
<property name="cronExpression">
<!-- 配置表达式,这里表示每1分钟执行一次 -->
<value>0 0/1 * * * ?</value>
</property>
</bean>

4.定时任务

@Transactional(readOnly = false)
public void repeatInterface() {
RequestInfo requestInfo = new RequestInfo();
requestInfo.setRepeatFlag(true);
requestInfo.setResult(false);
List<RequestInfo> requestInfoList = requestInfoDao.findAllList(requestInfo);
for (RequestInfo requestInfo : requestInfoList){
String paramStr = requestInfo.getParam();
String beanStr = requestInfo.getBeanName();
String methodStr = requestInfo.getMethod();
try {
Object obj = SpringContextHolder.getBean(beanStr);
Method m = null;
Method[] methods = obj.getClass().getMethods();
if (methods != null && methods.length > 0) {
for (Method method : methods) {
if (method.getName().equals(methodStr)) {
m = method;
break;
}
}
}
Class paramCls = m.getParameterTypes()[0];
List<Object> params =
JSONArray.parseArray(paramStr);
MethodUtils.invokeExactMethod(obj, methodStr, JSON.parseObject(JSONObject.toJSONString(params.get(0)), paramCls));
}catch (Exception e){
e.printStackTrace();
logger.error("接口重试:失败,失败原因:"+e.getMessage());
continue;
}
logger.info("接口重试成功:类名"+beanStr+";方法:"+methodStr+";参数:"+paramStr+";结束重试");
}
}

5.定时任务调度器-定时任务代理

public class InterfaceJobSchedule extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(InterfaceJobSchedule.class);
private String targetObject;
private String targetMethod;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
Object otargetObject = SpringContextHolder.getBean(targetObject);
Method m = null;
Method[] methods = otargetObject.getClass().getMethods();
if (methods != null && methods.length > 0) {
for (Method method : methods) {
if (method.getName().equals(targetMethod)) {
m = method;
break;
}
}
m.invoke(otargetObject, new Object[]{});
}
} catch (Exception e) {
logger.error("InterfaceJobSchedule Exception:", e);
}
}
/**
* @param targetObject the targetObject to set
*/
public void setTargetObject(String targetObject) {
this.targetObject = targetObject;
}
/**
* @param targetMethod the targetMethod to set
*/
public void setTargetMethod(String targetMethod) {
this.targetMethod = targetMethod;
}
}

6.接口重试注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InterfaceRepeatFlag {
public boolean value() default true;
}

7.学习总结

Spring AOP核心是代理模式,可见代理模式的拓展性有多强,有业务的代码才会有收获,试一试,收获颇多

转载于:https://www.cnblogs.com/heiqiubaihu/p/9304536.html

最后

以上就是温柔吐司为你收集整理的SpringAOP&&定时任务简单实现接口访问入表和定时任务接口重试的全部内容,希望文章能够帮你解决SpringAOP&&定时任务简单实现接口访问入表和定时任务接口重试所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部