學習開源項目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的國際化操作了,雖然簡單,但是也是值得一看。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章