Spring boot 入門(技術分享)

構建一個Spring Boot應用

先決條件
  • Java開發神器IDEA
  • JDK 1.8或更高版本
  • Maven 3.2+ 或者 Gradle 4+

通過Maven來構建

如果您不還熟悉maven,請參閱 使用Maven構建Java項目

接下來,我們通過IDEA 來快速創建maven項目。

  1. 點擊New->Project...
  1. 選擇Maven,點擊Next
  1. 輸入GroupIdArtifactIdVersion,點擊 Next
  1. 輸入Project nameProject location,點擊 Finish
  1. 項目創建成功后,你會得到如下界面

添加classpath依賴項

pom.xml描述了用于構建項目的策略,為了使得我們的項目支持spring-boot,我們需要在pom.xml添加如下依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sunmi</groupId>
    <artifactId>sping-boot-study</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <!--父節點啟動器-->
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
    </parent>

    <dependencies>
        <!--spring-boot依賴項-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

Spring Boot提供了許多“Starters”,可以將jar添加到classpath中。 我們的示例應用程序已經在pom.xml文件中指定parentspring-boot-starter-parentspring-boot-starter-parent是一個特殊的啟動器,提供有用的maven默認值。 它還提供了一個依賴項的version,以便您可以省略依賴項的版本標記。


創建一個Application

在這里,您將使用組件創建一個應用程序類:
src/main/java/hello/Application.java

package hello;

import java.util.Arrays;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
        return args -> {

            System.out.println("Let's inspect the beans provided by Spring Boot:");

            String[] beanNames = ctx.getBeanDefinitionNames();
            Arrays.sort(beanNames);
            for (String beanName : beanNames) {
                System.out.println(beanName);
            }

        };
    }

}
@SpringBootApplication是一個便利注釋,添加了以下所有內容:
  • @Configuration 標記該類作為應用程序上下文的bean定義的來源。
  • @EnableAutoConfiguration 告訴Spring Boot開始根據classpath設置,其他bean和各種屬性設置添加bean
  • 通常你會為Spring MVC應用添加@EnableWebMvc 注解,但Spring Boot會在classpath上看到webmvc時自動添加它。 這會將應用程序標記為Web應用程序,并激活關鍵行為以及設置調度程序servlet
    這會將應用程序標記為Web應用程序,并在安裝DispatcherServlet時激活關鍵行為。
  • @ComponentScan 告訴Springhello包中尋找其他componentsconfigurationsservices

main()方法使用Spring BootSpringApplication.run()方法來啟動應用程序。 您是否注意到沒有一行XML? 也沒有web.xml文件。 此Web應用程序是100%Java,您無需處理配置任何管道或基礎結構。

還有一個標記為@BeanCommandLineRunner方法,它在spring boot啟動時運行。 示例中它將檢索由您的應用程序創建或Spring Boot自動添加的所有bean。 它對它們進行分類并打印出來。


運行該應用程序

mvn spring-boot:run


創建一個簡單的Web應用程序

現在,我們為簡單的Web應用程序創建Web controller:
src/main/java/hello/HelloController.java

package hello;

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

@RestController
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "Greetings from Spring Boot!";
    }

}

該類被標記為@RestController,這意味著Spring MVC可以使用它來處理Web請求。 @RequestMapping/映射到index()方法。 從瀏覽器訪問或在命令行上使用curl時,該方法返回純文本。 這是因為@RestController結合了@Controller@ResponseBody,兩個注釋導致Web請求返回數據而不是視圖。


檢查服務
  1. 第一個終端執行mvn spring-boot:run
  2. 第二個終端執行
$ curl localhost:8080
Greetings from Spring Boot!

添加單元測試

您將需要為endpoint添加測試,Spring Test已經為此提供了一些機制,并且很容易包含在您的項目中。

maven中加入如下依賴

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

現在編寫一個簡單的單元測試,通過endpoint模擬servlet請求和響應:

package hello;

import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {

    @Autowired
    private MockMvc mvc;

    @Test
    public void getHello() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("Greetings from Spring Boot!")));
    }
}

MockMvc對象來自Spring Test,它允許您通過一組便利構造器類將HTTP請求發送到DispatcherServlet并對結果進行斷言。 請注意@AutoConfigureMockMvc@SpringBootTest一起使用以注入MockMvc實例。 使用@SpringBootTest后,web應用程序會被自動創建。

除了模擬HTTP請求周期之外,我們還可以使用Spring Boot編寫一個非常簡單的全棧集成測試。 例如,我們可以這樣做,而不是上面的模擬測試:

package hello;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

import java.net.URL;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIT {

    @LocalServerPort
    private int port;

    private URL base;

    @Autowired
    private TestRestTemplate template;

    @Before
    public void setUp() throws Exception {
        this.base = new URL("http://localhost:" + port + "/");
    }

    @Test
    public void getHello() throws Exception {
        ResponseEntity<String> response = template.getForEntity(base.toString(),
                String.class);
        assertThat(response.getBody(), equalTo("Greetings from Spring Boot!"));
    }
}

