SpringCloud微服务实战——搭建企业级开发框架(四十二):集成分布式任务调度平台XXL-JOB,实现定时任务功能

2023-10-27

  定时任务几乎是每个业务系统必不可少的功能,计算到期时间、过期时间等,定时触发某项任务操作。在使用单体应用时,基本使用Spring提供的注解即可实现定时任务,而在使用微服务集群时,这种方式就要考虑添加分布式锁来防止多个微服务同时运行定时任务而导致同一个任务重复执行。
  除了使用注解,现在还有一种方式,就是搭建分布式任务平台,所有的微服务注册到分布式任务平台,由分布式任务平台统一调度,这样避免了同一任务被重复执行。这里我们选择使用XXL-JOB作为分布式任务调度平台,XXL-JOB核心设计目标是开发迅速、学习简单、轻量级、易扩展。
  使用分布式任务调度平台的优点除了避免同一任务重复执行外,还有使用简单,可以手动执行、有详细的调度日志查看任务具体执行情况等优点。
  XXL-JOB官方架构设计图:

xxl-job v2.1.0架构图

  下面我们按照步骤来介绍,如何结合我们的微服务平台将分布式任务调度平台XXL-JOB集成进来,实现我们需要的定时任务功能。

一、微服务框架整合xxl-job-admin
1、XXL-JOB开源网站下载源码,下载地址 https://github.com/xuxueli/xxl-job/releases ,下载下来的源码如下:
xxl-job-admin:调度中心
xxl-job-core:公共依赖
xxl-job-executor-samples:执行器Sample示例(选择合适的版本执行器,可直接使用,也可以参考其并将现有项目改造成执行器)
    :xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执行器,推荐这种方式;
    :xxl-job-executor-sample-frameless:无框架版本;

  下载下来的开源包有三个目录:xxl-job-admin、xxl-job-core和xxl-job-executor-samples,顾名思义,xxl-job-admin是分布式任务平台的服务端兼管理台,我们需要部署的也是这个工程,我们可以把整个工程集成到我们的微服务中,统一打包部署;xxl-job-core是公共依赖包,我们其他需要实现定时任务的微服务需要引入这个包来实现定时任务执行器。xxl-job-executor-samples为定时任务执行器的实例代码。

2、在基础平台gitegg-platform工程gitegg-platform-bom中引入xxl-job-core核心包,统一版本管理。
......
        <!--分布式任务调度平台XXL-JOB核心包-->
        <xxl-job.version>2.3.1</xxl-job.version>
......
            <!--分布式任务调度平台XXL-JOB核心包-->
            <dependency>
                <groupId>com.xuxueli</groupId>
                <artifactId>xxl-job-core</artifactId>
                <version>${xxl-job.version}</version>
            </dependency>
3、将xxl-job-admin集成到微服务工程中,方便统一打包部署

  根据我们的微服务架构设计,gitegg-plugin作为我们系统的插件工程,里面放置我们需要的插件服务。有些插件是必须的,而有些插件可能会用不到,此时我们就可以根据自己的业务需求去选择部署业务插件。
  为和我们的微服务深度集成就不是解耦的特性,我们需要对xxl-job-admin的配置文件进行适当的修改:

  • 首先修改pom.xml,保持各依赖库版本一致,修改parent标签,使其引用GitEgg工程的基础jar包和微服务配置注册功能,同时排除logback,使用log4j2记录日志
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>gitegg-plugin</artifactId>
        <groupId>com.gitegg.cloud</groupId>
        <version>1.0.1.RELEASE</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    
    <artifactId>gitegg-job</artifactId>
    <name>${project.artifactId}</name>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.test.skip>true</maven.test.skip>

        <netty-all.version>4.1.63.Final</netty-all.version>
        <gson.version>2.9.0</gson.version>

        <spring.version>5.3.20</spring.version>
        <spring-boot.version>2.6.7</spring-boot.version>

        <mybatis-spring-boot-starter.version>2.2.2</mybatis-spring-boot-starter.version>
        <mysql-connector-java.version>8.0.29</mysql-connector-java.version>

        <slf4j-api.version>1.7.36</slf4j-api.version>
        <junit-jupiter.version>5.8.2</junit-jupiter.version>
        <javax.annotation-api.version>1.3.2</javax.annotation-api.version>

        <groovy.version>3.0.10</groovy.version>

        <maven-source-plugin.version>3.2.1</maven-source-plugin.version>
        <maven-javadoc-plugin.version>3.4.0</maven-javadoc-plugin.version>
        <maven-gpg-plugin.version>3.0.1</maven-gpg-plugin.version>
    </properties>
    
    <dependencies>
        <!-- gitegg Spring Boot自定义及扩展 -->
        <dependency>
            <groupId>com.gitegg.platform</groupId>
            <artifactId>gitegg-platform-boot</artifactId>
        </dependency>
        <!-- gitegg Spring Cloud自定义及扩展 -->
        <dependency>
            <groupId>com.gitegg.platform</groupId>
            <artifactId>gitegg-platform-cloud</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis-spring-boot-starter.version}</version>
            <!-- 去除springboot默认的logback配置-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <!-- 去除springboot默认的logback配置-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- freemarker-starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
            <!-- 去除springboot默认的logback配置-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- mail-starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
            <!-- 去除springboot默认的logback配置-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- starter-actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <!-- 去除springboot默认的logback配置-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-connector-java.version}</version>
        </dependency>
        <!--分布式任务调度平台XXL-JOB核心包-->
        <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-job-core</artifactId>
            <!-- 去除冲突的slf4j配置-->
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>com.google.cloud.tools</groupId>
                <artifactId>jib-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

  • 修改application.properties ,根据我们系统的规范,新增bootstrap.yml、bootstrap-dev.yml、bootstrap-prod.yml、bootstrap-test.yml文件。将application.properties部分配置,移到bootstrap.yml配置中。因xxl-job-admin单独数据库,且其默认使用的是Hikari数据库连接池,这里我们不打算改动,仍然使其保持原有的数据库配置,我们将可配置的内容放置在Nacos微服务配置中心上,同时在bootstrap.yml中添加多yaml文件配置(请注意,在我们本地使用的是yml结尾的文件,Nacos服务注册中心上使用的是yaml结尾的文件,两者是一样的,只是扩展名的不同)。

