《Spring Boot實戰》之(zhī)二:開發第一個(gè)應用程序 - 新聞資訊 - 雲南小程序開發|雲南軟件開發|雲南網站建設-昆明融晨信息技術有限公司

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不(bù)管是(shì)網站,軟件還是(shì)小程序,都要(yào / yāo)直接或間接能爲(wéi / wèi)您産生價值,我們在(zài)追求其視覺表現的(de)同時(shí),更側重于(yú)功能的(de)便捷,營銷的(de)便利,運營的(de)高效,讓網站成爲(wéi / wèi)營銷工具,讓軟件能切實提升企業内部管理水平和(hé / huò)效率。優秀的(de)程序爲(wéi / wèi)後期升級提供便捷的(de)支持!

您當前位置>首頁 » 新聞資訊 » 技術分享 >

《Spring Boot實戰》之(zhī)二:開發第一個(gè)應用程序

發表時(shí)間:2019-7-5

發布人(rén):融晨科技

浏覽次數:41

本章使用Spring Boot實現一個(gè)簡單的(de)例子(zǐ),主要(yào / yāo)包括兩個(gè)知識點:

  • 使用Spring Boot的(de)起步依賴
  • 使用Spring Boot自動進行Spring的(de)配置

2.1 運用Spring Boot

下面将使用Spring Boot創建一個(gè)簡單的(de)閱讀列表程序,用戶可以(yǐ)輸入想讀的(de) 圖書信息,查看列表,删除已經讀過的(de)書。

首先,使用Spring Boot初始化項目,從技術角度來(lái)看,我們要(yào / yāo)用Spring MVC來(lái)處理Web請求,用Thymeleaf來(lái)定義Web視圖,用Spring Data JPA來(lái)把閱讀列表持久化到(dào)數據庫裏,這(zhè)裏先用嵌入式的(de)H2數據庫。我們使用Initializr的(de)Web界面進行初始化,在(zài)添加依賴的(de)地(dì / de)方添加Web、Thymeleaf和(hé / huò)JPA。還要(yào / yāo)添加H2,以(yǐ)在(zài)開發應用程序時(shí)使用内嵌式數據庫。

初始化後的(de)文件結構:

2.1.1 ReadListApplication.java

首先看ReadListApplication.java,ReadListApplication在(zài)Spring Boot應用程序裏有兩個(gè)作用:配置和(hé / huò)啓動引導。首先, 這(zhè)是(shì)主要(yào / yāo)的(de)Spring配置類。雖然Spring Boot的(de)自動配置免除了(le/liǎo)很多Spring配置,但你還需要(yào / yāo)進行 少量配置來(lái)啓用自動配置。@SpringBootApplication開啓了(le/liǎo)Spring的(de)組件掃描和(hé / huò)Spring Boot的(de)自動配置功能。實際 上(shàng),@SpringBootApplication将三個(gè)有用的(de)注解組合在(zài)了(le/liǎo)一起。

  • Spring的(de)@Configuration:标明該類使用Spring基于(yú)Java的(de)配置。
  • Spring的(de)@ComponentScan:啓用組件掃描,這(zhè)樣你寫的(de)Web控制器類和(hé / huò)其他(tā)組件才能被 自動發現并注冊爲(wéi / wèi)Spring應用程序上(shàng)下文裏的(de)Bean。本章稍後會寫一個(gè)簡單的(de)Spring MVC 控制器,使用@Controller進行注解,這(zhè)樣組件掃描才能找到(dào)它。
  • Spring Boot 的(de) @EnableAutoConfiguration :這(zhè)個(gè)注解也(yě)可以(yǐ)稱爲(wéi / wèi) @Abracadabra,就(jiù)是(shì)這(zhè)一行配置開啓了(le/liǎo)Spring Boot自動配置的(de)魔力,讓你不(bù)用再寫成篇的(de)配置了(le/liǎo)。

如前所述,ReadListApplication還有一個(gè)作用是(shì)啓動引導,運行Spring Boot應用程序有兩種方式:一是(shì)通過傳統的(de)WAR包形式;二是(shì)通過可執行jar包的(de)方式。這(zhè)裏向SpringApplication.run()傳遞了(le/liǎo)一個(gè)ReadingListApplication類的(de)引用,還有命令行參數,通過這(zhè)些東西啓動應用程序。

package com.yuan.readlist;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication    //開啓組件掃描和(hé / huò)自動配置
public class ReadlistApplication {

	public static void main(String[] args) {
		SpringApplication.run(ReadlistApplication.class, args); //負責啓動引導應用程序
	}
}

