Java定时任务技术分析

2023-11-08

《从零打造项目》系列文章

工具

ORM框架选型

数据库变更管理

定时任务框架

  • Java定时任务技术分析

缓存

  • 待更新

安全框架

  • 待更新

开发规范

  • 待更新

常见的业务场景:

  • 某博客平台,支持定时发送文章。
  • 某学习平台,定时发送学习任务通知用户
  • 定时进行数据抓取等等

在项目中要求我们在某个时刻去做某件事情,下面我们就来看看有哪些方法可以实现定时任务。

JDK内置类

Timer

java.util.Timer是 JDK 1.3 开始就已经支持的一种定时任务的实现方式。

Timer 内部使用一个叫做 TaskQueue 的类存放定时任务,它是一个基于最小堆实现的优先级队列。TaskQueue 会按照任务距离下一次执行时间的大小将任务排序,保证在堆顶的任务最先执行。这样在需要执行任务时,每次只需要取出堆顶的任务运行即可!由于某个任务的执行时间可能较长,则后面的任务运行的时间会被延迟,所以执行的时间和你预期的时间可能不一致。延迟的任务具体开始的时间,就是依据前面任务的结束时间。

核心方法:

//启动任务之后,延迟多久时间执行
void schedule(TimerTask task, long delay);
//在指定的时间执行任务
void schedule(TimerTask task, Date time);
//启动任务后,延迟多久时间执行,执行之后指定间隔多久重复执行任务
void schedule(TimerTask task, long delay, long period);
//指定时间启动任务,执行后间隔指定时间重复执行任务
void schedule(TimerTask task, Date firstTime, long period);

代码案例:

public class TimerUse {

  public static void main(String[] args) {
    System.out.println("当前时间: " + new Date() + "n" +
        "线程名称: " + Thread.currentThread().getName());

    testTimer1();
//    testTimer2();
//    testTimer3();
//    testTimer4();
  }

  // 方法一:设定指定任务task在指定时间time执行 schedule(TimerTask task, long delay)
  public static void testTimer1() {
    Timer timer = new Timer("Timer");
    timer.schedule(new TimerTask() {
      public void run() {
        System.out.println("当前时间: " + new Date() + "n" +
            "线程名称: " + Thread.currentThread().getName());
      }
    }, 3500);
    // 设定指定的时间time为3500毫秒
  }

  /**
   * 方法二:设定指定任务task在指定延迟delay后间隔指定时间peroid执行 schedule(TimerTask task, long delay, long period)
   */
  public static void testTimer2() {
    Timer timer = new Timer("Timer");
    timer.schedule(new TimerTask() {
      public void run() {
        System.out.println("当前时间: " + new Date() + "n" +
            "线程名称: " + Thread.currentThread().getName());
      }
    }, 2000, 3500);
  }


  /**
   * 方法三:在指定的时间执行任务 schedule(TimerTask task, Date time)
   */

  public static void testTimer3() {
    Date date = new Date();
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(Calendar.MINUTE, 1); // 往后推一分钟

    Date time = calendar.getTime();    //获取当前系统时间

    Timer timer = new Timer("Timer");
    timer.schedule(new TimerTask() {
      public void run() {
        System.out.println("当前时间: " + new Date() + "n" +
            "线程名称: " + Thread.currentThread().getName());
      }
    }, time);
  }

  /**
   * 方法四:安排指定的任务task在指定的时间firstTime开始进行重复的固定速率period执行. schedule(TimerTask task, Date firstTime,
   * long period)
   */
  public static void testTimer4() {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 12); // 控制小时
    calendar.set(Calendar.MINUTE, 0);    // 控制分钟
    calendar.set(Calendar.SECOND, 0);    // 控制秒

    Date time = calendar.getTime();    //获取当前系统时间

    Timer timer = new Timer("Timer");
    timer.schedule(new TimerTask() {
      public void run() {
        System.out.println("当前时间: " + new Date() + "n" +
            "线程名称: " + Thread.currentThread().getName());
      }
    }, time, 1000 * 60 * 60 * 24);// 这里设定将延时每天固定执行
  }
}
注意事项

