1. 程式人生 > >SpringBoot系列四:SpringBoot開發(改變環境屬性、讀取資源文件、Bean 配置、模版渲染、profile 配置)

SpringBoot系列四:SpringBoot開發(改變環境屬性、讀取資源文件、Bean 配置、模版渲染、profile 配置)

pat row 開發 ima set his 改變 端口配置 import

1、概念

SpringBoot 開發深入

2、具體內容

在之前已經基本上了解了整個 SpringBoot 運行機制,但是也需要清楚的認識到以下的問題,在實際的項目開發之中,尤其是 Java 的 MVC 版項目裏面,所有的項目都一定需要滿足於如下幾點要求:

· 訪問的端口不能夠是 8080,應該使用默認的 80 端口;

· 在項目之中為了方便進行數據的維護,建議建立一系列的*.properties 配置文件,例如:提示消息、跳轉路徑;

· 所有的控制器現在都采用了 Rest 風格輸出,但是正常來講,信息的顯示應該交給頁面(不再是 JSP)負責完成;

· 在進行項目打包的時候應該考慮到不同的 profile 配置(不同的環境使用不同的端口訪問,如生產環境80端口,beta環境8090端口,dev環境8080端口)。

2.1、改變環境屬性

通過當前的執行可以發現,默認情況下,在 SpringBoot 裏面啟動 WEB 容器為 Tomcat:

INFO 4448 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup

INFO 4448 --- [ restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)

從實際的開發來講,我們的 WEB 部署項目如果是單獨運行不可能運行在 8080 端口上。從正常來講我們的服務器應該運行在80 端口上,所以如果要想修改這樣的默認環境,則必須編寫與之對應的配置文件,該配置文件一定要寫在 classpath 之中,例如: 項目中的“src/main/resources”就是一個 classpath 路徑,那麽在這個目錄之中直接創建有一個 application.properties(文件名稱絕對 不要改變

)。

範例:定義 application.properties 配置文件

1 # 設置Tomcat的運行服務所在端口
2 
3 server.port=80

隨後重新運行程序會出現有如下的提示信息:“Tomcat started on port(s): 80 (http)”。

範例:如果有需要也可以配置 contextPath 的信息

# 設置Tomcat的運行服務所在端口
server.port=80
# 可以配置ContextPath訪問路徑,但是在實際開發之中是不能夠進行配置的
server.context-path=/hello

此時的訪問路徑需要追加 contextPath 前綴:http://localhost/hello/;

嚴格來講在 SpringBoot、SpringCloud 裏面可以使用兩類配置文件:application.properties、application.yml。

YAML 文件: 這是一種結構化的數據文件,其在很多的地方上都使用過,例如:Apache Storm 開發組件上進行配置的時候使用的就是yml 配置文件,該配置文件的全稱(Yet Another Markup Languange、仍然是一種標記語言)。

範例:定義 application.yml 配置文件

server:
 port: 80 # 此處設置的服務的訪問端口配置

如果 application.properties 和 application.yml 兩個文件同時存在使用那個?

那麽這個時候將優先進行application.properties配置文件的加載,如果現在兩個配置項的作用沖突了,則以 properties 為主,如果不沖突,則以存在的為主。

在之前默認使用的 WEB 容器是 Tomcat 容器,實際上在 SpringBoot 裏面如果用戶有需要也可以將容器更換為 jetty 容器,如果 現在要想使用這個容器,則只需要追加一些依賴即可:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

如果在以後項目以微服務的方式進行打包發布的時候,強烈建議大家使用 jetty 服務進行發布。

2.2、讀取資源文件

在實際的項目開發之中資源文件一定不可或缺,因為所有的提示文字信息都要求在資源文件之中進行定義,而且資源文件是 實現國際化技術的主要手段。如果要想在 SpringBoot 裏面進行資源文件的配置只需要做一些簡單的 application.yml 配置即可,而且 所有註入的資源文件都可以像最初的 Spring 處理那樣直接使用 MessageSource 進行讀取。

