spring aop实现接口超时处理组件的代码详解

 更新时间:2024年02月05日 11:36:33   作者:用针戳左手中指指头  
这篇文章给大家介绍了spring aop实现接口超时处理组件,文中有详细的实现思路,并通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下

实现思路

  • 这里使用FutureTask,它通过get方法以阻塞的方式获取执行结果,并设定超时时间:
public V get() throws InterruptedException, ExecutionException ;

public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException ;
  • 利用spring aop解耦业务
  • 定义业务异常信息

实现代码

定义注解:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
public @interface TimeoutCheck {

    /**
     * 超时时间,默认5秒
     */
    long timeout() default 5L;

    /**
     * 超时单位,默认秒
     */
    TimeUnit unit() default TimeUnit.SECONDS;

    /**
     * 超时后是否销毁线程
     */
    boolean destroy() default true;
}

这里有一个destroy()的方法,因为我们在执行时开独立线程处理,所以这个方法是为了在超时后,用来判断是否销毁还在执行的线程;

定义异常:

注意:这里的父类应该是项目中的基础业务异常类;

public class TimeoutCheckException extends RuntimeException{

    public TimeoutCheckException(String message) {
        super(message);
    }

    public TimeoutCheckException(String message, Throwable throwable) {
        super(message, throwable);
    }
}

再顺便定义一个属性配置:

这个的作用是全局控制开关,当不需要的时候可以直接通过配置关闭;

@Component
@ConfigurationProperties(prefix = "aliweb.timeout")
public class TimeoutCheckProperties {

    private boolean enable = true;

    public boolean isEnable() {
        return enable;
    }

    public void setEnable(boolean enable) {
        this.enable = enable;
    }
}

最后就是我们的aop类:

@Aspect
@Component
public class TimeoutAop {

    private static final Logger logger = LoggerFactory.getLogger(TimeoutAop.class);

    @Autowired
    private TimeoutCheckProperties timeoutCheckProperties;

    @Pointcut("@annotation(timeoutCheck)")
    public void pointCut(TimeoutCheck timeoutCheck) {
    }

    @Around(value = "pointCut(timeoutCheck)", argNames = "joinPoint, timeoutCheck")
    public Object around(ProceedingJoinPoint joinPoint, TimeoutCheck timeoutCheck) throws Throwable {
        if (!timeoutCheckProperties.isEnable()) {
            return joinPoint.proceed();
        }
        long timeout = timeoutCheck.timeout();
        if (timeout <= 0) {
            throw new TimeoutCheckException("业务逻辑执行时间不能小于等于0");
        }
        long start = System.currentTimeMillis();
        String msg = null;
        Exception error = null;
        Object data = null;
        FutureTask<Object> futureTask = createTask(joinPoint);
        try {
            Thread thread = new Thread(futureTask);
            thread.start();
            data = futureTask.get(timeout, timeoutCheck.unit());
        } catch (InterruptedException e) {
            msg = "执行中断";
            error = e;
        } catch (ExecutionException e) {
            msg = "执行异常";
            error = e;
        } catch (TimeoutException e) {
            msg = "执行超时";
            error = e;
        } finally {
            futureTask.cancel(timeoutCheck.destroy());
        }
        logger.debug("执行时间:{}", System.currentTimeMillis() - start);
        if (error != null) {
            String suf = error.getMessage() == null ? "" : ":" + error.getMessage();
            logger.error(msg + suf, error);
            throw new TimeoutCheckException(msg + suf, error);
        }
        return data;
    }

    private static FutureTask<Object> createTask(ProceedingJoinPoint joinPoint) {
        return new FutureTask<>(() -> {
            try {
                return joinPoint.proceed();
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        });
    }

}

starter组件

将功能提取成starter组件:

  • 定义配置类
@Configuration
@ComponentScan("com.liry.aliweb.timeout")
public class TimeoutCheckAutoConfig {
}

  • 定义配置扫描文件spring.factories,路径:

src/main/resources/META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.liry.aliweb.timeout.config.TimeoutCheckAutoConfig
  • pom增加依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

如上,在主项目引入时就可以直接使用了

到此这篇关于spring aop实现接口超时处理组件的代码详解的文章就介绍到这了,更多相关spring aop接口超时处理组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Flink状态和容错源码解析

    Flink状态和容错源码解析

    这篇文章主要为大家介绍了Flink状态和容错源码示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • Spring RestTemplate具体使用详解

    Spring RestTemplate具体使用详解

    这篇文章主要介绍了Spring RestTemplate具体使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • Maven中两个命令clean 和 install的使用

    Maven中两个命令clean 和 install的使用

    Maven是一个项目管理和自动构建工具,clean命令用于删除项目中由先前构建生成的target目录,install命令用于将打包好的jar包安装到本地仓库中,供其他项目依赖使用,下面就来详细的介绍一下这两个命令
    2024-09-09
  • 友盟 微信第三方登录示例

    友盟 微信第三方登录示例

    这篇文章主要介绍了友盟 微信第三方登录示例的相关资料,需要的朋友可以参考下
    2016-10-10
  • MyBatis-Flex实现多表联查(自动映射)

    MyBatis-Flex实现多表联查(自动映射)

    我们可以轻松的使用 Mybaits-Flex 链接任何数据库,本文主要介绍了MyBatis-Flex实现多表联查(自动映射),具有一定的参考价值,感兴趣的可以了解一下
    2024-06-06
  • Maven 安装目录的详细介绍

    Maven 安装目录的详细介绍

    这篇文章主要介绍了Maven 安装目录的详细介绍的相关资料,这里对Maven进行了解读,希望通过本文可以帮助到大家,需要的朋友可以参考下
    2017-08-08
  • java泛型学习示例

    java泛型学习示例

    Java泛型(Generics)是JDK5开始引入的一个新特性,允许在定义类和接口的时候使用类型参数(Type Parameter)。下面是学习泛型的示例
    2014-04-04
  • SpringCloud使用Feign实现动态路由操作

    SpringCloud使用Feign实现动态路由操作

    这篇文章主要介绍了SpringCloud使用Feign实现动态路由操作,文章围绕主题展开详细的内容介绍具有一定的参考价值,需要的小伙伴可以参考一下
    2022-06-06
  • ElasticSearch6.2.3+head插件安装的方法步骤

    ElasticSearch6.2.3+head插件安装的方法步骤

    这篇文章主要介绍了ElasticSearch6.2.3+head插件安装的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-02-02
  • Java创建线程的七种方法总结(全网最全面)

    Java创建线程的七种方法总结(全网最全面)

    线程是Java中的基本执行单元,它允许程序在同一时间执行多个任务,下面这篇文章主要给大家总结介绍了关于Java创建线程的七种方法,文中通过实例代码将这七种方法介绍的非常详细,需要的朋友可以参考下
    2023-05-05

最新评论