bootstrap.yml配置:

server:
  port: 8007
spring:
  profiles:
    active: '@spring.profiles.active@'
  application:
    name: '@artifactId@'
  cloud:
    inetutils:
      ignored-interfaces: docker0
    nacos:
      discovery:
        server-addr: ${spring.nacos.addr}
      config:
        server-addr: ${spring.nacos.addr}
        file-extension: yaml
        extension-configs:
          # 必须带文件扩展名,此时 file-extension 的配置对自定义扩展配置的 Data Id 文件扩展名没有影响
          - data-id: ${spring.nacos.config.prefix}.yaml
            group: ${spring.nacos.config.group}
            refresh: true
          - data-id: ${spring.nacos.config.prefix}-xxl-job.yaml
            group: ${spring.nacos.config.group}
            refresh: true
  ### xxl-job-admin config
  mvc:
    servlet:
      load-on-startup: 0
    static-path-pattern: /static/**
  resources:
    static-locations: classpath:/static/
  ### freemarker
  freemarker:
    templateLoaderPath: classpath:/templates/
    suffix: .ftl
    charset: UTF-8
    request-context-attribute: request
    settings.number_format: 0.##########
### actuator
management:
  server:
    servlet:
      context-path: /actuator
  health:
    mail:
      enabled: false
### mybatis
mybatis:
  mapper-locations: classpath:/mybatis-mapper/*Mapper.xml


Nacos上gitegg-cloud-config-xxl-job.yaml配置:

server:
  servlet:
    context-path: /xxl-job-admin
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1/xxl_job?useSSL=false&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
    ### datasource-pool
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimum-idle: 10
      maximum-pool-size: 30
      auto-commit: true
      idle-timeout: 30000
      pool-name: HikariCP
      max-lifetime: 900000
      connection-timeout: 10000
      connection-test-query: SELECT 1
      validation-timeout: 1000
  ### email
  mail:
    host: smtp.qq.com
    port: 25
    username: xxx@qq.com
    from: xxx@qq.com
    password: xxx
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true
          socketFactory:
            class: javax.net.ssl.SSLSocketFactory
### xxl-job, access token
xxl:
  job:
    accessToken: default_token
    ### xxl-job, i18n (default is zh_CN, and you can choose "zh_CN", "zh_TC" and "en")
    i18n: zh_CN
    ## xxl-job, triggerpool max size
    triggerpool: 
      fast: 
        max: 200
      slow:
        max: 100
    ### xxl-job, log retention days
    logretentiondays: 30
4、初始化xxl-job-admin需要的数据库脚本

  初始化脚本存放在下载的包目录的\xxl-job-2.3.1\doc\db\tables_xxl_job.sql中,一共需要8张表。我们将xxl-job-admin的数据库和业务数据库分开,配置不同的数据源,在Nacos配置单独的xxl-job-admin配置文件。

  • 新建xxl_job数据库

xxl_job数据库

  • 打开数据库执行建表语句

image.png

5、在GitEgg工程的父级pom.xml下添加静态文件过滤

  xxl-job-admin是SpringMVC项目,其前端页面由ftl文件和静态文件组成,默认情况下maven启用分环境读取配置时,会对resource目录下的@进行替换,导致静态文件下的字体文件不能用,所以,这里需要进行和jks文件一样的过滤配置:

        <resources>
            <!-- 增加分环境读取配置 -->
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <excludes>
                    <exclude>**/*.jks</exclude>
                    <exclude>static/**</exclude>
                </excludes>
            </resource>
            <!-- 解决jks被过滤掉的问题 -->
            <resource>
                <directory>src/main/resources</directory>
                <filtering>false</filtering>
                <includes>
                    <include>**/*.jks</include>
                    <include>static/**</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
6、在Gateway添加xxl-job-admin路由转发

  xxl-job-admin路由转发需要添加两方面内容,一个是xxl-job-admin注册到Nacos注册中心上的gitegg-job服务,一个是xxl-job-admin前端页面请求的静态文件转发。第一个是为了和我们整体微服务保持一致,第二个是为了解决xxl-job-admin前端ftl页面在请求静态文件时,请求的是/xxl-job-admin根路径。新增Gateway路由转发配置如下:

        - id: gitegg-job
          uri: lb://gitegg-job
          predicates:
            - Path=/gitegg-job/**
          filters:
            - StripPrefix=1
        - id: xxl-job-admin
          uri: lb://gitegg-job
          predicates:
            - Path=/xxl-job-admin/**
          filters:
            - StripPrefix=0
7、增加xxl-job-admin访问白名单

  xxl-job-admin有自己的权限访问控制,我们不在网关对其进行鉴权,所以在Nacos配置中,增加白名单配置:

# 网关放行设置 1、whiteUrls不需要鉴权的公共url,白名单,配置白名单路径 2、authUrls需要鉴权的公共url
oauth-list:
......
  whiteUrls:
......
    - "/gitegg-job/**"
    - "/xxl-job-admin/**"
......
8、启动xxl-job-admin微服务,查看是否启动成功,默认用户名密码: admin/123456

启动成功

登录页

登录成功页

二、测试XXL-JOB定时任务功能

  我们在上面的第一步中,完成了xxl-job-admin的整合和启动,xxl-job-admin可以看做是分布式任务的服务注册中心和管理台,如果我们需要实现定时任务,还需要具体实现执行器让xxl-job-admin调用执行。
  XXL-JOB支持多种方式的定时任务调用,可以将定时任务执行器写在业务代码中,也可以写在xxl-job-admin服务端:

  • BEAN模式(类形式): Bean模式任务,支持基于类的开发方式,每个任务对应一个Java类。
  • BEAN模式(方法形式): Bean模式任务,支持基于方法的开发方式,每个任务对应一个方法。
  • GLUE模式(Java/Shell/Python/NodeJS/PHP/PowerShell) :任务以源码方式维护在调度中心,支持通过Web IDE在线更新,实时编译和生效,因此不需要指定JobHandler。
1、增加xxl-job通用配置

  新增gitegg-platform-xxl-job工程,增加通用配置XxlJobConfig.java通用配置,这样在需要使用定时任务的微服务中,只需要引入一次即可,不需要重复配置。

XxlJobConfig.java:

package com.gitegg.platform.xxl.job.config;

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * xxl-job config
 *
 * @author xuxueli 2017-04-28
 */
