1. 程式人生 > >SpringBoot實戰筆記:28_Spring Batch

SpringBoot實戰筆記:28_Spring Batch

28_Spring Batch

什麼是Spring Batch
Spring Batch 是用來處理大量資料操作的一個框架,主要用來讀取大量資料,然後進行一定處理後輸出指定的形式。

Spring Batch 主要組成

名稱 用途
JobRepository 用來註冊Job的容器
JobLauncher 用來啟動Job的介面
Job 我們要實際執行的任務,包含一個或多個Step
Step Step-步驟,包含ItemReader,ItemProcessor,ItemWriter
ItemReader 用來讀取資料的介面
ItemProcessor 用來處理資料的介面
ItemWriter 用來輸出資料的介面

1,Spring Boot 的支援

Spring BootSpring Batch 提供了自動配置,為我們自動初始化了 Spring Batch 儲存批處理記錄的資料庫,且當我們程式啟動時,會自動執行我們定義的 Job 的Bean

相關配置

#啟動時要執行的job,預設會執行全部job
spring.batch.job.names=job1,job2

#是否自動執行job,預設為是
spring.batch.job.enabled=true

#是否初始化Spring Batch 的資料庫,預設為是
spring.batch.initializer.enabled=true #設定資料庫 #spring.batch.schema= #設定 Spring Batch 資料庫表的字首 #spring.batch.table-prefix=

2,新建Spring Boot專案

依賴:JDBC,Batch,Web,Oracle驅動,hibernate-validator(資料校驗)
**注:**Spring Batch 會自動載入 hsqldb 驅動,要去除

<dependency>
  <groupId>org.springframework.boot</groupId
>
<artifactId>spring-boot-starter-batch</artifactId> <exclusions> <exclusion> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version>11.2.0.2.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> </dependency>

3,準備用來測試的csv資料位於 src/main/resources/people.csv


4,資料表定義,位於 src/main/resources/schema.sql

5,資料來源配置

spring.datasource.username=root
spring.datasource.password=123
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jackson.serialization.indent-output=true

6,Person類

package com.zyf.domain;

import javax.validation.constraints.Size;

/**
 * Created by zyf on 2018/3/15.
 */
public class Person {

    /**
     * 使用JSR-303校驗資料
     */
    @Size(max = 4,min = 2)
    private String name;
    private int age;
    private String nation;
    private String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getNation() {
        return nation;
    }

