学习开源项目Halo(二)

mac2026-08-21  2

undertow容器

打开application.yaml文件,就可以看到Halo的配置内容,笨鸟有笨的办法,我们可以一点点的开始分析,先来看看关于内置服务器undertow的配置

server: port: 8090 use-forward-headers: true undertow: io-threads: 2 worker-threads: 36 buffer-size: 1024 directBuffers: true servlet: session: timeout: 86400s

这些都是常规的设置,什么端口号啊,session失效时间,还有有关undertow的io线程数,阻塞任务线程池等等。这些配置如果不懂呢网上搜一搜就知道了。当然还有这个springboot内嵌服务器啊,如何将默认的tomcat转换为undertow也是需要自己慢慢弄明白的,如果不会呢,就可以看看我写的博客《springboot配置undertow容器》,不过呢我是用springboot2.1.1做的demo,假如你比我的版本高的话就可以不用博客里的最后一步,直接将tomcat依赖排除,加上undertow的依赖,然后配置文件写上配置就完事了,完全不用再配置一个ServletWebServerFactory,还是相当简单的。 

H2数据库

接下来就是H2数据库的配置了,如图所示

spring: output: ansi: enabled: always datasource: type: com.zaxxer.hikari.HikariDataSource # H2database 配置 driver-class-name: org.h2.Driver url: jdbc:h2:file:./halo/halo username: admin password: 123456 #MySql配置 # driver-class-name: com.mysql.cj.jdbc.Driver # url: jdbc:mysql://127.0.0.1:3306/halodb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai # username: root # password: 123456 h2: console: settings: web-allow-others: true path: /h2-console enabled: true jpa: hibernate: ddl-auto: update show-sql: false

作者用的是H2数据库并没有使用mysql,当然它也是可以支持mysql的,mysql我们已经熟悉了,所以我们可以试试这个陌生的H2数据库是怎么使用的。这些也是很常规的配置,我相信大家肯定看得懂,从上到下分别是,日志彩色显示,连接池(应该是连接池吧),驱动,url,用户名,密码,还有有关H2的配置,Jpa的配置啥的,mysql配置已经注释掉了。H2配置里的path属性表示项目启动之后就可以用这个路径来访问数据库,是的,它是通过浏览器访问数据库的,不过呢关系型数据库都差不多,都很简单,大家看一看就明白了。还有就是这个url地址,刚开始在file:后边是~符号,项目一启动就会在C盘用户目录下创建数据库文件,于是呢我就把它改到了项目根目录下./表示项目的根目录,如图所示

这个就是你的数据库了。

接下来就是有关Freemarker的配置,如果你想学就研究研究。不过呢现在都流行前后端分离的模式,所以我不打算研究它。

然后呢就是上传文件的设置,国际化的设置,日志的设置

servlet: multipart: max-file-size: 10MB max-request-size: 10MB # 多语言资源文件路径 messages: basename: i18n/messages logging: file: ./logs/log.log

关于springboot实现国际化也是非常的简单,如果没有做过,可以网上搜一搜,都有详细的教程,只要照着做就行了,当然要是有人像我一样不老老实实的照着做,出现问题了,可以参考我的这篇文章,是不是出现了和我一样的问题——springboot国际化

Halo的国际化

接下来我们来看看Halo是如何实现国际化的,我们先看看这个i18n文件夹里的properties文件,看着就不简单,500行左右,也就是近500个词作者都做了国际化翻译,要是让我来,光是给变量起名字都费死劲了。这里我还得说一句,看看人家的包名

                                         

看着就很好,一眼下去就知道哪个包是干什么的,我们想要找国际化设置,自然是在config包里面找

                                         

这里面就两个类,一看类名就知道是在哪个类里边,不得不说一句,我们要学学人家是怎么起名字的,光看类名就知道这个类是干啥的。我也是在几个月前才开始尽量起比较符合规范的名字,不要怕名字长,没关系,名字长不长的无所谓,我们要的是望文知意。点开这个类,往下翻,就能看到有关国际化的设置

