SpringBatch从入门到实战(二):HelloWorld

news2024/11/19 18:45:23

一:HelloWorld

1.1 配置Job、Step、Tasklet

在这里插入图片描述

@Configuration
public class HelloWorldJobConfig {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;


    @Bean
    public Job helloWorldJob() {
        return jobBuilderFactory.get("helloWorldJob")
                .start(hellWorldStep())
                .build();
    }

    @Bean
    public Step hellWorldStep() {
        return stepBuilderFactory.get("hellWorldStep")
                .tasklet(hellWorldTasklet())
                .build();
    }

    @Bean
    public Tasklet hellWorldTasklet() {
        return new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("hello world spring batch");
                return RepeatStatus.FINISHED;
            }
        };
    }
}

RepeatStatus枚举有两个值:

  • FINISHED:表示完成,一般都是返回FINISHED。
  • CONTINUABLE:继续,如果返回该值,会死循环的执行execute()方法。

1.2 手动触发作业Job

@RestController
@RequestMapping("/job")
public class JobController {
    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    @Qualifier("helloWorldJob")
    private Job job;


    @RequestMapping("/start")
    public ExitStatus start() throws Exception {
        JobExecution jobExecution = jobLauncher.run(job, new JobParameters());
        return jobExecution.getExitStatus();
    }
}

在这里插入图片描述

在这里插入图片描述

1.3 基础概念

  • JobLauncher作业启动器,启动作业的入口。对应的实现类为SimpleJobLauncher。
  • Job作业,用于配置作业的相关配置,一个作业可以配置多个步骤,步骤之间是有序的。
  • Step步骤,作业具体执行的业务逻辑,一个Job可以配置多个Step。步骤有两种实现方式:
    • Tasklet方式:所有作业逻辑写在一个方法中。
    • Chunk方式:将一个完整的作业逻辑根据作用拆分到三个方法中
      • ItemReader:负责从数据源中读数据(如从文件、数据库等)。
      • ItemProcessor :负责对读出来的数据进行非法校验和对数据进行加工。
      • ItemWriter:将数据写到某个目标中(如文件、数据库等)。
  • JobBuilderFactory作业构建起工厂,用于构建作业Job对象。
    • get(String name):设置作业名称。
    • start(Step step):设置作业启动的第一个步骤。
    • build():构建Job对象。
  • StepBuilderFactory作业构建器工厂,用于构造步骤Step对象。
    • get(String name):设置步骤名称。
    • tasklet(Tasklet tasklet):设置Tasklet。
    • build():构建Step对象。
  • Tasklet:用来封装批处理具体的业务逻辑。
  • JobRepository:作业持久化,在执行作业的过程中用于操作spring batch相关的表,记录作业的相关状态等。

1.4 JobInstance作业实例和JobExecution作业执行

  • exitCode=COMPLETED, 表示一个执行实例,往BATCH_JOB_INSTANCE表中插入一条数据。
  • 每执行一次作业(无论exitCode是什么)都会往BATCH_JOB_EXECUTION表中插入一条数据。
  • 当exitCode=COMPLETED时,一个作业中配置了多少个步骤就往BATCH_STEP_EXECUTION表插入多少条数据。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.5 第二次启动作业

在这里插入图片描述

注意:exitCode: COMPLETED,表示作业真正完成。一旦成功执行了这次作业,就不允许执行第二次,如果再执行会返回NOOP,表示无效的作业。 如果想重复执行可以改一下jobName或者改一下jobParameters。

每执行一次(无论exitCode是什么值)就会往BATCH_JOB_EXECUTION表插入一条记录,所以第二次执行作业也会插入一条数据,但是status=COMPLETEDexit_code=NOOP,exit_code表示此次的退出状态,status表示整个作业状态。

在这里插入图片描述