    public void setNation(String nation) {
        this.nation = nation;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

7,資料處理及校驗

處理

package com.zyf.batch;

import com.zyf.domain.Person;
import org.springframework.batch.item.validator.ValidatingItemProcessor;
import org.springframework.batch.item.validator.ValidationException;

/**
 * Created by zyf on 2018/3/15.
 */
public class CsvItemProcessor extends ValidatingItemProcessor<Person> {

    @Override
    public Person process(Person item) throws ValidationException {
        //呼叫自定義的校驗器
        super.process(item);

        //處理資料
        if(item.getNation().equals("蜀國")){
            item.setNation("01");
        }else {
            item.setNation("02");
        }

        return item;
    }
}

校驗

package com.zyf.batch;

import org.springframework.batch.item.validator.ValidationException;
import org.springframework.batch.item.validator.Validator;
import org.springframework.beans.factory.InitializingBean;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import java.util.Set;


/**
 * Created by zyf on 2018/3/15.
 */
public class CsvBeanValidator<T> implements Validator<T>,InitializingBean {

    private javax.validation.Validator validator;


    @Override
    public void validate(T t) throws ValidationException {
        //校驗資料,得到驗證不通過的約束
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);
        if(constraintViolations.size() > 0){
            StringBuilder message = new StringBuilder();
            for (ConstraintViolation<T> constraintViolation : constraintViolations) {
                message.append(constraintViolation.getMessage()+"\n");
            }
            throw new ValidationException(message.toString());
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //使用JSR-303 的 Validator 來校驗我們的資料
        //此處初始化JSR-303 的 Validator
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();

        validator = validatorFactory.usingContext().getValidator();
    }

}

8,Job監聽

package com.zyf.batch;

import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;

/**
 * Created by zyf on 2018/3/15.
 */
public class CsvJobListener implements JobExecutionListener {

    long startTime;
    long endTime;


    @Override
    public void beforeJob(JobExecution jobExecution) {
        startTime = System.currentTimeMillis();
        System.out.println("任務開始");
    }

    @Override
    public void afterJob(JobExecution jobExecution) {
        endTime = System.currentTimeMillis();
        System.out.println("任務結束");

        System.out.println("耗時:"+(endTime - startTime) + "ms");
    }
}

9,配置

package com.zyf.batch;

import com.zyf.domain.Person;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.item.validator.Validator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

/**
 * Created by zyf on 2018/3/15.
 */
@Configuration
@EnableBatchProcessing//開啟批處理的支援
public class CsvBatchConfig {
    @Bean
    public ItemReader<Person> reader(){
        //使用FlatFileItemReader讀取檔案
        FlatFileItemReader<Person> reader = new FlatFileItemReader<>();
        //設定目標檔案的路徑,通過ClassPathResource找到類路徑
        reader.setResource(new ClassPathResource("p.csv"));
        //將檔案中的資料與Person類中的屬性一一對映
        reader.setLineMapper(new DefaultLineMapper<Person>(){
            //程式碼塊
            {
                setLineTokenizer(new DelimitedLineTokenizer(){
                    //程式碼塊
                    {
                        setNames(new String[]{"name","age","nation","address"});
                    }
                });

                setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>(){
                    {
                        setTargetType(Person.class);
                    }
                });
            }
        });
        return reader;
    }

    @Bean
    public ItemProcessor<Person,Person> processor(){

        //使用我們自定義的CsvItemProcessor
        CsvItemProcessor processor = new CsvItemProcessor();
        //為處理器指定校驗器
        processor.setValidator(csvBeanValidator());
        return processor;

    }

    /**
     *
     * @param dataSource spring boot 已經為我們定義了 DataSource,Spring能讓容器中已有的Bean,以引數的形式注入
     * @return
     */
    @Bean
    public ItemWriter<Person> writer(DataSource dataSource){
        //使用jdbc批處理的JdbcBatchItemWriter將資料寫入到資料庫
        JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<>();
        writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>());
        String sql = "insert into PERSON (id,name,age,nation,address) values(PERSON_BATCH.nextval, :name, :age, :nation, :address)";
        //設定要執行批處理的SQL語句
        writer.setSql(sql);
        //配置資料來源
        writer.setDataSource(dataSource);
        return writer;
    }

    /**
     *
     * @param dataSource 自動注入
     * @param transactionManager 自動注入
     * @return
     * @throws Exception
     */
    @Bean
    public JobRepository jobRepository(DataSource dataSource, PlatformTransactionManager transactionManager) throws Exception {
        JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
        jobRepositoryFactoryBean.setDataSource(dataSource);
        jobRepositoryFactoryBean.setTransactionManager(transactionManager);
        jobRepositoryFactoryBean.setDatabaseType("oracle");
        return jobRepositoryFactoryBean.getObject();

    }

    @Bean
    public SimpleJobLauncher jobLauncher(DataSource dataSource,PlatformTransactionManager transactionManager) throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository(dataSource,transactionManager));
        return jobLauncher;
    }

    @Bean
    public Job importJob(JobBuilderFactory jobs,Step s1){
        return jobs.get("importJob")
                .incrementer(new RunIdIncrementer())
                .flow(s1)//為job指定step(要執行什麼)
                .end()
                .listener(csvJobListener())//繫結監聽器
                .build();
    }

    /**
     *
     * @param stepBuilderFactory
     * @param reader
     * @param writer
     * @param processor
     * @return
     */
    @Bean
    public Step step1(StepBuilderFactory stepBuilderFactory,ItemReader<Person> reader,ItemWriter<Person> writer,ItemProcessor<Person,Person> processor){
        return stepBuilderFactory.get("step1")
                .<Person,Person>chunk(65000)//批處理每次提交65000條資料
                .reader(reader)//給step繫結reader
                .processor(processor)//給step繫結processor
                .writer(writer)//給step繫結writer
                .build();

    }

    @Bean
    public CsvJobListener csvJobListener(){
        return new CsvJobListener();
    }

    @Bean
    public Validator<Person> csvBeanValidator(){
        return new CsvBeanValidator<Person>();
    }
}

