新主站开发-Log

怎么说呢?其实可以不用记录,但是(非盈利)私人项目这大概是最后一个了,还是记录一下吧。

主站原来基于 Python Flask 等技术,现在完全基于 SpringBoot技术栈,记录一下给别人参考。

(或者我自己,以后那一块儿配置忘记了,除了参考我的 HandBook,也可以看这里)

 

书写时间:书写工具:内容
2020年1月尾 ~ 2020年2月上旬打字机 Typora (for mac)Do one, Do well
   

一、创建工程

创建 SpringBoot 项目,严格来说是 SpringMVC 的 web 项目。

此时不要选择过多的依赖,先让项目能跑起来。

image-20200131185730659

image-20200131190019352

因为我这里并不写 jsp,而采用的模板渲染,所以这里选择 Jar 包,OK的。

image-20200131191023660

 

基本上只选了 Spring Web MVC 相关的,其他的包括数据库支持都没有选。

(后面需要的时候一步一步的来 add Framework 或者 手动添加依赖)

image-20200131192358965

等着 Maven 依赖下载完毕(上面有 Dependencies 显示的时候),然后跑起来试试看看。

image-20200131193126380

 

二、处理包结构

编写入口的 Controller,这里首先要建立相关的包结构:

image-20200131200244774

我个人有个习惯如果是接口,一般不会再前面写 I 字母,而实现类上面则是标注 Impl 后缀(且单独分包)。

 

三、初步配置

先配置一下 application.properties

image-20200131202317092

同时在 templates 文件目录下放入一个 html,最好是分模块(蓝图、板块)放置。

 

四、跑起来

写个 Controller,然后跑起来;不过以我的经验,这里最好先来个 BaseController,后面会提取公共部分过来的:

image-20200131203214495

然后填充好 control 就跑起来吧: (代码略)

image-20200131203230308

五、配置热部署

也是醉了,加入 spring-boot-devtools 依赖,但是 IDE 完全没有给我们配置,所以热部署现在还不好用。

来配置一下 devtools 吧:

image-20200131204026142

image-20200131210031222

仅仅修改 html 文件,没有相关的 java 文件,比如 Mapping 方法里面的 model 貌似也不会重启。

所以我这里还是狠心,调整了一下默认的 exclude,把 template 放进来,然后还是不生效

查询了一下资料,大致是说要配置 IDE,让它动态编译?

image-20200131210141202

然后调出 Maintainence 的界面 control + shift + meta + /:

image-20200131210455533

然后彻底重启一下 IDEA。

(貌似如果自己外部的 Tomcat 程序,那么还需要配置Tomcat)

 

六、引入测试

引入依赖吧:

image-20200131212830976

不过我还是习惯 JUnit,抱歉了spring-test: (后续注解也要修改)

image-20200131213552628

image-20200131213443854

当然习惯用 Spring boot 自带的也行。(从 @Test 注解就能看出来区别)

先从 HandBook 里面把测试片段拷贝过来:

image-20200131215325530

 

七、配置日志

这里如果要看某些默认配置,貌似还是得弄一下日志级别。(高于某级别才显示)

TRACE < DEBUG < INFO < WARN < ERROR < FATAL

先引入包,其实可以不必引入

image-20200131220239549

其实可以不必引入:

因为 Thymeleaf依赖包含了spring-boot-starter,最终我只要引入Thymeleaf即可。

试试先不配置,来测试一个日志的引入情况:

image-20200131221738536

然后,再测试一下配置之后的情况:

The same result,好,那配置成 debug 呢?

image-20200131221909298

已经坐实了,如果不配置,默认就是 info 级别。(它能察觉 profile 是 dev,然后仍然配置了 info 级别,胃疼)

还是配置成 debug 级别吧,生产的话配置为 info。

 

但是我这里引入了 LomBok啊(启用了 Annotation Processors),我肯定不能这样弄啊。

image-20200131222523327

Feels lucky...

全部的配置一般是:

image-20200131224209729

 

认情况下,日志文件的大小达到10MB时会切分一次,产生新的日志文件。

image-20200131224411283

先这样吧,我是怕了。这得几千万的业务啊。

 

八、构建主页面

主页面需要很多数据,从缓存中拿或者从数据库中查询等先不管,先用假数据填充一下。

确定了主站的导航,然后能够划分模块,然后可以根据用户-角色,限定可以访问的 URL。

这一部分主要就是从 Jinja2 切换到 Thymeleaf 引擎,OK,话不多说。

image-20200201145653660

上面还说错了,这里还没有涉及到引擎问题,因为连 VO 都没有。这里完全就是假数据。image-20200204140846905

当然这里显示的还是 站点主人 的信息以及记录的时间时区等信息。

这里有一个非常搞人的的资源路径问题,我是说,同一份代码怎么匹配开发时本地路径和部署时CDN的问题。

不过好在解决了(限于这个模板引擎确实不怎么优雅,所以嘛,或许还有优化的余地)。

 

九、主页国际化

先不慌着去做其他页面的Controller逻辑,这里处理好首页的国际化问题(提供用户可选)。

image-20200204143224390

这里配置完毕后,需要页面(模板引擎) + 代码两方面都支持国际化处理,所以还是写一个Utils类方便处理。

同时,这里要相应用户的用户的切换请求,处理默认的区域解析器,还要自定义一个拦截器去处理。

