halo开源博客学习

项目目录结构

  • config:代码检查配置文件夹
  • gradle:gradle-wrapper文件夹
  • src/main/java/run/halo/:源代码文件夹
    • app:应用程序文件夹
      • annotation:自定义注解
      • aspect:自定义注解的切面
      • cache:缓存优化
      • config:自定义配置类
      • controller:控制层(连接前端和后端)
      • core:包含模板引擎和xxx
      • event:事务管理
      • exception:异常管理
      • factory:
      • filter:过滤器
      • handler:数据迁移、文件、主题处理器
      • listener:监听器
      • mail:邮件管理
      • model:
      • repository:数据库层(CRUD操作)
      • security:安全层
      • service:业务层(用于处理控制层分发的请求)
      • task:
      • theme:博客主题相关
      • utils:工具类
    • resource:资源文件夹

gradle

gradle文件夹

Gradle-Wrapper是什么?

​ Halo官方推荐使用Gradle-Wrapper,这是个什么东西呢?

​ Gradle-Wrapper译为Gradle包装器,由于每个人在开发时都会在电脑安装Gradle,这就会存在Gradle环境与版本的差异。为了解决这个问题,Gradle提供了一个解决方案,那就是Gradle Wrapper,它是一个脚本,可以在计算机没有安装Gradle的情况下运行Gradle构建,并且能够指定Gradle的版本,开发人员可以快速启动并运行Gradle项目,而不必手动安装,这样就标准化了项目,从而提高了开发效率。

​ 项目根目录下的Gradle文件如下:

├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat

​ 每个文件的含义如下:

  • gradle-wrapper.jar :包含Gradle运行时的逻辑代码。
  • gradle-wrapper.properties :负责配置包装器运行时行为的属性文件,用来配置使用哪个版本的Gradle等属性。
  • gradlew:Linux平台下,用于执行Gralde命令的包装器脚本。
  • gradlew.bat:Windows平台下,用于执行Gralde命令的包装器脚本。

配置Gradle Wrapper

​ gradle-wrapper.properties用来配置使用哪个版本的Gradle等属性,Halo中使用的gradle-wrapper.properties如下所示:

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

​ 各个字段的含义如下:

  • distributionBase:Gradle解包后存储的主目录。
  • distributionPath:distributionBase指定目录的子目录。distributionBase+distributionPath就是Gradle解包后的存放位置。
  • distributionUrl:Gradle发行版压缩包的下载地址。
  • zipStoreBase:Gradle压缩包存储主目录。
  • zipStorePath:zipStoreBase指定目录的子目录。zipStoreBase+zipStorePath就是Gradle压缩包的存放位置。

build.gradle

​ build.gradle类似于maven中的pom.xml都是用来对项目进行最基本的管理。