10,執行測試


11,通過訪問某路徑,執行job

新的配置
別忘了吧CsvBatchConfig類的@Configuration註釋掉

package com.zyf.batch;

import com.zyf.domain.Person;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.item.validator.Validator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

/**
 * Created by zyf on 2018/3/15.
 */
@Configuration
@EnableBatchProcessing
public class TriggerBatchConfig {
    @Bean
    @StepScope
    public FlatFileItemReader<Person> reader(@Value("#{jobParameters['input.file.name']}") String pathToFile){
        //使用FlatFileItemReader讀取檔案
        FlatFileItemReader<Person> reader = new FlatFileItemReader<>();
        //設定目標檔案的路徑,通過ClassPathResource找到類路徑
        reader.setResource(new ClassPathResource(pathToFile));
        //將檔案中的資料與Person類中的屬性一一對映
        reader.setLineMapper(new DefaultLineMapper<Person>(){
            //程式碼塊
            {
                setLineTokenizer(new DelimitedLineTokenizer(){
                    //程式碼塊
                    {
                        setNames(new String[]{"name","age","nation","address"});
                    }
                });

                setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>(){
                    {
                        setTargetType(Person.class);
                    }
                });
            }
        });
        return reader;
    }

    @Bean
    public ItemProcessor<Person,Person> processor(){

        //使用我們自定義的CsvItemProcessor
        CsvItemProcessor processor = new CsvItemProcessor();
        //為處理器指定校驗器
        processor.setValidator(csvBeanValidator());
        return processor;

    }

    /**
     *
     * @param dataSource spring boot 已經為我們定義了 DataSource,Spring能讓容器中已有的Bean,以引數的形式注入
     * @return
     */
    @Bean
    public ItemWriter<Person> writer(DataSource dataSource){
        //使用jdbc批處理的JdbcBatchItemWriter將資料寫入到資料庫
        JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<>();
        writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>());
        String sql = "insert into PERSON (id,name,age,nation,address) values(PERSON_BATCH.nextval, :name, :age, :nation, :address)";
        //設定要執行批處理的SQL語句
        writer.setSql(sql);
        //配置資料來源
        writer.setDataSource(dataSource);
        return writer;
    }

    /**
     *
     * @param dataSource 自動注入
     * @param transactionManager 自動注入
     * @return
     * @throws Exception
     */
    @Bean
    public JobRepository jobRepository(DataSource dataSource, PlatformTransactionManager transactionManager) throws Exception {
        JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
        jobRepositoryFactoryBean.setDataSource(dataSource);
        jobRepositoryFactoryBean.setTransactionManager(transactionManager);
        jobRepositoryFactoryBean.setDatabaseType("oracle");
        return jobRepositoryFactoryBean.getObject();

    }

    @Bean
    public SimpleJobLauncher jobLauncher(DataSource dataSource, PlatformTransactionManager transactionManager) throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository(dataSource,transactionManager));
        return jobLauncher;
    }

    @Bean
    public Job importJob(JobBuilderFactory jobs, Step s1){
        return jobs.get("importJob")
                .incrementer(new RunIdIncrementer())
                .flow(s1)//為job指定step(要執行什麼)
                .end()
                .listener(csvJobListener())//繫結監聽器
                .build();
    }

    /**
     *
     * @param stepBuilderFactory
     * @param reader
     * @param writer
     * @param processor
     * @return
     */
    @Bean
    public Step step1(StepBuilderFactory stepBuilderFactory, ItemReader<Person> reader, ItemWriter<Person> writer, ItemProcessor<Person,Person> processor){
        return stepBuilderFactory.get("step1")
                .<Person,Person>chunk(65000)//批處理每次提交65000條資料
                .reader(reader)//給step繫結reader
                .processor(processor)//給step繫結processor
                .writer(writer)//給step繫結writer
                .build();

    }

    @Bean
    public CsvJobListener csvJobListener(){
        return new CsvJobListener();
    }

    @Bean
    public Validator<Person> csvBeanValidator(){
        return new CsvBeanValidator<Person>();
    }

}

