Halo是一款现代化的我的独立博客系统,给习惯写博客的同窗一个更好的选择。听说这是一个较容易读懂的Spring-Boot项目,那我就但愿经过这个项目学习前辈的经验。java
若有帮助,不胜荣幸。若有错误,欢迎指正!web
最先看到这个博客的源码的时候是经过B站up主-CodeSheep的一个视频:Java企业级开源项目推荐,帮助你们从学习走向实践,奈何当时本身知识有限,没有仔细的阅读源码。近日Halo也推出了正式版,我也就抱着学习的心态拜读一下。spring
首先打开工程,看到整个工程有如下两个明显的变化:api
能够明显的看到,在处理层级关系的时候,properties须要使用大量的路径来描述层级(或者属性),好比environments.dev.url和environments.dev.name。其次,对于较为复杂的结构,好比数组(my.servers),写起来更为复杂。而对应的YAML格式文件就简单不少:数组
由于此前有过Android的开发经验,因此这一改变对个人影响并不大😄。gradle逐渐替代meavn应该是目前的趋势,可是目前大部分教学和企业采用的仍是以meavn为主,因此此前我也不曾尝试过采用gradle构建项目。由此看出Halo仍是很Fashion的👍。tomcat
首先打开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的项目运行起来仍是比较简单的🤪。页面也很美观👍
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设计