@Slf4j
@Configuration
public class XxlJobConfig {

    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;

    @Value("${xxl.job.accessToken}")
    private String accessToken;

    @Value("${xxl.job.executor.appname}")
    private String appname;

    @Value("${xxl.job.executor.address}")
    private String address;

    @Value("${xxl.job.executor.ip}")
    private String ip;

    @Value("${xxl.job.executor.port}")
    private int port;

    @Value("${xxl.job.executor.logpath}")
    private String logPath;

    @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays;


    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        log.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppname(appname);
        xxlJobSpringExecutor.setAddress(address);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

        return xxlJobSpringExecutor;
    }

    /**
     * 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;
     *
     *      1、引入依赖:
     *          <dependency>
     *             <groupId>org.springframework.cloud</groupId>
     *             <artifactId>spring-cloud-commons</artifactId>
     *             <version>${version}</version>
     *         </dependency>
     *
     *      2、配置文件,或者容器启动变量
     *          spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
     *
     *      3、获取IP
     *          String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
     */
}

Nacos配置中心:

xxl:
  job:
    admin:
      addresses: http://127.0.0.1/xxl-job-admin
    accessToken: 'default_token'
    executor:
      appname: ${spring.application.name}
      address:
      ip:
      port: 9999
      logpath: D:\\log4j2_nacos\\xxl-job\\jobhandler
      logretentiondays: 30