12,建立Controller

package com.zyf.web.controller;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by zyf on 2018/3/15.
 */
@RestController
public class DemoController {

    @Autowired
    JobLauncher jobLauncher;

    @Autowired
    Job importJob;

    JobParameters jobParameters;

    @RequestMapping("/imp")
    public String imp(String fileName) throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
        String path = fileName +".csv";
        jobParameters = new JobParametersBuilder().addLong("time",System.currentTimeMillis())
                .addString("input.file.name",path)
                .toJobParameters();
        jobLauncher.run(importJob,jobParameters);
        return "ok";
    }
}

13,更改自動執行job的配置

14,訪問 /imp?fileName=p

相關推薦

SpringBoot實戰筆記28_Spring Batch

28_Spring Batch 什麼是Spring Batch Spring Batch 是用來處理大量資料操作的一個框架,主要用來讀取大量資料,然後進行一定處理後輸出指定的形式。 Spring Batch 主要組成 名稱 用途

SpringBoot實戰筆記03_Spring常用配置

Spring常用配置 1,Bean的Scope //預設是Singleton,相當於@Scope("singleton"),單例 @Service public class DefaultScopeService{ } @Service @Scop

SpringBoot實戰筆記15_SpringBoot 自定義starter pom

15_SpringBoot 自定義starter pom 我們在 pom.xml 中的那些springboot依賴,就是starter 目的:當某個類存在的時候,自動配置這個類的Bean,並可將Bean的書寫在 application.properties

SpringBoot實戰筆記24_Spring Boot 的事務支援

24_Spring Boot 的事務支援 所有的資料訪問技術都有事務處理機制,這些技術提供了API用來開啟事務,提交事務來完成資料操作,或者在發生錯誤的時候回滾資料。 Spring 的事務機制是用統一的機制來處理不同的資料訪問技術的事務處理。 Spring

SpringBoot實戰筆記02_使用註解與Java配置的Aop示例

使用註解與Java配置的Aop示例 0,新增所需依賴 <!--02_新的依賴--> <!--匯入spring的aop支援--> <dependency>

Spring實戰筆記Spring核心(一)

spring bean spring core一.簡介: 1.依賴註入(DI) 優點:解耦 Spring 通過應用上下文(Application Context)裝載bean的定義,並把它們組裝起來。 Spring應用上下文負責對象的創建和組裝。 ClassPathXm

Spring實戰筆記Web中的Spring

web spring一.構建Spring Web應用1.Spring MVC中用戶請求處理 上圖展示了請求使用Spring MVC所經歷的所有站點。 1:在請求離開瀏覽器時,會帶有所有請求內容的信息,至少會包含請求的URL。 請求通過Spring的DispatcherServlet前

Spring實戰筆記Spring集成

Spring RPC REST 消息 一.使用遠程服務 遠程調用是客戶端應用和服務端之間的會話。 1.Spring通過多種遠程調用技術支持RPC(remote procedure call,遠程過程調用)RPC模型使用場景RMI不考慮網絡限制時(例如防火墻),訪問/發布基於Java

Spring實戰筆記後端中的Spring

spring 數據庫 緩存 安全 一.使用對象-關系映射持久化數據 對象/關系映射(object-relational mapping,ORM)。 在持久層使用ORM工具可以節省術前行代碼和大量開發時間。 Spring對ORM框架的支持提供了與這些框架的集成點以及一些附加的服