嵌入式服務器通過webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT在隨機端口上啟動,并在運行時使用@LocalServerPort發現實際端口。


創建一個可執行的Jar

我們通過創建一個包含全部依賴的可執行jar文件來完成我們的示例,我們可以在生產中運行它。 可執行jar(有時稱為“fat jar”)是包含已被編譯的代碼以及需要的全部依賴jar的歸檔。

要創建可執行jar,我們需要將spring-boot-maven-plugin添加到我們的pom.xml中。 為此,請在依賴項部分下方插入以下行:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

接著在終端執行如下命令

mvn package

查看target目錄,則應該看到sping-boot-study-1.0-SNAPSHOT.jar。 該文件大小應為10 MB左右。 如果你想查看jar的內部,你可以使用jar tvf,如下所示:

jar tvf target/sping-boot-study-1.0-SNAPSHOT.jar

要運行該應用程序,請使用java -jar命令,如下所示:

java -jar target/sping-boot-study-1.0-SNAPSHOT.jar

和以前一樣,要退出應用程序,請按ctrl-c


Spring-boot使用MySQL訪問數據


創建數據庫

打開終端,例如在Linux/Mac 上,我們使用命令

$ sudo mysql --password

這以管理員身份連接到MySQLbash

  1. 創建一個新的數據庫
mysql> create database db_example; -- 創建新的數據庫
mysql> create user 'springuser'@'localhost' identified by 'ThePassword'; -- 創建一個用戶
mysql> grant all on db_example.* to 'springuser'@'localhost'; -- 對新創建的數據庫的所有權限給予新創建的用戶
  1. 查看創建的數據庫
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db_example         |
| mydatabase         |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
6 rows in set (0.00 sec)
  1. 查看新創建的user
mysql> SELECT User FROM mysql.user;
+---------------+
| User          |
+---------------+
| springuser    |
| mysql.session |
| mysql.sys     |
| root          |
+---------------+
4 rows in set (0.00 sec)

配置spring-boot
  1. 修改src/main/resources/application.yml文件
spring:
  jpa:
    hibernate:
      ddl-auto: update
  datasource:
    url: jdbc:mysql://localhost:3306/db_example
    username: springuser
    password: ThePassword

spring.jpa.hibernate.ddl-auto可以是noneupdatecreatecreate-drop,有關詳細信息,請參閱Hibernate文檔

  • none: 這是MySQL的默認值,不會更改數據表結構。
  • update: Hibernate根據給定的實體結構更改數據表結構。
  • create 每次創建數據表,但在關閉時不會刪除數據表。
  • create-drop 創建數據表,然后在SessionFactory關閉時刪除它。

我們這里以create開頭,因為我們還沒有數據表結構。 第一次運行后,我們可以根據程序要求將其切換為updatenone。 如果要對數據表結構進行一些更改,請使用update

在數據庫處于生產狀態后,您可以使用none并從連接到Spring應用程序的MySQL用戶撤消所有權限,然后只給他SELECTUPDATEINSERTDELETE,這是一種很好的安全做法。
本指南最后詳細介紹了這一點。

  1. pom.xml添加如下依賴
        <!--提供了spring boot java持久化API-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <!--提供了操作mysql的依賴-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

創建 @Entity 模型

src/main/java/hello/User.java

package com.sunmi.bean;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;


@Entity // 這告訴Hibernate從這個類中創建一個表
@Data //省去get、set 等方法的編寫
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;

    private String name;

    private String email;

}

Hibernate將把帶有@Entity注解的實體類自動轉換為數據庫表的結構。


創建操作數據表的接口
package com.sunmi.repository;

import com.sunmi.bean.User;
import org.springframework.data.repository.CrudRepository;

public interface UserRepository extends CrudRepository<User, Integer> {
}

spring將會自動創建一個實現了 UserRepository 接口的 bean,包括CRUD等接口。

創建控制器
package com.sunmi.controller;

import com.sunmi.bean.User;
import com.sunmi.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(path = "/demo") // 這意味著訪問url以/demo開始
public class MainController {

    //這意味著spring會自動生成userRepository bean對象并注入,我們用這個對象來和mysql交互
    @Autowired
    private UserRepository userRepository;


    @PostMapping(path = "/add")
    public String addNewUser(@RequestBody User user) {
        userRepository.save(user);
        return "Saved";
    }

    @GetMapping(path = "/add2")
    public String addNewUser(String name
            , @RequestParam String email) {
        User user = new User();
        user.setName(name);
        user.setEmail(email);
        userRepository.save(user);
        return "Saved2";
    }



    @GetMapping(path = "/all")
    public Iterable<User> getAllUsers() {
        // 返回所有的用戶
        return userRepository.findAll();
    }