​ 下面我们对build.gradle中每一个字段进行解释:

  • //plugins{}:这种方式引入的插件来自Gradle官方插件库
    plugins {
        id "org.springframework.boot" version "2.5.1"
        id "io.spring.dependency-management" version "1.0.11.RELEASE"
        id "checkstyle"
        id "java"
    }
    
  • //使用依赖的项目所在的组
    group = "run.halo.app"
    //项目描述
    description = "Halo, An excellent open source blog publishing application."
    //指定编译.java文件的jdk版本
    sourceCompatibility = JavaVersion.VERSION_11
    
  • //配置代码质量检查
    checkstyle {
        toolVersion = "8.39"
        showViolations = false
        ignoreFailures = false
    }
    
  • //这里类似maven的仓库
    repositories {
        //使用本地仓库http://central.maven.org/作为maven仓库的路径
        mavenLocal()
        //使用中央仓库
        mavenCentral()
        //使用远程仓库URL
        maven { url 'https://repo.spring.io/milestone' }
        //jcenter是一个由 bintray.com维护的Maven仓库 
        jcenter()
    }
    
  • /**
     * Gradle将对依赖进行分组,比如编译Java时使用的是这组依赖,运行Java时又可以使用另一组依赖。
     * 每一组依赖称为一个Configuration,在声明依赖时,我们实际上是在设置不同的Configuration。
     */
    configurations {
        //implementation和api是取代之前的compile的,其中api和compile是一样的效果,implementation有所不同,通过implementation依赖的库只能自己库本身访问,举个例子,A依赖B,B依赖C,如果B依赖C是使用的implementation依赖,那么在A中是访问不到C中的方法的,如果需要访问,请使用api依赖
        implementation {
            exclude module: "spring-boot-starter-tomcat"
            exclude module: "slf4j-log4j12"
            exclude module: 'junit'
        }
        //compile only和provided效果是一样的,只在编译的时候有效, 不参与打包
        compileOnly {
            //依赖于annotationProcessor
            extendsFrom annotationProcessor
        }
    }
    
  • //打包
    bootJar {
        //指定依赖包的名称和版本
        manifest {
            attributes "Implementation-Title": "Halo Application",
                    "Implementation-Version": archiveVersion
        }
    }
    
  • //创建docker镜像
    bootBuildImage.doFirst {
        // check data
        assert System.getenv("DOCKER_USERNAME") != null
        assert System.getenv("DOCKER_TOKEN") != null
    }
    bootBuildImage {
        // prepare data
        def tagLatest = Boolean.valueOf(System.getenv("TAG_LATEST"))
        def dockerImageName = System.getenv("DOCKER_IMAGE_NAME")
        def dockerUsername = System.getenv("DOCKER_USERNAME")
        def dockerToken = System.getenv("DOCKER_TOKEN")
    
        if (dockerImageName == null) {
            dockerImageName = "${dockerUsername}/halo"
        }
        if (!tagLatest) {
            dockerImageName = "${dockerImageName}:${project.version}"
        }
    
        // config plugin
        imageName = "${dockerImageName}"
        docker {
            publishRegistry {
                username = "${dockerUsername}"
                password = "${dockerToken}"
                email = "hi@halo.run"
            }
        }
    }
    
  • //本质上是一个map,一般用来做版本管理
    ext {
        guavaVersion= "31.0-jre"
        upyunSdkVersion = "4.2.0"
        qiniuSdkVersion = "7.2.29"
        aliyunSdkVersion = "3.11.3"
        baiduSdkVersion = "0.10.36"
        qcloudSdkVersion = "5.6.25"
        minioSdkVersion = "7.1.4"
        swaggerVersion = "3.0.0"
        commonsFileUploadVersion = "1.4"
        commonsLangVersion = "3.10"
        httpclientVersion = "4.5.12"
        dataformatYamlVersion = "2.11.0"
        jgitVersion = "5.9.0.202009080501-r"
        flexmarkVersion = "0.62.2"
        thumbnailatorVersion = "0.4.13"
        image4jVersion = "0.7zensight1"
        flywayVersion = "7.5.1"
        h2Version = "1.4.197"
        levelDbVersion = "0.12"
        annotationsVersion = "3.0.1u2"
        zxingVersion = "3.4.0"
        huaweiObsVersion = "3.19.7"
        templateInheritanceVersion = "0.4.RELEASE"
        jsoupVersion = "1.13.1"
    }
    
  • //添加需要什么依赖
    dependencies {
        implementation "org.springframework.boot:spring-boot-starter-actuator"
        implementation "org.springframework.boot:spring-boot-starter-data-jpa"
        implementation "org.springframework.boot:spring-boot-starter-web"
        implementation "org.springframework.boot:spring-boot-starter-jetty"
        implementation "org.springframework.boot:spring-boot-starter-freemarker"
        implementation 'org.springframework.boot:spring-boot-starter-validation'
    
        implementation "com.sun.mail:jakarta.mail"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "com.upyun:java-sdk:$upyunSdkVersion"
        implementation "com.qiniu:qiniu-java-sdk:$qiniuSdkVersion"
        implementation "com.aliyun.oss:aliyun-sdk-oss:$aliyunSdkVersion"
        implementation "com.baidubce:bce-java-sdk:$baiduSdkVersion"
        implementation "com.qcloud:cos_api:$qcloudSdkVersion"
        implementation "com.huaweicloud:esdk-obs-java:$huaweiObsVersion"
        implementation "io.minio:minio:$minioSdkVersion"
        implementation "io.springfox:springfox-boot-starter:$swaggerVersion"
        implementation "commons-fileupload:commons-fileupload:$commonsFileUploadVersion"
        implementation "org.apache.commons:commons-lang3:$commonsLangVersion"
        implementation "org.apache.httpcomponents:httpclient:$httpclientVersion"
        implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$dataformatYamlVersion"
        implementation "org.eclipse.jgit:org.eclipse.jgit:$jgitVersion"
        implementation "com.google.code.findbugs:annotations:$annotationsVersion"
    
        implementation "com.vladsch.flexmark:flexmark:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-attributes:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-autolink:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-emoji:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-escaped-character:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-gfm-strikethrough:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-gfm-tasklist:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-ins:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-media-tags:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-tables:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-toc:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-superscript:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-yaml-front-matter:$flexmarkVersion"
        implementation "com.vladsch.flexmark:flexmark-ext-gitlab:$flexmarkVersion"
    
        implementation "kr.pe.kwonnam.freemarker:freemarker-template-inheritance:$templateInheritanceVersion"
        implementation "net.coobird:thumbnailator:$thumbnailatorVersion"
        implementation "net.sf.image4j:image4j:$image4jVersion"
        implementation "org.flywaydb:flyway-core:$flywayVersion"
        implementation "com.google.zxing:core:$zxingVersion"
    
        implementation "org.iq80.leveldb:leveldb:$levelDbVersion"
        runtimeOnly "com.h2database:h2:$h2Version"
        runtimeOnly "mysql:mysql-connector-java"
    
        compileOnly "org.projectlombok:lombok"
        annotationProcessor "org.projectlombok:lombok"
    
        testCompileOnly "org.projectlombok:lombok"
        testAnnotationProcessor "org.projectlombok:lombok"
    
        testImplementation("org.springframework.boot:spring-boot-starter-test") {
            exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
        }
        testImplementation("org.jsoup:jsoup:${jsoupVersion}")
    
        developmentOnly "org.springframework.boot:spring-boot-devtools"
    }
    
  • //测试时的配置
    test {
        useJUnitPlatform()
        testLogging.showStandardStreams = true
    }
    
    task projectVersion {
        description = 'Prints current project version.'
        doLast {
            println project.version
        }
    }