springboot學習筆記01Building a RESTful Web Service

我學習的時候使用eclipse Jee 作為開發工具。另外再推薦idea community版本。 學習資料地址 我使用的是maven構建專案方式 按照文章裡介紹的,依次修改活新建: pom.xml src/main/java/hello/Greeting.ja

實戰筆記Jenkins打造強大的前端自動化工作流

背景 公司的前端構建及部署工作都是人工去做,隨著業務擴大,專案迭代速度變快,人員增多,各種問題都暴露出來,本文是對前端自動化工作流進行探索後的一篇經驗分享,將通過一個簡單案例分享一下基於Jenkins的前端自動化工作流搭建的過程,搭建完這套工作流,我們只需要在本地發起一個g

【JAVAWEB學習筆記】網上商城實戰4訂單模塊

接收 筆記 網上商城 詳情 src head 分頁查詢 cnblogs logs 今日任務 完成訂單模塊的功能 1.1 訂單 模塊的功能 1.1.1 我的訂單: 【我的訂單的查詢】 * 在header.jsp中點擊我的訂單. * 提交到Servlet:

【JAVAWEB學習筆記】網上商城實戰5後臺的功能模塊

form 所有 實現 返回 .com 訂單管理 模塊 集合 後臺 今日任務 完成後臺的功能模塊 1.1 網上商城的後臺功能的實現: 1.1.1 後臺的功能的需求: 1.1.1.1 分類管理: 【查詢所有分類】 * 在左側菜單

SpringBoot學習筆記(5)處理前端JSON返回的日期的格式

處理 date() ring row 學習筆記 post 直觀 val rtt SpringBoot學習筆記(4):處理前端JSON返回的日期的格式 問題描述   前端頁面顯示的時間為毫秒格式,不利於直觀顯示! 解決方法1——後端解決 public class Flow

SpringBoot學習筆記(1)配置Mybatis

target oca run class .com gpo connect auto users SpringBoot學習筆記(1):配置Mybatis 參考資料:   1.AndyLizh的博客   2.xiaolyuh123的博客 快速開始 添加Mybatis依賴(

SpringBoot學習筆記(10)使用MongoDB來訪問數據

and exclude 包含 思維導圖 .org args 表示 告訴 http SpringBoot學習筆記(10):使用MongoDB來訪問數據 快速開始   本指南將引導您完成使用Spring Data MongoDB構建應用程序的過程,該應用程序將數據存儲在Mong

SpringBoot學習筆記(11)使用WebSocket構建交互式Web應用程序

-- 文件 基於 ping pan lan tin eas return SpringBoot學習筆記(11):使用WebSocket構建交互式Web應用程序 快速開始   本指南將引導您完成創建“hello world”應用程序的過程,該應用程序在瀏覽器和服務器之間來回發

SpringBoot學習筆記(12)計劃任務

當前 frame mode oot odin 構建java項目 ati pre string SpringBoot學習筆記(12):計劃任務 快速開始   本指南將指導您完成使用Spring安排任務的步驟。 參考教程: https://spring.io/guides/g

SpringBoot學習筆記(13)日誌框架

配置 沒有 alt clas load dep 技術 bubuko col SpringBoot學習筆記(13):日誌框架——SL4J 快速開始 說明   SpringBoot底層選用SLF4J和LogBack日誌框架。    SLF4J的使用 SpringBoot的底層依

20180813視頻筆記 深度學習基礎上篇(1)之必備基礎知識點 深度學習基礎上篇(2)神經網絡模型視頻筆記深度學習基礎上篇(3)神經網絡案例實戰 和 深度學習基礎下篇

計算 概念 人臉識別 大量 png 技巧 表現 lex github 深度學習基礎上篇(3)神經網絡案例實戰 https://www.bilibili.com/video/av27935126/?p=1 第一課:開發環境的配置 Anaconda的安裝 庫的安裝 Windo