1.6 Job、JobInstance、JobExecution关系

  • 同一个job_name在BATCH_JOB_INSTANCE表中有多少条数据取决于 (job_name + job_key) 作为联合主键,job_key又依赖于JobParameters,同一个Job可以有不同的JobParameters,所以Job和JobInstance是多对多的关系。
  • 每执行一次作业就会生成一条JobExecution(无论exitCode是什么),当作业执行成功时有1条JobExecution,当执行失败时可以重新执行,JobExecution会大于1条,所以JobInstance和JobExecution是多对多的关系。

在这里插入图片描述

二:多步骤

一个Job可以配置多个Step,多个步骤按照定义的先后顺序执行:

  • start(Step):定义第一个步骤。
  • next(Step):定义其它后续步骤。
@Bean
public Job helloWorldJob() {
    return jobBuilderFactory.get("helloWorldJob")
    		// 第一个步骤
            .start(hellWorldStep())
            // 其它步骤
            .next(hellWorldStep2())
            .build();
}


@Bean
public Step hellWorldStep() {
    return stepBuilderFactory.get("hellWorldStep")
            .tasklet(hellWorldTasklet())
            .build();
}

@Bean
public Tasklet hellWorldTasklet() {
    return new Tasklet() {
        @Override
        public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
            System.out.println(" hello world spring batch");
            return RepeatStatus.FINISHED;
        }
    };
}



@Bean
public Step hellWorldStep2() {
    return stepBuilderFactory.get("hellWorldStep2")
            .tasklet(hellWorldTasklet2())
            .build();
}


@Bean
public Tasklet hellWorldTasklet2() {
    return new Tasklet() {
        @Override
        public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
            JobExecution jobExecution = stepContribution.getStepExecution().getJobExecution();
            // STARTED
            System.out.println(jobExecution.getStatus());
            return RepeatStatus.FINISHED;
        }
    };
}

在这里插入图片描述

三:流式步骤 Flow

流式步骤是一系列有序子步骤的集合,将一个大的步骤拆分成多个有序子步骤。执行顺序:

  1. Step1: tasklet1
  2. Step2: Flow
    • 2.1 Step21:tasklet21
    • 2.2 Step22:tasklet22
    • 2.3 Step23:tasklet23
  3. Step3: tasklet3
@Configuration
public class HelloWorldFlowJobConfig {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;


    @Bean
    public Job flowStepJob() {
        return jobBuilderFactory.get("flowStepJob")
                .start(step1())
                .next(step2())
                .next(step3())
                .build();
    }

    @Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
                .tasklet(tasklet1())
                .build();
    }

    @Bean
    public Step step2() {
    	// 将Flow包装成Step
        return stepBuilderFactory.get("step2")
                .flow(flow2())
                .build();
    }

    @Bean
    public Flow flow2() {
        return new FlowBuilder<Flow>("flow2")
                .start(step21())
                .next(step22())
                .next(step23())
                .build();
    }

    @Bean
    public Step step21() {
        return stepBuilderFactory.get("step21")
                .tasklet(tasklet21())
                .build();
    }
    @Bean
    public Step step22() {
        return stepBuilderFactory.get("step22")
                .tasklet(tasklet22())
                .build();
    }
    @Bean
    public Step step23() {
        return stepBuilderFactory.get("step23")
                .tasklet(tasklet23())
                .build();
    }

    @Bean
    public Step step3() {
        return stepBuilderFactory.get("step3")
                .tasklet(tasklet3())
                .build();
    }


    @Bean
    public Tasklet tasklet1() {
        return new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("tasklet1");
                return RepeatStatus.FINISHED;
            }
        };
    }

    @Bean
    public Tasklet tasklet21() {
        return new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("tasklet21");
                return RepeatStatus.FINISHED;
            }
        };
    }

    @Bean
    public Tasklet tasklet22() {
        return new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("tasklet22");
                return RepeatStatus.FINISHED;
            }
        };
    }

    @Bean
    public Tasklet tasklet23() {
        return new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("tasklet23");
                return RepeatStatus.FINISHED;
            }
        };
    }


    @Bean
    public Tasklet tasklet3() {
        return new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("tasklet3");
                return RepeatStatus.FINISHED;
            }
        };
    }
}

