【菜鸟读源码】halo✍源码学习(一)

       Halo是一款现代化的我的独立博客系统,给习惯写博客的同窗一个更好的选择。听说这是一个较容易读懂的Spring-Boot项目,那我就但愿经过这个项目学习前辈的经验。java

       若有帮助,不胜荣幸。若有错误,欢迎指正!web

前言

       最先看到这个博客的源码的时候是经过B站up主-CodeSheep的一个视频:Java企业级开源项目推荐,帮助你们从学习走向实践,奈何当时本身知识有限,没有仔细的阅读源码。近日Halo也推出了正式版,我也就抱着学习的心态拜读一下。spring

       首先打开工程,看到整个工程有如下两个明显的变化:api

  • 配置文件由properties变为yaml

       能够明显的看到,在处理层级关系的时候,properties须要使用大量的路径来描述层级(或者属性),好比environments.dev.url和environments.dev.name。其次,对于较为复杂的结构,好比数组(my.servers),写起来更为复杂。而对应的YAML格式文件就简单不少:数组

  • 构建工具由meavn变为gradle

       由于此前有过Android的开发经验,因此这一改变对个人影响并不大😄。gradle逐渐替代meavn应该是目前的趋势,可是目前大部分教学和企业采用的仍是以meavn为主,因此此前我也不曾尝试过采用gradle构建项目。由此看出Halo仍是很Fashion的👍。tomcat

Application

       首先打开Application.java文件,看看有什么学习的地方🤤。服务器

@SpringBootApplication
@EnableJpaAuditing
@EnableScheduling
@EnableAsync
@EnableJpaRepositories(basePackages = "run.halo.app.repository", repositoryBaseClass = BaseRepositoryImpl.class)
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        // Customize the spring config location
        System.setProperty("spring.config.additional-location", "file:${user.home}/.halo/,file:${user.home}/halo-dev/");

        // Run application
        SpringApplication.run(Application.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        System.setProperty("spring.config.additional-location", "file:${user.home}/.halo/,file:${user.home}/halo-dev/");
        return application.sources(Application.class);
    }
}

       发现与我以前Spring-Boot开发两点不同的地方:架构

       其一:继承SpringBootServletInitializer从而实现configure方法app

       可能找答案的姿式不对,只零星找到下面几点描述:ide

       一、启动类继承SpringBootServletInitializer类,重写 configure(SpringApplicationBuilder builder`)方法

       二、由于想要用web容器启动项目

       三、使用外部 servlet 容器

结论:为了Undertow容器!

       缘由:

一、排除内置的tomcat容器-build.gradle

exclude module: 'spring-boot-starter-tomcat'

二、添加Undertow依赖-build.gradle

implementation 'org.springframework.boot:spring-boot-starter-undertow'

三、配置服务器

server:
  port: 8090
  use-forward-headers: true
  undertow:
    io-threads: 2
    worker-threads: 36
    buffer-size: 1024
    directBuffers: true

       结合此前在别人基础上修改的网盘项目获得了相同的印证。

       其二:System.setProperty("spring.config.additional-location", "...");

       开发者给了如下注释:Customize the spring config location(定制spring配置文件的位置)

       存在如下三个疑问:

       一、System.setProperty有何用?

       setProperty (String prop, String value); 一、 设置指定键对值的系统属性,其中prop:系统属性的名称,value:系统属性的值。注:这里的system,系统指的是 JRE (runtime)system,不是指 OS。 二、System.setProperty至关于一个静态变量,存在内存里面,能够在项目的任何一个地方,经过System.getProperty("变量")来得到

       二、为什么要设定这个变量?

       加载外部配置文件。打包jar运行也不方便修改jar内部数据,经过设置环境变量spring.config.location。由于博客中也有不少配置选项,因此猜测须要从外部读取某些会改变的配置,须要继续阅读源码验证猜测。

       三、${user.home}从何而来?

       如从前所示user.home应该是一个静态变量,尝试打印:

System.out.println(System.getProperty("user.home"));
//打印出:C:\Users\74472 验证猜测成功
变量 含义
java.version Java 运行时环境版本
java.vendor Java 运行时环境供应商
java.vendor.url Java 供应商的 URL
java.home Java 安装目录
java.vm.specification.version Java 虚拟机规范版本
java.vm.specification.vendor Java 虚拟机规范供应商
java.vm.specification.name Java 虚拟机规范名称
java.vm.version Java 虚拟机实现版本
java.vm.vendor Java 虚拟机实现供应商
java.vm.name Java 虚拟机实现名称
java.specification.version Java 运行时环境规范版本
java.specification.vendor Java 运行时环境规范供应商
java.specification.name Java 运行时环境规范名称
java.class.version Java 类格式版本号
java.class.path Java 类路径
java.library.path 加载库时搜索的路径列表
java.io.tmpdir 默认的临时文件路径
java.compiler 要使用的 JIT 编译器的名称
java.ext.dirs 一个或多个扩展目录的路径
os.name 操做系统的名称
os.arch 操做系统的架构
os.version 操做系统的版本
file.separator 文件分隔符(在 UNIX 系统中是“/”)
path.separator 路径分隔符(在 UNIX 系统中是“:”)
line.separator 行分隔符(在 UNIX 系统中是“/n”)
user.name 用户的帐户名称
user.home 用户的主目录
user.dir 用户的当前工做目录

测试运行

       Spring-Boot的项目运行起来仍是比较简单的🤪。页面也很美观👍Halo博客

Controller学习

       Spring-boot的项目一般都是从Controller读起,发现一个共同的特色,就是代码都是相似这样一个结构:

private final PostService postService;

private final OptionService optionService;

... .... // 其余的Service

private final ThemeService themeService;

public ContentIndexController(PostService postService,
                              OptionService optionService,
                              ThemeService themeService) {
    this.postService = postService;
    this.optionService = optionService;
    ... .... // 其余的Service
    this.themeService = themeService;
}

@GetMapping
public String index(Model model) {
    return this.index(model, 1, Sort.by(DESC, "topPriority").and(Sort.by(DESC, "createTime")));
}

 @GetMapping(value = "page/{page}")
public String index(Model model,
                    @PathVariable(value = "page") Integer page,
                    @SortDefault.SortDefaults({
                        @SortDefault(sort = "topPriority", direction = DESC),
                        @SortDefault(sort = "createTime", direction = DESC)
                    }) Sort sort) {
    ...//省略   
}

       学习收获一:使用构造器注入须要用到的Service

       学习收获二:使用多态处理请求

       真正起做用的是后者,前者只是为用户添加了参数后调用后者。

return this.index(model, 1, Sort.by(DESC, "topPriority").and(Sort.by(DESC, "createTime")));

       学习收获三:RESTful的api设计

相关文章
相关标签/搜索