/** * 国际化设置 * * @return LocaleResolver */ @Bean public LocaleResolver localeResolver() { final SessionLocaleResolver slr = new SessionLocaleResolver(); slr.setDefaultLocale(Locale.CHINA); return slr; } /** * 国际化参数拦截器 * * @return LocaleChangeInterceptor */ @Bean public LocaleChangeInterceptor localeChangeInterceptor() { final LocaleChangeInterceptor lci = new LocaleChangeInterceptor(); lci.setParamName("lang"); return lci; }

作者实现国际化的方式跟我的略有不同,使用的是SessionLocaleResolver和LocaleChangeInterceptor相结合的方式,不过作者为什么要将这两个对象用final修饰呢,难道是要把它变成唯一不可变的吗?但是如果把它交给spring来管理,默认的就是单例模式,不用final也可以吧。这个问题先存着,或许等我有项目经验了就明白了。言归正传,接下来就是注册拦截器了,也是在这个类里边,最上边的这个方法

/** * 注册拦截器 * * @param registry registry */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor) .addPathPatterns("/admin.*") .addPathPatterns("/admin/**") .addPathPatterns("/backup/**") .excludePathPatterns("/admin/login") .excludePathPatterns("/admin/getLogin") .excludePathPatterns("/static/**"); registry.addInterceptor(installInterceptor) .addPathPatterns("/**") .excludePathPatterns("/install") .excludePathPatterns("/install/do") .excludePathPatterns("/static/**"); registry.addInterceptor(apiInterceptor) .addPathPatterns("/api/**"); registry.addInterceptor(localeInterceptor) .addPathPatterns("/admin.*") .addPathPatterns("/admin/**") .addPathPatterns("/install"); registry.addInterceptor(localeChangeInterceptor()) .addPathPatterns("/install"); }

我们看到,它注册了不少拦截器,其中有两个关于国际化的,就是最后两个,它居然有两个拦截器,刚刚我们只是看到了其中一个LocaleChangeInterceptor用来拦截参数,通过参数来改变语言,接下来看看这个LocaleInterceptor主要是干啥的。看看有这么多拦截器就知道,作者肯定有一个包专门放拦截器,就是在web包下。我们打开这个拦截器类,也没几行代码,看着一行怪长,还没有写注释,但是我们耐心一读就明白了。这样,我手动加上注释再把代码贴出来。

@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //先从session中找到Locale final Object attribute = request.getSession().getAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME); //判断Locale是否存在,如果有就直接放行 if (null != attribute) { return true; } /* * 判断博客语言设置是不是en_US,如果是的话就在session中保存一个英文的Locale * 如果不是就存一个中文的Locale */ if (StrUtil.equals(LocaleEnum.EN_US.getValue(), OPTIONS.get(BlogPropertiesEnum.BLOG_LOCALE.getProp()))) { request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, new Locale("en", "US")); } else { request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, new Locale("zh", "CN")); } return true; }

这里作者又一次用了final,我依旧不甚理解为什么要用final修饰,而且好多地方都用了final,也可能是我经验少,没写过什么项目,到现在我写代码几乎没有用过final修饰,所以看到了这个final就觉得作者用了好多次。好了,回到正题,我们还是说一说这个国际化的问题,我们知道,国际化需要用Locale来决定用英文还是中文或者是其他语言,这个SessionLocaleResolver应该是将这个Locale保存到了session中,所以先要看看session中有没有这个Locale,如果有的话直接放行,直接用session中的Locale就行了,如果没有的话,自然是新建一个,怎么建呢,就是接下来的代码,先看看博客设置选项里是不是英文的,如果不是就建一个中文的。或许大家会有疑问,每个变量这么长都是啥意思?这个问题不要担心,作者已经做了注释,只要选中这个变量,然后快捷键ctrl+q就会显示出来这个变量的意思。这些基本上就是Halo的国际化操作了,虽然简单,但是也是值得一看。

最新回复(0)