2、实现定时任务测试代码

  我们在gitegg-service-system中测试定时任务执行器,先在pom.xml中添加gitegg-platform-xxl-job依赖,然后新增SystemJobHandler.java测试类

SystemJobHandler.java:

package com.gitegg.service.system.jobhandler;

import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * 定时任务示例代码,其他更多示例请查看
 * https://www.xuxueli.com/xxl-job
 * @author GitEgg
 */
@Slf4j
@Component
public class SystemJobHandler {
    
    /**
     * 1、简单任务示例(Bean模式)不带返回值
     */
    @XxlJob("systemJobHandler")
    public void systemJobHandler() throws Exception {
        
        XxlJobHelper.log("不带返回值:XXL-JOB, Hello World.");
        for (int i = 0; i < 5; i++) {
            XxlJobHelper.log("beat at:" + i);
            TimeUnit.SECONDS.sleep(2);
        }
    }
    
    /**
     * 2、简单任务示例(Bean模式)带成功或失败返回值
     */
    @XxlJob("userJobHandler")
    public ReturnT<String> userJobHandler() throws Exception {
        
        XxlJobHelper.log("带返回值:XXL-JOB, Hello World.");
        for (int i = 0; i < 5; i++) {
            XxlJobHelper.log("beat at:" + i);
            TimeUnit.SECONDS.sleep(2);
        }
        return ReturnT.SUCCESS;
    }

}

3、配置xxl-job-admin新增执行器
  • 新增时:
    新增
  • gitegg-service-system服务启动后,自动注册:
    自动注册
4、新增xxl-job-admin任务

  执行器可以看做是一组微服务,而任务是微服务具体执行的方法。任务新增后,默认是STOP状态,需要手动启动,当列表显示RUNNING时,表示该任务是运行状态,会根据配置的时间执行。

任务新增界面

任务启动

5、查看执行器是否执行

  在本地开发环境查看任务执行的方式有多种,直接Debug也可以,生产环境我们可以查看xxl-job日志,在测试代码中记录的log,在xxl-job-admin管理台都可以详细查看。

调度日志列表

调度日志详情

  通过以上操作步骤,我们将xxl-job和xxl-job-admin整合到了我们的微服务架构中,只需要在有任务调度需求的微服务中实现执行器就可以满足我们的需求了。

GitEgg-Cloud是一款基于SpringCloud整合搭建的企业级微服务应用开发框架,开源项目地址:

Gitee: https://gitee.com/wmz1930/GitEgg
GitHub: https://github.com/wmz1930/GitEgg

欢迎感兴趣的小伙伴Star支持一下。

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

SpringCloud微服务实战——搭建企业级开发框架(四十二):集成分布式任务调度平台XXL-JOB,实现定时任务功能 的相关文章