在这里插入图片描述

四:步骤并行执行

默认步骤之间是使用同一个线程串行执行的,先执行第一个步骤,第一个步骤执行完后再执行第二个步骤,第二个步骤执行完后再执行第三个步骤。通过 split(TaskExecutor executor) 可以将步骤放在不同的线程中并行执行。并行执行哪个步骤先执行是不确定的。

@Bean
public Job helloWorldJob() {
    return jobBuilderFactory.get("helloWorldJob")
            .start(hellWorldStep())
            .incrementer(new RunIdIncrementer())
            .split(new SimpleAsyncTaskExecutor())
            .add(hellWorldFlow())
            .end()
            .build();
}

@Bean
public Step hellWorldStep() {
    return stepBuilderFactory.get("hellWorldStep")
            .tasklet(hellWorldTasklet())
            .build();
}

@Bean
public Step hellWorldStep2() {
    return stepBuilderFactory.get("hellWorldStep2")
            .tasklet(hellWorldTasklet2())
            .build();
}

@Bean
public Flow hellWorldFlow() {
    return new FlowBuilder<Flow>("hellWorldFlow")
            .start(hellWorldStep2())
            .build();
}

@Bean
public Tasklet hellWorldTasklet() {
    return new Tasklet() {
        @Override
        public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
            System.out.println(Thread.currentThread().getName() + " hellWorldTasklet");
            return RepeatStatus.FINISHED;
        }
    };
}

@Bean
public Tasklet hellWorldTasklet2() {
    return new Tasklet() {
        @Override
        public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
            System.out.println(Thread.currentThread().getName() + " hellWorldTasklet2");
            return RepeatStatus.FINISHED;
        }
    };
}

并行执行,Step2比Step1先执行了。
在这里插入图片描述

五:作业执行监听器 JobExecutionListener

作业执行监听器用于作业开始前执行某些操作,作业结束时执行某些操作。

方式一:实现接口 JobExecutionListener

public class HelloWorldJobListener implements JobExecutionListener {
    @Override
    public void beforeJob(JobExecution jobExecution) {
        jobExecution.getExecutionContext().put("begin", System.currentTimeMillis());
        // Status=STARTED
        System.err.println("beforeJob " + jobExecution.getStatus());
    }

    @Override
    public void afterJob(JobExecution jobExecution) {
        long begin = jobExecution.getExecutionContext().getLong("begin");
        long total = System.currentTimeMillis() - begin;
        // Status=COMPLETED
        System.err.println("afterJob " + jobExecution.getStatus() + " total: "+ total);
    }
}

方式二:注解 @BeforeJob + @AfterJob

public class HelloWorldJobAnnationListener {
    @BeforeJob
    public void beforeJob(JobExecution jobExecution) {
        jobExecution.getExecutionContext().put("begin", System.currentTimeMillis());
        // Status=STARTED
        System.err.println("beforeJob " + jobExecution.getStatus());
    }

    @AfterJob
    public void afterJob(JobExecution jobExecution) {
        long begin = jobExecution.getExecutionContext().getLong("begin");
        long total = System.currentTimeMillis() - begin;
        // Status=COMPLETED
        System.err.println("afterJob " + jobExecution.getStatus() + " total: "+ total);
    }
}

@Bean
public Job helloWorldJob() {
    return jobBuilderFactory.get("helloWorldJob")
            .start(hellWorldStep())
            // 配置监听器
            .listener(jobExecutionListener())
            .build();
}

@Bean
public JobExecutionListener jobExecutionListener() {
    return new HelloWorldJobListener();
}

六:步骤执行监听器

可以通过实现StepExecutionListener接口实现,也可以通过注解方式实现(@BeforeStep、@AfterStep)。