2.1.2 ReadlistApplicationTests.java

ReadingListApplicationTests不(bù)僅提供了(le/liǎo)一個(gè)用于(yú)測試Spring Boot項目的(de)框架,它還是(shì)一個(gè)例子(zǐ),告訴你如何爲(wéi / wèi)Spring Boot應用程序編寫測試。

contextLoads()這(zhè)個(gè)空方法足以(yǐ)證明應用程序上(shàng)下文的(de)加載沒有問題,如果ReadingListApplication裏定義的(de)配置是(shì)好的(de),就(jiù)能通過測試。如果有問題,測試就(jiù)會失敗。

當然,現在(zài)這(zhè)隻是(shì)一個(gè)新的(de)應用程序,你還會添加自己的(de)測試。但contextLoads()方法是(shì)個(gè)良好的(de)開端,此刻可以(yǐ)驗證應用程序提供的(de)各種功能。第4章會更詳細地(dì / de)讨論如何測試Spring Boot應用程序。

package com.yuan.readlist;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ReadlistApplicationTests {

	@Test
	public void contextLoads() {
	}
}

2.1.3 application.properties

Initializr爲(wéi / wèi)你生成的(de)application.properties文件是(shì)一個(gè)空文件,該文件可以(yǐ)用來(lái)調整Spring Boot的(de)自動配置。

要(yào / yāo)注意的(de)是(shì),你完全不(bù)用告訴Spring Boot爲(wéi / wèi)你加載application.properties,隻要(yào / yāo)它存在(zài)就(jiù)會被加載,Spring和(hé / huò)應用程序代碼都能獲取其中的(de)屬性,當然如果它不(bù)存在(zài)也(yě)完全沒有問題,Spring Boot會使用其默認配置。

2.1.4 運行項目

構建一個(gè)Spring Boot應用程序和(hé / huò)構建其他(tā)Java應用程序的(de)過程類似,可以(yǐ)選擇GradleMaven作爲(wéi / wèi)構建工具。描述構建說(shuō)明文件的(de)方法和(hé / huò)描述非Spring Boot應用程序的(de)方法也(yě)相似。Spring Boot爲(wéi / wèi)Gradle和(hé / huò)Maven提供了(le/liǎo)構建插件,以(yǐ)便輔助構建Spring Boot項目。

将項目導入到(dào)MyEclipse中,執行ReadlistApplication的(de)main方法,即可運行項目,然後浏覽器訪問127.0.0.1:8080,由于(yú)還沒有寫控制器類,會打開一個(gè)404的(de)錯誤頁面。

2.2 使用起步依賴

指定基于(yú)功能的(de)依賴

通過使用Spring Boot的(de)起步依賴,可以(yǐ)使我們不(bù)用指定具體的(de)版本号,甚至不(bù)需要(yào / yāo)指定具體使用的(de)依賴。比如我們前面在(zài)引入依賴時(shí),我們隻是(shì)在(zài)Initializr添加了(le/liǎo)WebThymeleaf、JPA和(hé / huò)H2,而(ér)通過傳遞依賴,它們聲明的(de)依賴也(yě)會被傳遞依賴進來(lái),添加這(zhè)四個(gè)依賴就(jiù)等價于(yú)将相關的(de)庫都添加了(le/liǎo)進來(lái)。在(zài)《Spring Boot實戰》附錄B羅列出(chū)了(le/liǎo)全部起步依賴,并簡要(yào / yāo)描述了(le/liǎo)一下它們向項目構建引入了(le/liǎo)什麽。

覆蓋起步依賴引入的(de)傳遞依賴

起步依賴和(hé / huò)你項目裏的(de)其他(tā)依賴沒什麽區别。也(yě)就(jiù)是(shì)說(shuō),你可以(yǐ)通過構建工具中的(de)功能,選擇性地(dì / de)覆蓋它們引入的(de)傳遞依賴的(de)版本号,排除傳遞依賴,當然還可以(yǐ)爲(wéi / wèi)那些Spring Boot起步依賴沒有涵蓋的(de)庫指定依賴。在(zài)Maven裏,可以(yǐ)用元素來(lái)排除傳遞依賴。

Maven總是(shì)會用最近的(de)依賴,也(yě)就(jiù)是(shì)說(shuō),如果你在(zài)項目裏想要(yào / yāo)覆蓋Spring Boot引入的(de)傳遞依賴,可以(yǐ)直接在(zài)在(zài)項目的(de)構建說(shuō)明文件裏增加的(de)這(zhè)個(gè)依賴。