    @GetMapping(path = "/delete")
    public String delete(@RequestParam Integer id) {
        userRepository.deleteById(id);
        return "ok";
    }

    @GetMapping(path = "/find-by-id")
    public Optional<User> find(@RequestParam Integer id) {
        return userRepository.findById(id);
    }

}

上面的示例沒有明確指定GETPUTPOST等,因為@GetMapping@RequestMapping(method = GET)的快捷方式。 @RequestMapping默認映射所有HTTP操作。 使用@RequestMapping(method = GET)或其他快捷方式注解來限制映射。


測試我們的服務
  1. 添加一個user對象
$ curl 'http://localhost:8080/demo/add2?name=First&email=someemail@someemailprovider.com'

響應應該如下

Saved
  1. 查詢所有的user
$ curl 'http://localhost:8080/demo/all'

響應應該如下

[{"id":1,"name":"First","email":"someemail@someemailprovider.com"}]
  1. 更新用戶通過id
$ curl --request POST --header "Content-Type: application/json" http://localhost:8080/demo/add --data '{"id":1,"name":"Test","email":"someemail@someemailprovider.com"}'
Saved
  1. 查詢用戶通過id
$ curl 'http://localhost:8080/demo/find-by-id?id=1'
{"id":1,"name":"Test","email":"someemail@someemailprovider.com"}
  1. 刪除用戶通過id
$ curl 'http://localhost:8080/demo/delete?id=1'
"ok"
$ curl 'http://localhost:8080/demo/find-by-id?id=1'
null
  1. 你可能注意到對于add2接口,其第二個參數帶有@RequestParam注解,這表明來自客戶端的請求必須包含該字段。
$ curl 'http://localhost:8080/demo/add2?name=First'

你將得到如下錯誤

{"timestamp":"2019-03-22T04:49:29.239+0000","status":400,"error":"Bad Request","message":"Required String parameter 'email' is not present","path":"/demo/add2"}>

如果只指定了email字段

$ curl 'http://localhost:8080/demo/add2?email=someemail@someemailprovider.com'
Saved
$ curl 'http://localhost:8080/demo/all'
[{"id":1,"name":"First","email":"someemail@someemailprovider.com"}, 
{"id":2,"name":null,"email":"someemail@someemailprovider.com"}]
  1. 簡化服務端的編碼

當一個接口的參數過多時,我們可以通過@RequestBody注解,將這些參數組合成一個bean對象,客戶端訪問只需要傳遞一個json對象(其中的字段是可選的),服務端接收到請求后會自動將json對象系列化為bean

訪問此接口,并傳遞json對象

$ curl --request POST --header "Content-Type: application/json" http://localhost:8080/demo/add --data '{"name":"Second","email":"someemail@someemailprovider.com"}'
Saved
$ curl 'http://localhost:8080/demo/all'
[{"id":1,"name":"First","email":"someemail@someemailprovider.com"}, 
{"id":2,"name":null,"email":"someemail@someemailprovider.com"},
{"id":3,"name":Second,"email":"someemail@someemailprovider.com"}]
進行一些安全性更改

現在,當您處于生產環境中時,可能會遇到SQL注入攻擊。 黑客可能會注入DROP TABLE或任何其他破壞性SQL命令。 因此,作為安全實踐,在將應用程序公開給用戶之前,請對數據庫進行更改。

mysql> revoke all on db_example.* from 'springuser'@'localhost';

這將撤消與Spring應用程序關聯的用戶的所有權限。 現在Spring應用程序無法在數據庫中執行任何操作。 我們不希望如此。

mysql> grant select, insert, delete, update on db_example.* to 'springuser'@'localhost';

這為Spring應用程序提供了僅更改數據庫數據而不是數據表結構所需的權限。
并修改src/main/resources/application.yml文件

spring.jpa.hibernate.ddl-auto=none

而不是第一次運行時用的create

如果要對數據庫進行更改,請重新授予權限,將spring.jpa.hibernate.ddl-auto更改為update,然后重新運行應用程序,然后再重新授予權限,并將spring.jpa.hibernate.ddl-auto改為none。 或者,更好的是,使用專用的遷移工具,如FlywayLiquibase


響應式的方式訪問 Redis數據

待更新...

參考文檔
https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started-first-application.html
https://spring.io/guides/gs/spring-boot/#scratch
https://spring.io/guides/gs/accessing-data-mysql/
https://www.linuxprobe.com/mysql-show-all-users.html
https://blog.csdn.net/mccand1234/article/details/53456411
https://stackoverflow.com/questions/7172784/how-to-post-json-data-with-curl-from-terminal-commandline-to-test-spring-rest
https://github.com/spring-guides/gs-accessing-data-mysql/blob/master/complete/pom.xml


更多spring-boot技術資料
`

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容