学习开源项目Halo(二)

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的国际化操作了,虽然简单,但是也是值得一看。

发布了24 篇原创文章 · 获赞 9 · 访问量 6042

猜你喜欢

转载自blog.csdn.net/SiuMu_/article/details/102872807