public class HelloWorldStepListener implements StepExecutionListener {
    @Override
    public void beforeStep(StepExecution stepExecution) {
        System.out.println("步骤监听器:步骤执行之前监听," + stepExecution.getStepName());
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        System.out.println("步骤监听器:步骤执行之前监听," + stepExecution.getStepName());
        return stepExecution.getExitStatus();
    }
}
@Bean
public Step helloWorldStep() {
    return stepBuilderFactory.get("helloWorldStep")
            .tasklet(hellWorldTasklet())
            // 配置步骤监听器
            .listener(stepExecutionListener())
            .build();
}

@Bean
public StepExecutionListener stepExecutionListener() {
    return new HelloWorldStepListener();
}

七:Job嵌套

Job之间也可以嵌套,比如一个父Job封装多个已经存在的子Job。

@Configuration
public class ChildrenJobConfig {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;


    @Bean
    public Job childJob1() {
        return jobBuilderFactory.get("childJob1")
                .start(childJob1Step())
                .incrementer(new RunIdIncrementer())
                .build();
    }

    @Bean
    public Step childJob1Step() {
        return stepBuilderFactory.get("childJob1Step")
                .tasklet(childJob1StepTasklet())
                .build();
    }

    @Bean
    public Tasklet childJob1StepTasklet() {
        return new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println(Thread.currentThread().getName() + " childJob1StepTasklet");
                return RepeatStatus.FINISHED;
            }
        };
    }

    @Bean
    public Job childJob2() {
        return jobBuilderFactory.get("childJob2")
                .start(childJob2Step2())
                .incrementer(new RunIdIncrementer())
                .build();
    }

    @Bean
    public Step childJob2Step2() {
        return stepBuilderFactory.get("childJob2Step2")
                .tasklet(childJob2Step2Tasklet2())
                .build();
    }

    @Bean
    public Tasklet childJob2Step2Tasklet2() {
        return new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println(Thread.currentThread().getName() + " childJob2Step2Tasklet2");
                return RepeatStatus.FINISHED;
            }
        };
    }
}
@Configuration
public class ParentJobConfig {
    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private Job childJob1;

    @Autowired
    private Job childJob2;


    @Bean
    public Job parentJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        return jobBuilderFactory.get("parentJob")
                .start(parent1Step(jobRepository, transactionManager))
                .next(parent2Step(jobRepository, transactionManager))
                .incrementer(new RunIdIncrementer())
                .build();

    }

    @Bean
    public Step parent1Step(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        // Job转Step: 将子Job封装成父Step
        return new JobStepBuilder(new StepBuilder("parent1Step"))
                .job(childJob1)
                .launcher(jobLauncher)
                .repository(jobRepository)
                .transactionManager(transactionManager)
                .build();
    }

    @Bean
    public Step parent2Step(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        // Job转Step: 将子Job封装成父Step
        return new JobStepBuilder(new StepBuilder("parent2Step"))
                .job(childJob2)
                .launcher(jobLauncher)
                .repository(jobRepository)
                .transactionManager(transactionManager)
                .build();
    }
}

在这里插入图片描述

八:轻舟已过万重山

在这里插入图片描述

小时候,觉得忘记带作业是天大的事
高中的时候,觉得考不上大学是天大的事
恋爱的时候,觉得和喜欢的 人分开是天大的事
大学毕业时,觉得没有一个稳定的工作是天大的事

但现在回头看看
自己曾经难以跨过的山其实都已经跨过了
曾认为不能接受的,也都渐渐接受了

生活充满了选择
遗憾也不过是常态
失败也是贯穿生活始终的

其实人本身就是无论做什么选择都会后悔
只是总是习惯美化自己当初没有选择的另外一条路
可是大家都心知肚明,就算时间重来一次,以当时的心智和阅历还是会做出同样的选择
那么故事的结局可能就没那么重要了

我想人生就是一场享受过程的修行
与其后悔当初
不如回头看
轻舟已过万重山
向前看
前路漫漫亦灿灿

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/653877.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营第五十九天|503.下一个更大元素II 42. 接雨水