image-20200204222952203

主要还是围绕 cookie 改变UI,其中解决了泛地区问题。

公告板的数据从数据库拿出来,由于我肯定只会用一种语言去写,又不想调用外部API进行翻译,干脆就直接用英文算了,即使用代码转换, plus 翻译,最终也未必是我想要的效果。英文挺好的。

调整资源引用,布局,应用上下文/服务器上下文,工作量还真不少。

 

 

十、主页数据填充

之所以现在不慌着做其他模块,并不是别的,而是要 解耦

这里用冗余的数据表,数据来避免直接依赖别的表,或者多级,多表,多次查询。

以空间换时间也好,解耦也好,总之我管这些数据中间层怎么整的,只从固定的地方拿数据就对了。

简单的设计慢慢累积,最后大系统才不会太复杂;如果现在就开始依赖丛生,后面就不要看了,肯定很乱。

 

然后这里就要引入 Mybatis, Mapper 这些,顺便可以引入一些自动 Generator 简化工作。

 

十一、 Not This Time

配置 SpringSecurity(重点)

如果不先配置这类 URL 拦截的插件,那么后面配置其他组件会遇到好多问题。

一般都需要配置个差不多才行。

引入依赖:

实际开发中,我们一般会自定义用户,角色,模块的权限。所以简单配置,比如下面这样的,就不推荐了。

image-20200201011558674

这里还是通过 WebSecurityConfigurerAdapter (其实是 WebSecurityConfigurer的默认实现,抽象类 )进行自定义权限,准确说就是重写它的三个 config 接口。

这里就要进入重点代码阶段了:

也就是我们常说的运用中间表来绑定用户与角色的,然后后面可以根据用户的role/身份来决定其能够访问哪些模块,具体来说是可以通过哪些 url。

举个例子,如果是管理员,那么其有权限管理所有用户,对所有模块有 read/write 权限;如果是 site owner 其可以拥有比普通 user 更多的模块使用权,而 user 则只能用所有模块的子集的功能。

(其实角色和权限也是三表的关系,即多对多)

这里先不管,因为这里引入 SpringSecurity 只是为了后面可以配置监控。

(后续再来根据各个模块的需要,配置 SpringSecurity)

 

 

配置监控

现在配置监控?正是时候。(趁还没有开始业务逻辑时) 之后我写 API,写Mapping就能更加清楚的知道当前开放了哪些链接。这里我就不直接配置原始的 Actuator 了,而是配置其升级封装版本:

spring-boot-admin 是一个针对 Spring Boot 的 Actuator 接口进行 UI 美化封装的监控工具,它可以在列表中浏览所有被监控 spring-boot 项目的基本信息、详细的 Health 信息、内存信息、JVM 信息、垃圾回收信息、各种配置信息(比如数据源、缓存列表和命中率)等,还可以直接修改 logger 的 level。

其实功能和 Actuator 差不多,就是,好看一点

引入依赖:

OK,带有版本号的依赖不能这么写,应该:

不展开解释了。

然后在启动类头上加上 @EnableAdminServer。(等依赖加载完毕导入包)

然后启动试试,看看报不报错。(这里还要设置一下,服务端的监控端点只能是 admin 进行访问)

image-20200131230705918

简直不太丑。

接着引入 spring-boot-admin-starter-client,方便在浏览器端查看。

image-20200131230943501

(需要单独部署一个应用,我怕内存撑不住)

 

额外感触

 

整个项目下来,我发现了很多问题,自己的以及同行的,当然同行的就不说了。

第一个方面:

程序员会过时么?我想不会的。

因为程序员本质上属于工具人,大多数还是干活的。

所以如果自己的知识更新迭代更不上,很可能用完就被丢弃;同时,开发经验越丰富的人越是触类旁通,赢家通吃。

比如说以前处理国际化的问题的时候,就没有注意到,有些参数可能已经失效了:

image-20200201175839423

image-20200201181538955

而后也没有发生问题,但切换到 Java API 时,它并没有 Python 那么方便写法,所以即便连接参数那里侥幸不出问题,也不保证 JVM/System 的时间和数据库的 Time_zone 对不上的情况。

然后从这里还引出一个问题:人工智能代码?我想吧,只要技术不断更新,不断有新的业务出现,那么低阶智能无用。

 

第二个方面:

做一件事情有很多方式,但是最适合的往往只有一两种。

爱迪生和特斯拉的交流电直流电之争告诉我们,真理迟早胜过权威。但是并不是所有的事情都会在后来被大家认识的这么透彻,所以很有可能存在黎明前的昏暗时刻。比如某个技术栈就是要优于另外一个技术体系,但没有办法,上面管事儿的说了,大家(从众)用这个,所以你也就用这个吧。

但,技术是死的,人是变通的;时时刻刻应该变被动为主动,把不熟悉变为熟悉。

 

第三个方面:

如果你又要调界面,又要写业务逻辑,又要部署环境

全干工程的话,请多配一、两台显示器;请选用大内存,多屏幕的话,会吃 GPU 的,不是有些人说的给程序员的机器不用配置什么 GPU。(通常我们只注重CPU性能)

因为太弱的机器容易把它累趴下,即便没有死机,也会出现累的直吼(风扇呼呼呼)。

 

 

最后一个: 珍爱生命,远离编译