(關于(yú)起步依賴更多詳細内容,參考《Spring Boot實戰》2.2節使用起步依賴。)

2.3 使用自動配置

簡每當應用程序啓動的(de)時(shí)候,Spring Boot檢測ClassPath中包含的(de)包,并對包含的(de)包做一個(gè)基本的(de)配置。比如Spring Security是(shì)不(bù)是(shì)在(zài)Classpath裏?如果是(shì),則進行一個(gè)非常基本的(de)Web安全設置。

每當應用程序啓動的(de)時(shí)候,Spring Boot的(de)自動配置都要(yào / yāo)做将近200個(gè)這(zhè)樣的(de)決定,涵蓋安全、 集成、持久化、Web開發等諸多方面。所有這(zhè)些自動配置就(jiù)是(shì)爲(wéi / wèi)了(le/liǎo)盡量不(bù)讓你自己寫配置,從而(ér)更多的(de)專注于(yú)程序的(de)功能。

下面我們繼續ReadList的(de)功能實現:

  • 定義領域模型

讀者閱讀列表上(shàng)的(de)書是(shì)本例的(de)核心領域概念,我們定義一個(gè)實體類Book來(lái)表示這(zhè)個(gè)概念。

@Entity注解表明它是(shì)一個(gè)JPA實體,id屬性加了(le/liǎo)@Id和(hé / huò)@GeneratedValue注解,說(shuō)明這(zhè)個(gè)字段是(shì)實體的(de)唯一标識,并且這(zhè)個(gè)字段的(de)值是(shì)自動生成的(de)。

package com.yuan.readlist;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Book {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	private String reader;
	private String isbn;
	private String title;
	private String author;
	private String description;
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getReader() {
		return reader;
	}
	public void setReader(String reader) {
		this.reader = reader;
	}
	public String getIsbn() {
		return isbn;
	}
	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
}
  • 定義倉庫接口

用于(yú)把Book對象持久化到(dào)數據庫的(de)倉庫了(le/liǎo)。因爲(wéi / wèi)用了(le/liǎo)Spring Data JPA,所以(yǐ)我們要(yào / yāo)做的(de)就(jiù)是(shì)簡單地(dì / de)定義一個(gè)接口,擴展一下Spring Data JPA的(de)JpaRepository接口:

package com.yuan.readlist;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ReadingListRepository extends JpaRepository<Book, Long> {
	List<Book> findByReader(String reader);
}

通過擴展JpaRepositoryReadingListRepository直接繼承了(le/liǎo)18個(gè)執行常用持久化操作的(de)方法。JpaRepository是(shì)個(gè)泛型接口,有兩個(gè)參數:倉庫操作的(de)領域對象類型,及其ID屬性的(de)類型。此外,我還增加了(le/liǎo)一個(gè)findByReader()方法,可以(yǐ)根據讀者的(de)用戶名來(lái)查找閱讀列表。 如果你好奇誰來(lái)實現這(zhè)個(gè)ReadingListRepository及其繼承的(de)18個(gè)方法,請不(bù)用擔心,Spring Data提供了(le/liǎo)很神奇的(de)魔法,隻需定義倉庫接口,在(zài)應用程序啓動後,該接口在(zài)運行時(shí)會自動實現。

  • 創建控制器

我們創建Spring MVC控制器來(lái)處理HTTP請求。ReadingListController使用了(le/liǎo)@Controller注解,這(zhè)樣組件掃描會自動将其注冊爲(wéi / wèi) Spring應用程序上(shàng)下文裏的(de)一個(gè)Bean。它還用了(le/liǎo)@RequestMapping注解,将其中所有的(de)處理器 方法都映射到(dào)了(le/liǎo)“/”這(zhè)個(gè)URL路徑上(shàng)。

package com.yuan.readlist;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
@Controller
@RequestMapping("/")
public class ReadingListController {
	private ReadingListRepository readingListRepository;
	@Autowired
	public ReadingListController(ReadingListRepository readingListRepository) {
		this.readingListRepository = readingListRepository;
	}
	@RequestMapping(value = "/{reader}", method = RequestMethod.GET)
	public String readersBooks(@PathVariable("reader") String reader,
			Model model) {
		List<Book> readingList = readingListRepository.findByReader(reader);
		if (readingList != null) {
			model.addAttribute("books", readingList);
		}
		return "readingList";
	}
	@RequestMapping(value = "/{reader}", method = RequestMethod.POST)
	public String addToReadingList(@PathVariable("reader") String reader,
			Book book) {
		book.setReader(reader);
		readingListRepository.save(book);
		return "redirect:/{reader}";
	}
}