目录 LeeCode 503.下一个更大元素II LeeCode 42. 接雨水 暴力解法 优化双指针法 单调栈法 LeeCode 503.下一个更大元素II 503. 下一个更大元素 II - 力扣&#xff08;LeetCode&#xff09; 【思路】 相较于前两道题目&#xff0c;这道题目将数组改为循环数组&#x…

python获取度娘热搜数据并保存成Excel

python获取百度热搜数据 一、获取目标、准备工作二、开始编码三、总结 一、获取目标、准备工作 1、获取目标&#xff1a; 本次获取教程目标&#xff1a;某度热搜 2、准备工作 环境python3.xrequestspandas requests跟pandas为本次教程所需的库&#xff0c;requests用于模拟h…

在读博士怎么申请公派访学?

作为在读博士生&#xff0c;申请公派访学是一项重要而有益的经历。下面知识人网将为您介绍一些关于如何申请公派访学的步骤和注意事项。 首先&#xff0c;您需要找到一个合适的公派访学机会。可以通过与导师、教授或其他相关人士进行交流来获取相关信息。还可以参考学术会议、研…

【Linux】linux | 服务响应慢、问题排查 | 带宽问题导致

一、说明 1、项目使用云服务器&#xff0c;服务器配置&#xff1a;5M带宽、4核、32G&#xff0c;1T&#xff0c;CentOS7 2、CPU、内存、磁盘IO都没有达到瓶颈&#xff0c;猜测是带宽问题 3、应用比较多&#xff0c;应用中间件&#xff0c;十几个差不多 4、同时在线人数30 5、已…

继承~~~

1&#xff1a;继承概述&#xff0c;使用继承的好处 1&#xff1a;什么是继承&#xff1f; Java中提供一个关键字extends&#xff0c;用这个关键字&#xff0c;我们可以让一个类和另一类建立起父子关系。 public class Student extends People{} Student称为子类&#xff08…

乘势而起:机载航电·显控显示系统仿真

改革开放以来&#xff0c;我国国民经济与科学技术取得了长足的发展&#xff0c;信息化、工业成熟度与自动化程度不断深化&#xff0c;极大地增强了国家的综合实力、在世界范围内显示了大国地位。在当前科技产业的发展和变革的历史性交汇期&#xff0c;“工业4.0”、“中国制造2…

iOS App 上架流程图文教学

在上架App 之前必须先准备好开发者帐号&#xff0c;但申请开发者帐号因法兰克早在之前已经申请好了&#xff0c;故就跳过此步骤&#xff0c;直接从产生凭证到上传App开始讲起。首先&#xff0c;要将自己辛苦写好的App 送审的话&#xff0c;则要依序做完下列几件事情即可。 在开…