随机推荐

  • 调用阿里云语音合成Python版SDK

    一 阿里云介绍 阿里云创立于2009年 是全球领先的云计算及人工智能科技公司 致力于以在线公共服务的方式 提供安全 可靠的计算和数据处理能力 让计算和人工智能成为普惠科技 阿里云服务着制造 金融 政务 交通 医疗 电信 能源等众多领域的领军
  • 简单四边形不等式优化dp(下)

    广义决策单调性 强烈推荐题解视频 设 f k i f k i fk i 表示前
  • 【腾讯云的1001种玩法】JavaWeb项目部署指南

    腾讯云技术社区 博客主页持续为大家呈现云计算技术文章 欢迎大家关注 作者 刘潇龙 如何快速直接地在腾讯云上部署JavaWeb项目 第一步 登录 我选了ubuntu系统 账户是ubuntu 于是在终端里 ssh ubuntu aa bb cc
  • poj 2096 Collecting Bugs

    Problem poj org problem id 2096 vjudge net contest 151678 problem Q Reference blog csdn net xingyeyongheng article detai
  • 导出一个schame并排除不必要的表

    由于测试的需要 下午收到一个邮件 要求搭建一个测试环境 使用expdp导数据的时候 将数据量大于1千万的表只导一部分 其他的表全部导出 然后看了一下要导出的表一共有545张 然而有大概30多张表的数据量大于1千万行 表那么都 不可能一张一张
  • 线性回归用matlab怎么做,matlab中如何应用regress()函数进行线性回归分析?

    matlab中如何应用regress 函数进行线性回归分析 回归分析是研究一个随机变量与一个或多个普通变量之间的相关系的统计方法 如果做回归分析 有很多软件都已经封装好了的 我们只需直接调用就可以了 例如Matlab中的regress 就是
  • 视频监控智能分析之火焰检测原理

    一 应用背景 基于视频分析的室内 室外烟火自动检测预警系统的目的是能够实现无人值守的不间断工作 自动发现监控区域内的异常烟雾和火灾苗头 以最快 最佳的方式进行告警和协助消防人员处理火灾危机 并最大限度的降低误报和漏报现象 同时还可查看现场实
  • AI实战营第二期——第一次作业:基于RTMPose的耳朵穴位关键点检测

    文章目录 题目 基于RTMPose的耳朵穴位关键点检测 背景 任务 数据集 训练目标检测器 错误 NameError name unicode is not defined 评估目标检测器 训练关键点检测器 评估关键点检测器 模型轻量化转换
  • USB——眼图测试常识

    最近的项目外设的USB总是传输数据异常 供应商建议我们做USB眼图测试 对于纯软件出身的我对USB本身都知之甚少 更别提眼图了 赶紧补课 如果将被测信号输入示波器 并且当示波器的触发时钟和被测信号同步时 在示波器上显示的图形很象人的眼睛 因
  • 持安科技入选CCIA2023年中国网安产业潜力之星!

    近日 中国网络安全产业联盟 CCIA 公布2023年中国网安产业潜力之星 持安科技作为零信任领域明星创业公司 成功入选榜单 中国网络安全产业联盟 CCIA 自2023年3月份启动网络安全企业发展情况调研工作 本次调研延续前五次产业调研模式
  • VSCODE设置自动换行后仍然无法在视区宽度内自动换行

    问题 百度如何设置vscode在视区内自动换行 查到的是设置word wrap设置为 on 即可 但我设置后仍然无法在视区宽度内自动换行 原因 设置错误 在vscode选项里搜索 wordwrap 会出现两个结果 第一个是Diff edit
  • 2017.5.27测试 2. 刷题(P1167)

    2 刷题 c pas cpp c 题目背景 好啊 一言为定 作为蒟蒻的GJY竟然约定和神犇来一场世纪大战 题目描述 GJY在期末的时候跟神犇约定了一次战争 这对于GJY来说可是一件具有挑战性并十分困难的事情 所有GJY从现在开始就要努力学习
  • linux安装nodejs,并切换版本

    之前使用linux系统centos7中遇见nodejs版本过低的问题 想要切换版本可以阅读以下参考 yum update 安装nodejs命令 yum install nodejs 查看node版本号 node v 查看npm版本号 npm
  • QT 常用部件 之窗体篇 widget 属性(一)

    这里介绍的是widget 窗体的属性 最完整的属性请查看qt自带的帮助文档 这里之拿了一部分做说明 窗体属性 object name 物件名称 qwidget enable 使能本部件 geometry 窗口位置和大小设置 sizepoli
  • 6.Xaml CheckBox控件

    1 运行图片 2 运行源码 a xaml 源码
  • 微信小程序调用相册和相机

    首先来写好wxml部分 给一个图片列表 img list 和上传图片的按钮 addimg
  • Android 12.0 禁用系统app首次启动动画SplashScreen功能分析

    1 前言 在12 0的系统开发中 由于系统增加了新特性 在app首次启动的时候 添加了启动引导动画SplashScreen功能 所以会默认显示 app图标作为一张动画来过度 解决首次启动卡顿问题 接下来分析下看是怎么样添加的 然后禁用就可以
  • 高性能RTL仿真器ESEENT专题1:安装

    ESSENT是最近提出的一种高性能开源RTL仿真器 本节开始详细介绍ESEENT 首先介绍下开源工具的使用 我们使用的环境是ubuntu20 源代码 git clone https github com ucsc vama essent g
  • IntelliJ Idea解决Could not autowire. No beans of ‘xxxx‘ type found的错误提示

    SpringMVC整合的时候 一共两种可能 翻遍了所有的帖子 一 注解没有写 service层多看看 二 包扫描名字写错 我就是坑在这儿 还有 看到Autowired报错千万别放过 有可能有大问题
  • SpringCloud微服务实战——搭建企业级开发框架(四十二):集成分布式任务调度平台XXL-JOB,实现定时任务功能

    定时任务几乎是每个业务系统必不可少的功能 计算到期时间 过期时间等 定时触发某项任务操作 在使用单体应用时 基本使用Spring提供的注解即可实现定时任务 而在使用微服务集群时 这种方式就要考虑添加分布式锁来防止多个微服务同时运行定时任务而