1、 為了統一管理資源文件,在“src/main/resources”目錄之中建立有一個 i18n 的存儲目錄;

2、 在“src/main/resources/i18n”目錄之中建立有兩個資源文件:

· 建立 Messages.properties:

welcome.url=www.study.cn
welcome.msg=歡迎{0}光臨!

· 建立 Pages.properties 配置文件:

member.add.page=/pages/back/admin/member/member_add.jsp
member.add.action=/pages/back/admin/member/member_add.action

3、 修改 application.yml 配置文件:

spring:     # 表示該配置直接為Spring容器負責處理
  messages: # 表示進行資源配置
    basename: i18n/Messages,i18n/Pages  # 資源文件的名稱
server:
  port: 80      # 此處設置的服務的訪問端口配置

4、 當執行完以上的配置之後會自動為用戶創建 MessageSource 對象,那麽用戶在使用的時候直接註入此對象即可。

· 考慮到實際開發的標準型,所以現在建議創建一個父的控制器的抽象類;AbstractBaseController,而後在此抽象類之中進 行資源讀取類的配置;

package cn.study.microboot.util.controller;

import java.util.Locale;

import javax.annotation.Resource;

import org.springframework.context.MessageSource;

public abstract class AbstractBaseController {
    @Resource
    private MessageSource messageSource; // 自動註入此資源對象
    public String getMessage(String key, String... args) {
        return this.messageSource.getMessage(key, args, Locale.getDefault()); 
    }
}

5、 在控制器的子類之中讀取以上的配置信息:

package cn.study.microboot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import cn.mldn.microboot.util.controller.AbstractBaseController;

@RestController
public class MessageController extends AbstractBaseController {
    @RequestMapping(value = "/echo", method = RequestMethod.GET)
    public String echo(String mid) {
        System.out.println("【*** 訪問地址 ***】" + super.getMessage("member.add.action"));
        return super.getMessage("welcome.msg", mid);
    }
}

6、 編寫一個 junit 測試類,來測試以上的控制器程序是否正確:

package cn.study.microboot.test;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import cn.mldn.microboot.StartSpringBootMain;
import cn.mldn.microboot.controller.MessageController;

@SpringBootTest(classes = StartSpringBootMain.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class TestMessageController {
    @Resource
    private MessageController messageController;
    @Test
    public void testEcho() {
        System.out.println(this.messageController.echo("lgs"));
    }
}

輸出:

【*** 訪問地址 ***】/pages/back/admin/member/member_add.action
歡迎lgs光臨!

通過 SpringBoot 執行可以清楚的發現,在 SpringBoot 裏面所有對象信息的註入配置操作,都直接通過一行簡單的字符串實現 了,而且最終也能夠保持與之前同樣的運行效果。

2.3、Bean 配置

在使用 Spring 進行開發配置的時候有兩類選擇:*.xml 配置文件、配置的 Bean(@Configure),於是在 SpringBoot 的開發世界 裏面,為了繼續崇尚所謂的“零配置”,提供有一種簡單的支持,也就是說如果現在你真的有配置需要通過*.xml 文件編寫,但是又 不想出現配置文件的話,這個時候最簡單的做法就是使用 Bean 的方式來進行類的配置。

前提:該配置程序的 Bean 所在的包必須是程序啟動類所在包的子包之中,這樣才可以自動掃描到。

1.在傳統的開發中我們一般使用註解@service和@Resource即可完成bean的配置和註入

2.在SpringBoot中使用@Configuration和@Bean配置bean

package cn.study.microboot.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import cn.mldn.microboot.service.impl.MessageServiceImpl;

@Configuration    // 此處為配置項
public class ServiceConfig {
    @Bean(name="configService")        // 此處返回的是一個Spring的配置Bean,與xml的“<bean>”等價
    public MessageServiceImpl getMessageService() {    // 方法名稱隨便寫
        return new MessageServiceImpl() ;
    }
}

此時采用了自動掃描 Bean 的模式來進行了相關對象的配置。

3、 SSM 或 SSH 開發框架出現的時間比較長,現在遷移到 SpringBoot 之中,那麽如果說現在你已經有一個非常完善的 xml 配置文件出現了,那麽難道還需要將整個的 xml 配置文件轉換為 Bean 配置嗎?為了防止這類情況出現, SpringBoot 也支持有配置文件的 讀取,例如:下面創建一個 spring-common.xml 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="messageService" class="cn.mldn.microboot.service.impl.MessageServiceImpl" />
</beans>

4、 隨後可以在程序啟動類上使用 xml 進行配置加載:

package cn.study.microboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication    // 啟動SpringBoot程序,而後自帶子包掃描
@ImportResource(locations={"classpath:spring-common.xml"})
public class StartSpringBootMain {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(StartSpringBootMain.class, args);
    }
}