1、创建一个 Timer 对象相当于新启动了一个线程,但是这个新启动的线程,并不是守护线程。它一直在后台运行,通过如下代码将新启动的 Timer 线程设置为守护线程。

Timer timer = new Timer(true);

变为守护线程,则意味着主线程执行结束,则程序就结束了,定时任务也就不会执行。

2、当计划时间早于当前时间,则任务立即被运行。

ScheduledExecutorService

ScheduledExecutorService 是一个接口,有多个实现类,比较常用的是 ScheduledThreadPoolExecutor

public class ScheduledThreadPoolExecutor 
  extends ThreadPoolExecutor implements ScheduledExecutorService {}

scheduledthreadexecutor

ScheduledThreadPoolExecutor 的状态管理、入队操作、拒绝操作等都是继承于 ThreadPoolExecutorScheduledThreadPoolExecutor 主要是提供了周期任务和延迟任务相关的操作;

schedule(Runnable command, long delay, TimeUnit unit) // 无返回值的延迟任务
schedule(Callable callable, long delay, TimeUnit unit) // 有返回值的延迟任务
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) // 固定频率周期任务
scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) // 固定延迟周期任务

代码示例:

TimerTask repeatedTask = new TimerTask() {
  @SneakyThrows
  public void run() {
    System.out.println("当前时间: " + new Date() + "n" +
                       "线程名称: " + Thread.currentThread().getName());
  }
};
System.out.println("当前时间: " + new Date() + "n" +
                   "线程名称: " + Thread.currentThread().getName());
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
long delay = 1L;
long period = 2L;
// 延迟1s,周期2s
executor.scheduleAtFixedRate(repeatedTask, delay, period, TimeUnit.SECONDS);
// 定时任务重复执行3个周期
Thread.sleep((delay + period * 3) * 1000);
executor.shutdown();

执行结果为:

当前时间: Wed Nov 23 09:52:35 CST 2022n线程名称: main
当前时间: Wed Nov 23 09:52:36 CST 2022n线程名称: pool-1-thread-1
当前时间: Wed Nov 23 09:52:38 CST 2022n线程名称: pool-1-thread-1
当前时间: Wed Nov 23 09:52:40 CST 2022n线程名称: pool-1-thread-1
当前时间: Wed Nov 23 09:52:42 CST 2022n线程名称: pool-1-thread-1
注意事项

1、scheduleAtFixedRatescheduleWithFixedDelay 是我们最常用的两个方法,两者略有区别,前者为固定频率周期任务,如果任务执行时间超出周期时,下一次任务会立刻运行;后者为固定延迟周期任务,无论执行时间是多少,其结果都是在执行完毕后,停顿固定的时间,然后执行下一次任务

2、ScheduledThreadPoolExecutor 线程最多为核心线程,最大线程数不起作用,因为 DelayedWorkQueue 是无界队列。

更多内容推荐阅读:并发系列(7)之 ScheduledThreadPoolExecutor 详解

小结

在 JDK 中,内置了两个类,可以实现定时任务的功能:

  • java.util.Timer :可以通过创建 java.util.TimerTask 调度任务,在同一个线程中串行执行,相互影响。也就是说,对于同一个 Timer 里的多个 TimerTask 任务,如果一个 TimerTask 任务在执行中,其它 TimerTask 即使到达执行的时间,也只能排队等待。因为 Timer 是串行的,同时存在 坑坑 ,所以后来 JDK 又推出了 ScheduledExecutorService ,Timer 也基本不再使用。
  • java.util.concurrent.ScheduledExecutorService :在 JDK 1.5 新增,基于线程池设计的定时任务类,每个调度任务都会被分配到线程池中并发执行,互不影响。这样,ScheduledExecutorService 就解决了 Timer 串行的问题。