NFT Insider #98:The Sandbox与Forkast Labs 达成合作,苹果的混合现实头显将增强游戏和元宇宙

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members(https://twitter.com/WHALEMembers)、BeepCrypto&#xff08;https://twitter.com/beep_crypto&#xff09;联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周…

对称加密DES加密算法原理、用户登录应用案例分享

更多知识 学习&#xff1a;https://www.processon.com/view/60504b5ff346fb348a93b4fa#map 目录&#xff1a; DES算法的工作原理DES算法的优点DES算法的缺点DES算法的应用场景DES算法性能分析用户登录实例总结 1. DES算法的工作原理 DES算法是一种对称加密算法&#xff0c;使…

定向写作模型CTRL,Conditional Transformer Language有条件的文本生成模型

定向写作模型CTRL 介绍 CTRL全称为Conditional Transformer Language有条件的文本生成模型&#xff0c;它始于Salesforce在2019年发布的论文《A Conditional Transformer Language Model for Controllable Generation》&#xff0c;该模型用于定向写作。论文地址如下&#xff…

双功能螯合剂:1777804-45-1,DOTA-(COOt-Bu)3-CH2-Ph-azide,的反应特点及其参数说明

​ 中文名称&#xff1a;1,1-二甲基乙基4-[(4-叠氮苯基)甲基] -7,10-双[2-(1,1-二甲基乙氧基) -2-氧乙基] -1,4,7,10-四氮杂环十二烷 -1-乙酸酯 英文名称&#xff1a;DOTA-(COOt-Bu)3-CH2-Ph-azide&#xff0c;DOTA-(COOt-Bu)3-CH2-Ph-N3 规格标准&#xff1a;1g、5g、10g CAS…

【电源设计】18650电池电源串并联设计——改变电压或容量

有时我们有需要改造电池电源的需要&#xff0c;比如增大容量&#xff0c;增大电压之类的&#xff0c;本文介绍18650锂电池&#xff0c;以及如何用18650锂电池串并联设计电源&#xff0c;达到增大容量或者增大电压的效果&#xff1a; 目录 一、18650锂电池基本知识&#xff1a…

腾讯的基础认证适合没经验、没专业知识的人吗?

IT行业可以说是现在最热门的行业之一了&#xff0c;很多人都会选择报考这个专业&#xff0c;同时还有很多没有基础的人&#xff0c;也会选择在毕业后继续教育&#xff0c;从而获得进入这一行的机会&#xff0c;可以说每个人都在内卷&#xff0c;技术和证书都需要拥有&#xff0…

这就是实力!京东资深架构师用实例详解Java虚拟机(源码剖析)

前言 Java是一门流行多年的高级编程语言&#xff0c;与其相关的就业岗位很多&#xff0c;但是最近几年却出现了用人单位招不到合适的人&#xff0c;而大量Java程序员找不到工作的尴尬局面。究其根本原因是岗位对Java开发技术的要求高&#xff0c;不但要会应用&#xff0c;而且…

祛除红眼算法python实现

最近研究了一下祛除红眼的算法&#xff0c;主要的思想都是将RGB通道里面的R通道给想法设法的降低&#xff0c;其他的通道稍微进行变换就行&#xff0c;这里使用python运行了一下例子看看&#xff0c; version2参考了代码&#xff1a;https://www.cnblogs.com/cpuimage/p/90002…

华为IP-san实验搭建

文章目录 RedHat or CentOS系统1、获得多路径软件2、配置主机iscsi名3、配置存储映射4、主机访问存储的LUN5、安装多路径解决重复磁盘问题6、使用多路径扫盘 windows系统1、为win虚拟机提供多路径包文件2、创建存储与主机的连接3、主机使用磁盘 RedHat or CentOS系统 1、获得多…

为什么 kubernetes 环境要求开启 bridge-nf-call-iptables ?

文章目录 背景基于网桥的容器网络Service 同节点通信问题开启 bridge-nf-call-iptables我的环境netshoot 工具 参考 背景 Kubernetes 环境中&#xff0c;很多时候都要求节点内核参数开启 bridge-nf-call-iptables: sysctl -w net.bridge.bridge-nf-call-iptables1 参考官方文…

SQL语句的一些高级用法1

这里写目录标题 SQL语句的一些高级用法11.修改表名和表结构1&#xff0e;修改表名 2.扩展表结构&#xff08;增加字段&#xff09;3.修改字段&#xff08;列&#xff09;名&#xff0c;添加唯一键4&#xff0e;删除字段 案例扩展数据表高级操作1.克隆表&#xff0c;将数据表的数…

【Spring Boot学习】Spring Boot的创建和使用

前言&#xff1a; &#x1f49e;&#x1f49e;今天我们开始学习Spring Boot&#xff0c;这里我们会学习到怎么去创建和使用Spring Boot&#xff0c;在这里我们会了解到什么是最为核心的框架之一。 &#x1f49e;&#x1f49e;前路漫漫&#xff0c;希望大家坚持下去&#xff0c;…

大模型 Transformer介绍-Part1

众所周知&#xff0c;transformer 架构是自然语言处理 (NLP) 领域的一项突破。它克服了 seq-to-seq 模型&#xff08;如 RNN 等&#xff09;无法捕获文本中的长期依赖性的局限性。事实证明&#xff0c;transformer 架构是 BERT、GPT 和 T5 及其变体等革命性架构的基石。正如许多…