如果此時所配置的兩個 bean 都沒有名字那麽在進行註入的時候一定會出現重復的錯誤,而這個錯誤在新版本裏面將其做了完 善,不過如果要想在開發之中準確的註入指定的對象,則需要使用名字完成:

@Resource(name="messageService")
private IMessageService messageService ;

2.4、模版渲染

在之前所見到的信息顯示發現都是以 Rest 風格進行顯示,但是很明顯在實際的開發之中,所有數據的顯示最終都應該交由頁 面完成,但是這個頁面並不是*.jsp 頁面,而是普通的*.html 頁面,而且最為重要的是,此處所使用的渲染的頁面采用的是模版方式 的顯示,而在 Java 開發行業,對於前臺的顯示模版常見的一共有三類技術:FreeMarker、Velocity、thymeleaf(推薦使用),於是下 面就利用 thymeleaf 實現一個簡單的模版渲染操作。

1、 如果要想在項目之中去使用 thymeleaf 模版,那麽應該首先進行相關支持依賴庫的導入,修改 pom.xml 配置文件:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

2、 本次的開發依然要通過一個控制層跳轉到頁面之中進行信息顯示。在 SpringMVC 的時代使用的是 ModelAndView 傳遞,而現 在在 SpringBoot 裏面如果要傳遞直接在方法中定義一個 Model 參數即可。

package cn.study.microboot.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import cn.mldn.microboot.util.controller.AbstractBaseController;

@Controller
public class MessageController extends AbstractBaseController {
    @RequestMapping(value = "/show", method = RequestMethod.GET)
    public String show(String mid, Model model) {
        model.addAttribute("url", "www.study.cn"); // request屬性傳遞包裝
        model.addAttribute("mid", mid); // request屬性傳遞包裝
        return "message/message_show"; // 此處只返回一個路徑, 該路徑沒有設置後綴,後綴默認是*.html
    }
}

3、 現在的控制器之中使用的是“@Controller”註解,所以此時執行該控制器的方法後會進行跳轉處理。如果現在要進行跳轉 頁面的定義,有嚴格要求:在CLASSPATH路徑下(src/main/resources、src/main/view)必須建立有一個templates的目錄,在這個目 錄裏面保存有thymeleaf的所有相關頁面,這些頁面可以按照文件目錄保存;

建立一個源代碼目錄:src/main/view;

技術分享圖片