在日常开发中,我们很少直接使用 Timer 或 ScheduledExecutorService 来实现定时任务的需求。主要有几点原因:

  • 它们仅支持按照指定频率,不直接支持指定时间的定时调度,需要我们结合 Calendar 自行计算,才能实现复杂时间的调度。例如说,每天、每周五、2019-11-11 等等,不支持 Cron 表达式。
  • 它们是进程级别,而我们为了实现定时任务的高可用,需要部署多个进程。此时需要等多考虑,多个进程下,同一个任务在相同时刻,不能重复执行。
  • 项目可能存在定时任务较多,需要统一的管理,此时不得不进行二次封装。

所以,一般情况下,我们会选择专业的调度任务中间件

中间件

Spring Task

由于 SpringTask 已经存在于 Spring 框架中,所以无需添加依赖。

下面我们弄个小 Demo 测试一下,新建一个项目,引入依赖。

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.6.3</version>
  <relativePath/>
</parent>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
  </dependency>
</dependencies>

添加 SpringTask 的配置类

@Configuration
@EnableScheduling
public class SpringTaskConfig {

}

在 application.yml 添加关于 Spring Task 的配置,如下:

spring:
  task:
    # Spring Task 调度任务的配置,对应 TaskSchedulingProperties 配置类
    scheduling:
      thread-name-prefix: job- # 线程池的线程名的前缀。默认为 scheduling- ,建议根据自己应用来设置
      pool:
        size: 10 # 线程池大小。默认为 1 ,根据自己应用来设置
      shutdown:
        await-termination: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true
        await-termination-period: 60 # 等待任务完成的最大时长,单位为秒。默认为 0 ,根据自己应用来设置

spring.task.scheduling.shutdown 配置项,是为了实现 Spring Task 定时任务的优雅关闭。

定时任务测试类

@Service
@Slf4j
public class ScheduledTaskService {

  private final AtomicInteger counts = new AtomicInteger();

  //  @Scheduled(cron = "0 0/10 * ? * ?")//每10分钟执行一次
  @Scheduled(fixedRate = 3000) // 每 3秒执行一次
  public void pushMessage() {
    log.info("[execute]定时第({})给用户发送通知", counts.incrementAndGet());
  }

}

最后创建一个启动类,启动项目,控制台输出如下:

SpringTask定时任务

Spring Task 支持 Cron 表达式 。Cron 表达式主要用于定时作业(定时任务)系统定义执行时间或执行频率的表达式,非常厉害,你可以通过 Cron 表达式进行设置定时任务每天或者每个月什么时候执行等等操作。

Cron 格式中每个时间元素的说明

Cron参数说明

平时可以找一个 Cron 表达式生成器在线网站按需生成想要的表达式。

SpringTask 功能小结:

1、SpringTask 内置于 Spring 框架,相比于Quartz更加简单方便,不需要引入其他依赖。

2、Spring Task 底层是基于 JDK 的 ScheduledThreadPoolExecutor 线程池来实现的。

3、支持 Cron 表达式

4、只支持单机,功能单一

Quartz

Github:https://github.com/quartz-scheduler/quartz

Quartz 作为一个优秀的开源调度框架,Quartz 具有以下特点:

  1. 强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求;
  2. 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式;
  3. 分布式和集群能力,Terracotta 收购后在原来功能基础上作了进一步提升。

另外,作为 Spring 默认的调度框架,Quartz 很容易与 Spring 集成实现灵活可配置的调度功能。

在 Quartz 体系结构中,有三个组件非常重要:

  • Scheduler :调度器。Scheduler启动Trigger去执行Job。
  • Trigger :触发器。用来定义 Job(任务)触发条件、触发时间,触发间隔,终止时间等。四大类型:SimpleTrigger(简单的触发器)、CornTrigger(Cron表达式触发器)、DateIntervalTrigger(日期触发器)、CalendarIntervalTrigger(日历触发器)。
  • Job :任务。具体要执行的业务逻辑,比如:发送短信、发送邮件、访问数据库、同步数据等。