該控制器有兩個(gè)方法。

readersBooks():處理/{reader}上(shàng)的(de)HTTP GET請求,根據路徑裏指定的(de)讀者,從(通過控制器的(de)構造器注入的(de))倉庫獲取Book列表。随後将這(zhè)個(gè)列表塞入模型,用的(de)鍵是(shì)books,最後返回readingList作爲(wéi / wèi)呈現模型的(de)視圖邏輯名稱。

addToReadingList():處理/{reader}上(shàng)的(de)HTTP POST請求,将請求正文裏的(de)數據綁定到(dào)一個(gè)Book對象上(shàng)。該方法把Book對象的(de)reader屬性設置爲(wéi / wèi)讀者的(de)姓名,随後通過倉庫的(de)save()方法保存修改後的(de)Book對象,最後重定向到(dào)/{reader}(控制器中的(de)另一個(gè)方法會處理該請求)。

  • 創建WEB界面

readersBooks()方法最後返回readingList作爲(wéi / wèi)邏輯視圖名,爲(wéi / wèi)此必須創建該視圖。因爲(wéi / wèi)在(zài)項目開始之(zhī)初就(jiù)決定要(yào / yāo)用Thymeleaf來(lái)定義應用程序的(de)視圖,所以(yǐ)接下來(lái)就(jiù)在(zài)src/main/resources/templates裏創建一個(gè)名爲(wéi / wèi)readingList.html的(de)文件:

<html>
<head>
<title>Reading List</title>
<link rel="stylesheet" th:href="@{/style.css}"></link>
</head>
<body
	<h2>Your Reading List</h2>
	<div th:unless="${#lists.isEmpty(books)}">
		<dl th:each="book : ${books}">
			<dt class="bookHeadline">
				<span th:text="${book.title}">Title</span> by <span
					th:text="${book.author}">Author</span> (ISBN: <span
					th:text="${book.isbn}">ISBN</span>)
			</dt>
			<dd class="bookDescription">
				<span th:if="${book.description}" th:text="${book.description}">Description</span>
				<span th:if="${book.description eq null}"> No description
					available</span>
			</dd>
		</dl>
	</div>
	<div th:if="${#lists.isEmpty(books)}">
		<p>You have no books in your book list</p>
	</div>
	<hr />
	<h3>Add a book</h3>
	<form method="POST">
		<label for="title">Title:</label> <input type="text" name="title"
			size="50"></input><br /> <label for="author">Author:</label> <input
			type="text" name="author" size="50"></input><br /> <label for="isbn">ISBN:</label>
		<input type="text" name="isbn" size="15"></input><br /> <label
			for="description">Description:</label><br />
		<textarea name="description" cols="80" rows="5"> 
 </textarea>
		<br /> <input type="submit"></input>
	</form>
</body>
</html>

添加名爲(wéi / wèi)style.css的(de)樣式文件,該文件位于(yú)src/main/resources/static目錄:

body { 
 background-color: #cccccc; 
 font-family: arial,helvetica,sans-serif; 
} 
.bookHeadline { 
 font-size: 12pt; 
 font-weight: bold; 
}
.bookDescription { 
 font-size: 10pt; 
} 
label { 
 font-weight: bold; 
}
  • 運行程序

到(dào)目前爲(wéi / wèi)止,我們就(jiù)已經完成了(le/liǎo)一個(gè)完整的(de)Spring WEB程序,可見我們并沒有進行什麽配置,所有的(de)配置都是(shì)Spring Boot自動完成的(de)。

下面我們來(lái)運行這(zhè)個(gè)WEB程序,在(zài)MyEclipse中右鍵,Run as Java Application,然後浏覽器訪問127.0.0.1:8080/name即可打開網頁,可提交查詢表單。

關于(yú)Spring Boot自動配置更多内容,及其如何實現自動配置功能,參見《Spring Boot實戰》2.3.3節内容。

2.4 總結

通過Spring Boot的(de)起步依賴和(hé / huò)自動配置,你可以(yǐ)更加快速、便捷地(dì / de)開發Spring應用程序。在(zài)下一章,我們将會看到(dào)如何覆蓋Spring Boot自動配置,借此達成應用程序的(de)一些特殊要(yào / yāo)求,還有如何運用類似的(de)技術來(lái)配置自己的(de)應用程序組件。

相關案例查看更多