4、 編寫 message_show.html 頁面(重要提示:該頁面編寫的時候所有的元素一定要完結

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>SpringBoot模版渲染</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<p th:text="‘官方網站:‘ + ${url}"/>
<p th:text="‘用戶名:‘ + ${mid}"/>
</body>
</html>

5、 運行服務,而後輸入訪問路徑:http://localhost/show?mid=lgs;

6、 如果現在我們所定義的要訪問的頁面不是通過控制器跳轉的怎麽辦?那麽為了解決這樣的問題,可以考慮在 thymeleaf 所在的 父路徑之中“src/main/view”建立一個 static 的子目錄,該目錄保存的是所有靜態頁面;

技術分享圖片

在以後的實際開發之中,像 js、css、images 等信息文件都要求放在 static 目錄裏面。

7、 thymeleaf 默認的訪問的頁面路徑的後綴為*.html,那麽也可以通過修改 application.yml 配置文件進行變更:

spring:     # 表示該配置直接為Spring容器負責處理
  thymeleaf:
    suffix: .htm
  messages: # 表示進行資源配置
    basename: i18n/Messages,i18n/Pages  # 資源文件的名稱
server:
  port: 80      # 此處設置的服務的訪問端口配置

這個時候你需要修改“src/main/view/templates/message”下的 message_show.html 頁面為 message_show.htm 才可以正常訪問。

2.5、profile 配置

在實際的開發之中,由於開發(dev)、測試(beta)、運行(product)的環境不同,有可能需要選擇不同的配置文件,所以在 SpringBoot 裏面充分的考慮到了此類問題,那麽就專門提供有多個 profile 配置,但是對於多 profile 配置一定給要區分出是 yml 還 是 properties,這兩種資源的配置是不同的。

1、 基於 yml 實現 profile 的配置處理:

· 在使用 yml 配置文件的時候所有可以使用的 profile 配置項都要求在一個文件之中編寫;

spring:
  profiles:
    active: product
---
spring:
  messages:
    basename: i18n/Messages,i18n/Pages
  profiles: dev
server:
  port: 8080
---
spring:
  messages:
    basename: i18n/Messages,i18n/Pages
  profiles: beta
server:
  port: 9090
---
spring:
  messages:
    basename: i18n/Messages,i18n/Pages
  profiles: product
server:
  port: 80

最初進行 profile 切換的處理可以通過 maven 的編譯工具動態選擇,但是在 Spring 裏面可以方便的實現這種切換。

2、 此時所有的 thymeleaf 頁面都保存在“src/main/view”目錄之中,而且所有的 SpringBoot 配置文件(*.yml)這個文件也應該都 一起輸出到 jar 文件裏面,那麽就需要配置一個資源的引用,修改“microboot”中的 pom.xml 配置文件:

<resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.yml</include>
                    <include>**/*.xml</include>
                    <include>**/*.tld</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                    <include>**/*.tld</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/view</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>

3、 隨後可以將項目進行打包處理,在打包之後也可以動態切換 profile 配置;

· Maven 打包:clean package;

· 隨後如果現在要使用默認的 profile 就正常執行:java -jar microboot.jar;

· 難道以後每一次訪問都需要重新打包嗎?也就是說為了方便用戶的動態進行 profile 切換,可以在程序執行的時候設置一個 執行的處理參數:java -jar microboot.jar --spring.profiles.active=beta;

4、 【趣味問題】現在當運行完成之後你會發現程序之中默認采用的圖標是 Spring 的圖標。

技術分享圖片

但是很多的公司應該去更換為自己的圖標,所以這個時候可以單獨準備出一個 ico 配置文件,可以將這個配置文件拷貝到 “src/main/view/static/images”目錄之中,隨後在頁面之中進行引入:

<link rel="icon" type="image/x-icon" href="/images/study.ico"/>

5、 在進行 profile 配置的時候特別需要註意一點,如果你使用的是 application.properties 配置,這樣的配置處理過程是不一樣的, 也就是說如果你基於屬性文件完成配置,那麽就需要編寫多個屬性文件內容:

技術分享圖片

隨後還是需要有一個公共的 application.properties 配置文件出現,用於指派可以使用的 profile 配置:

spring.profiles.active=beta

如果現在將開發程序打成*.jar 文件的話,也同樣可以在執行的時候使用“--spring.profiles.active=beta”動態指派不同的 profile 配置文件。

SpringBoot系列四:SpringBoot開發(改變環境屬性、讀取資源文件、Bean 配置、模版渲染、profile 配置)