Quartz 应用分为单机模式和集群模式。实际应用中,我们都会选择集群模式,关于 Quartz 的使用,后续会单独出一篇文章进行介绍。

Quartz 框架出现的比较早,后续不少定时框架,或多或少都基于 Quartz 研发的,比如当当网的elastic-job就是基于quartz二次开发之后的分布式调度解决方案。

并且,Quartz 并没有内置 UI 管理控制台,不过你可以使用 quartzui 这个开源项目来解决这个问题。

Quartz 虽然也支持分布式任务。但是,它是在数据库层面,通过数据库的锁机制做的,有非常多的弊端比如系统侵入性严重、节点负载不均衡。

Quartz 优缺点:

  • 可以与 Spring 集成,并且支持动态添加任务和集群。
  • 分布式支持不友好,没有内置 UI 管理控制台、使用麻烦(相较于其他框架)。

XXL-JOB

官方说明:XXL-JOB 是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。

通俗来讲:XXL-JOB 是一个任务调度框架,通过引入 XXL-JOB 相关的依赖,按照相关格式撰写代码后,可在其可视化界面进行任务的启动执行中止以及包含了日志记录与查询任务状态监控

官方文档:https://www.xuxueli.com/xxl-job/

GitHub:https://github.com/xuxueli/xxl-job

Gitee:http://gitee.com/xuxueli0323/xxl-job

特性:

xxl-job特性

Xxl-job 解决了很多 Quartz 的不足。

Xxl-job 解决了很多 Quartz 的不足

XXL-JOB 的架构设计如下图所示:

xxl-job架构图

从上图可以看出,XXL-JOB调度中心执行器 两大部分组成。调度中心主要负责任务管理、执行器管理以及日志管理。执行器主要是接收调度信号并处理。另外,调度中心进行任务调度时,是通过自研 RPC 来实现的。

关于 xxl-job 的使用,下篇文章会详细介绍的。

xxl-job 的优点相对于 Quartz 非常明显,使用更加简单,而且内置了 UI 管理控制台。

Elastic-Job

Github:https://github.com/apache/shardingsphere-elasticjob

官方文档:https://shardingsphere.apache.org/elasticjob/current/cn/overview/

ElasticJob 是面向互联网生态和海量任务的分布式调度解决方案,基于QuartzZooKeeper 开发,由两个相互独立的子项目 ElasticJob-Lite 和 ElasticJob-Cloud 组成。 它通过弹性调度、资源管控、以及作业治理的功能,打造一个适用于互联网场景的分布式调度解决方案,并通过开放的架构设计,提供多元化的作业生态。 它的各个产品使用统一的作业 API,开发者仅需一次开发,即可随意部署。

ElasticJob-Lite 的架构设计如下图所示:

ElasticJob-Lite Architecture

从上图可以看出,Elastic-Job 没有调度中心这一概念,而是使用 ZooKeeper 作为注册中心,注册中心负责协调分配任务到不同的节点上。

Elastic-Job 中的定时调度都是由执行器自行触发,这种设计也被称为去中心化设计(调度和处理都是执行器单独完成)。

@Component
@ElasticJobConf(name = "dayJob", cron = "0/10 * * * * ?", shardingTotalCount = 2,
        shardingItemParameters = "0=AAAA,1=BBBB", description = "简单任务", failover = true)
public class TestJob implements SimpleJob {
    @Override
    public void execute(ShardingContext shardingContext) {
        log.info("TestJob任务名:【{}】, 片数:【{}】, param=【{}】", shardingContext.getJobName(), shardingContext.getShardingTotalCount(),
                shardingContext.getShardingParameter());
    }
}

Elastic-Job 支持的功能:

Elastic-Job 支持的功能

关于 Elastic-Job 的使用,未来会抽时间出一篇文章的。

Elastic-Job 相较于 XXL-JOB 缺点也比较明显,就是需要引入额外的中间件,比如 Zookeeper,增加了操作难度。

总结

由于本人目前接触到的框架有限,除了上述四种中间件,还有不少大公司自研的中间件,如果从个人开发的角度来看,推荐大家使用 XXL-JOB,开箱即用,且配有可视化界面。如果想对其他中间件有所了解,这里推荐阅读如下两篇文章:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java定时任务技术分析 的相关文章

  • 如何从二维数组中仅打印单个列?

    我正在编写这个程序 我必须只打印二维数组的一列 而不是两者 for int i 0 i lt sjf length i for int j 0 j lt sjf i length j System out printf 5d 4s sjf
  • 使用 REST API 实现属性/字段级安全

    我正在为支持多租户授权模型的 REST API 构建概念验证 该模型不仅控制用户可以访问哪些对象 还控制对象中的字段 此模型的目标是确保租户管理员只能修改其租户并且只能查看允许的对象属性 我有一个正在开发的现有代码库 可在以下位置公开获取
  • Zuul不转发请求到其他微服务

    我正在使用 Spring Boot 微服务 我已经配置了 eureka zuul 代理和另一个微服务 帐户 如果我直接从帐户拨打电话 则工作正常 帐户和 zuul 服务器都显示在 eureka 上 当我尝试使用 zuul 代理进行访问时 它
  • SpringMVC 和 Hibernate:CannotCreateTransactionException:无法打开 Hibernate 会话进行事务;

    我正在尝试设置并Spring MVC 休眠项目 但它让我发疯 我还会考虑订购 xml 配置文件的建议 我有以下文件 web xml
  • JaxB2Marshaller 未将 XML 绑定到 Kotlin 数据类

    我正在编写一个批处理作业来解析 XML 提取字段并将它们保存在数据库中 解析 XML 时 它会选取 2 个根元素 但将所有字段保留为空 因此在我的数据库中 我有 2 条记录将为空字段 似乎无法弄清楚为什么它无法读取元素 TIA Bean f
  • log4j2 SMTP Appender:如何包含另一个级别的先前消息?

    我正在使用 log4j2 beta9 并且有以下配置 其中一部分
  • 正则表达式查找两个字符之间的内部匹配

    环境 Java 我想匹配两个字符串之间的字符 这是一个例子 foo
  • Gradle中的build-by-convention深度解释是什么?

    The 摇篮用户指南 http www gradle org docs current userguide userguide html经常提到 Gradle 是陈述性的和用途按惯例构建 这是什么意思 据我了解 这意味着 例如 在java插
  • 高负载应用程序的数据库可扩展性?

    我见过一些应用程序拥有集群 Web 服务器 例如 10 到 20 个服务器 以具有可扩展性 可以在其中分发 在网络服务器之间加载 但我总是看到所有网络服务器都使用单个数据库 现在考虑任何电子商务或铁路 Web 应用程序 其中有数百万用户在任
  • 从java应用程序发送电子邮件时出现异常:中继被拒绝

    我们正在使用 Spring Mail 从 java 应用程序发送电子邮件 org springframework mail javamail JavaMailSenderImpl Spring电子邮件配置是
  • 如何从网上获取源代码?

    我正在尝试从 Web 获取 HTML 源代码 我尝试这样做 u new URL url URLConnection con u openConnection con setRequestProperty User Agent Mozilla
  • 在Java中打印时差最惯用的方法是什么?

    我熟悉以毫秒为单位的打印时间差 long time System currentTimeMillis do something that takes some time long completedIn System currentTime
  • 从两个数组中查找公共文件

    我正在尝试从两个数组中查找通用名称文件 我已将两个不同文件夹的文件名保存在两个不同的数组中 现在我正在创建一个通用文件数组 其中包含具有通用名称的文件 filenames 1 包含文件夹 1 中文件名称的数组 filename2 包含文件夹
  • Jlist 自定义渲染器

    我正在尝试添加一个我猜你会称其为列表中每个项目的子列表 我构建了一个自定义渲染器 它提供以下输出 正如你所看到的 有些东西不对劲 我没能找到问题的答案 我猜我需要更改面板布局中的某些内容才能获得正确的结果 但不知道是什么 https i s
  • 调用本机方法时返回 java.lang.UnsatisfiedLinkError

    我正在尝试为第三方 DLL 制作 Java 包装器 我创建了自己的 DLL 充当 JNI 和第三方 DLL 之间的中间人 在java中我加载这个DLL很好但是错误java lang UnsatisfiedLinkError sixense
  • Spring Hibernate中的@Transient方法调用

    我有一个 Pojo 类 在其中创建一个未与数据库表映射的字段 所以我必须声明字段Declaration和setter和getter方法 Transient 否则会显示错误 Transient private String docHistor
  • 为什么对象可以改变类变量的值?

    由甲骨文提供定义 http docs oracle com javase tutorial java javaOO classvars html 有时 您希望拥有所有对象共有的变量 这是通过 static 修饰符来完成的 声明中带有 sta
  • 使用 testcontainer 作为 Dockerfile 的一部分运行测试

    我的 dockerfile 看起来像这样 FROM maven 3 jdk 11 slim COPY pom xml COPY src src RUN mvn clean install 这意味着构建的一部分是单元测试的执行 一些单元测试使
  • 错误:找不到符号 ArrayList

    我正在尝试创建某种列表来存储数组 表 中的值 我在这里使用数组列表 但我应该使用列表吗 但是 每次我尝试编译时 它都会引发以下错误 找不到标志 符号 ArrayList类 位置 玩家类 TablePlayer 代码如下 public cla
  • Spring MVC 和复选框

    我正在使用 Spring MVC 3 0 并且不能完全看到这个问题的所有部分 我的控制器将生成一个域对象列表 假设有一个简单的 User 对象 具有firstName lastName age 和role 属性 我想在表中输出该用户列表 每

随机推荐

  • vue上传文件夹,将file类型转为binary类型传参到后台

  • ES6-promise小技巧

    Promise all 从Promise all返回的主promise在所有成员promise都完成后才会执行 如果这些promise中有任何一个被拒绝 reject error 住promise就会被拒绝 并丢弃来自其他所有promise
  • 【Jupyter Notebook】安装及使用

    知识目录 前言 一 Jupyter Notebook安装使用 1 1 Jupyter Notebook的三种打开方式 1 点击Anaconda Prompt打开 2 点击Jupyter Notebook打开 3 使用Powershell打开
  • [计算机毕业设计]机器学习的数据驱动股票价格预测

    前言 大四是整个大学期间最忙碌的时光 一边要忙着准备考研 考公 考教资或者实习为毕业后面临的就业升学做准备 一边要为毕业设计耗费大量精力 近几年各个学校要求的毕设项目越来越难 有不少课题是研究生级别难度的 对本科同学来说是充满挑战 为帮助大
  • 算法设计与分析——0/1背包问题

    问题描述 给定n个重量为 w1 w2 wn 价值为 v1 v2 vn 的物品和一个容量为C的背包 0 1背包问题是求这些物品中的一个 最有价值的子集 并且能够装入背包中 基本算法思想 暴力法 用暴力法解决0 1背包问题 需要考虑给定n个物品
  • 概率密度函数

    概率密度函数 Probability Density Function 简称PDF 是描述随机变量的概率分布的函数 它对于连续型随机变量来说是非常重要的概念 PDF可以用来描述变量在不同取值上的概率分布情况 对于一个连续型随机变量X 其概率
  • 记忆化搜索 (蒟蒻练习生)

    定义 记忆化搜索是一种通过记录已经遍历过的状态的信息 从而避免对同一状态重复遍历的搜索实现方式 因为记忆化搜索确保了每个状态只访问一次 它也是一种常见的动态规划实现方式 引入 题目见 NOIP2005 采药 朴素的 DFS 做法 很容易实现
  • Python web自动化测试 —— 文件上传

    文件上传三种方式 一 查看元素标签 如果是input 则可以参照文本框输入的形式进行文件上传 方法 和用户输入是一样的 使用send keys 1 2 3 4 5 步骤 1 找到定位元素 2 输入文件路径 ele driver find e
  • ios android 字体大小,并排文字在ios上字体变大,安卓上正常显示

    IOS页面 安卓页面 复现代码 公告 疑情公告 notice notice export default data return notice 中民筑友码垛机作业区域一号工位发 疑似闯入行为中民筑友码垛机作业区域一号工位发 疑似闯入行为 发
  • Golang中结构体Struct

    前言 这里总结的Golang 笔记只适合有点编程基础的人看 比如Java 往期内容 Golang学习 day1 变量 类型 Golang学习 指针 循环控制相关 循环结构控制 包函数的使用 异常处理 数组 老奶奶可以看懂的切片 老奶奶可以看
  • C++之extern和static用法和区别

    目录 声明和定义的区别 关键字extern 作用 用法总结 关键字static 全局变量和全局静态变量区别 局部静态变量 静态函数 声明和定义的区别 变量定义 用于为变量分配存储空间 还可为变量指定初始值 程序中 变量有且仅有一个定义 变量
  • C语言读取写入CSV文件基础入门篇

    什么是CSV 大量C语言项目课设 小游戏源码 压 缩 包 免 费 下 载 链 接 如 下 c语言项目课设小游戏源码资料压缩包 zip C文档类资源 CSDN下载c语言项目课设小游戏源码资料压缩包 zipc语言项目课设小游戏源码资料压缩包 z
  • 数据驱动的数字化转型:从流程驱动到数据驱动

    以下文章来源于凯哥讲故事系列 作者凯哥 数字化时代已经到来 1996年的时候 Being Digital 的作者Negroponte就提出数字化生活的概念 而20年以后的今天 我们已经进入了数字化的生活 移动互联网 物联网 手机 各种社交媒
  • 刷脸支付无一例外地建构与完善起来

    刷脸支付均采用的是3D人脸识别技术 这种技术具有一项至关重要的功能 活体检测 即系统摄像头在识别人脸是否为本人的同时 还能检验是否有人利用照片等手段冒充用户 由此封闭了假体攻击的空间 正如支付工具的迭代总是高出人们的预估一样 技术的进化对于
  • 小程序配置网络请求@escook/request-miniprogram

    由于平台限制 小程序项目不支持axios 原生wx request API功能较为简单 不支持拦截器等功能 所以使用 escook request miniprogram第三方包发起网络数据请求 配置步骤 官方文档 https www np
  • 浅谈.NET语言开发应用领域

    NET语言是一种跨平台的开发框架 适用于各种应用程序的开发 以下是一些常见的 NET语言开发应用领域 桌面应用程序开发 使用 NET框架开发的桌面应用程序可以在Windows操作系统上运行 包括Windows Forms和WPF 这些应用程
  • 智能指针之weak_ptr06

    一 weak ptr 看名字就知道 他是一个弱引用 他的存在是为了辅助shared ptr的循环引用问题 它不占用引用数 只能通过shared ptr或者weak ptr构造赋值 它没有重载 和 gt 运算符 因此不可以直接通过 weak
  • hvv 文件上传和文件包含考点

    天眼如何判断文件上传漏洞是否成功 数据包分析 观察客户端请求数据 是否包含webshell流量特征 观察服务器返回信息 是否有 上传成功 或 success upload 等信息提示 尝试寻找上传的文件 访问上传的文件看是否存在 查看文件上
  • Java的数据类型及变量

    一 变量 内存存储的是运行中程序的数据 eg 我有10块钱 买早餐花了6元 问我现在还有多钱 计算机 1 存储数据 2 CPU取出来 参与运算 3 结果更新内存 变量的本质 内存中的一个存储空间 另一种说法 程序运行过程中 其值可以发生改变
  • Java定时任务技术分析

    从零打造项目 系列文章 工具 比MyBatis Generator更强大的代码生成器 ORM框架选型 SpringBoot项目基础设施搭建 SpringBoot集成Mybatis项目实操 SpringBoot集成MybatisPlus项目实