環(huán)境準(zhǔn)備
- jdk(1.8)
- Maven (也可以采用gridle,這里采用mavne)
- IDEA ULTIMATE 2018.2.7(idea中配置moven 和jdk),也可以采用Springboot官方推薦的sts開發(fā)ide,是eclpise的定制版本

其他知識(shí)
HTTP請(qǐng)求頭之User-Agent http://www.itdecent.cn/p/c5cf6a1967d1
簡(jiǎn)單應(yīng)用
- 編寫REST程序
- 運(yùn)行Spring Boot應(yīng)用
- 使用Http請(qǐng)求工具:PostMan
場(chǎng)景說明
- 定義用戶模型,包括屬性:用戶ID和名稱(注:服務(wù)端保存用戶數(shù)據(jù)庫(kù),采用Map方式模擬存儲(chǔ))
- 客戶端發(fā)送Post請(qǐng)求,創(chuàng)建用戶(Web MVC)
- 客戶端發(fā)送GET請(qǐng)求,查詢所以用戶(Web Flux)
【Tip】Spring WebFlux應(yīng)用程序并不嚴(yán)格依賴于Servlet API,因此它們不能作為war文件部署,也不能使用該src/main/webapp目錄。
第一步:start.spring.io 構(gòu)建應(yīng)用,并下載
https://start.spring.io/


第2步:用idea導(dǎo)入Gradle項(xiàng)目(start.spring.io 構(gòu)建的zip,解壓)
第一步start.spring.io 構(gòu)建的zip,解壓到指定目錄后,用idea導(dǎo)入


導(dǎo)入過程碰到的問題及解決辦法:

使用idea導(dǎo)入springboot項(xiàng)目maven報(bào)錯(cuò)Non-managed pom.xml file found
https://blog.csdn.net/q89757316/article/details/80896382
IDEA中Spring Boot的@SpringBootApplication無法引入的問題
https://blog.csdn.net/weixin_41942804/article/details/80044101
第3步:編寫代碼
項(xiàng)目的結(jié)構(gòu)

3-1 創(chuàng)建用戶模型:User
/**
* 用戶模型
*
*/
public class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
創(chuàng)建用戶倉(cāng)儲(chǔ):UserRepostory
package com.younghare.springBoothelloworld.repository;
import org.springframework.stereotype.Repository;
import com.younghare.springBoothelloworld.domain.User;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* {@link User} {@link Repository}
*/
@Repository
public class UserRepostory {
/**
* 采用內(nèi)存型存儲(chǔ)方式 -> Map
*/
private final ConcurrentMap<Integer,User> repository = new ConcurrentHashMap<>();
private final static AtomicInteger idGenerator =
new AtomicInteger();
/**
* 保存用戶對(duì)象
* @param user {@link User} 對(duì)象
* @return 如果保存成功,返回<code>true</code>,否則返回<code>false</code>
*/
public boolean save(User user){
boolean success = false;
Integer id = idGenerator.incrementAndGet();
//repository.put(id,user);
user.setId(id);
return repository.put(id,user) == null;
}
public Collection<User> findAll(){
return repository.values();
}
}
3-3創(chuàng)建用戶控制器:UserController
package com.younghare.springBoothelloworld.controller;
import com.younghare.springBoothelloworld.domain.User;
import com.younghare.springBoothelloworld.repository.UserRepostory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController //表示是一個(gè)Rest接口
public class UserController {
private final UserRepostory userRepostory; //沒有初始化,這里采用構(gòu)造器注入的方式
@Autowired
public UserController(UserRepostory userRepostory){
this.userRepostory = userRepostory;
}
@PostMapping("/person/save")
public User save(@RequestParam String name){
User user = new User();
user.setName(name);
if (userRepostory.save(user)){
System.out.printf("用戶對(duì)象:%s 保存成功\n",user);
}
return user;
}
}
第4步:用idea進(jìn)行debug運(yùn)行、調(diào)試
可以看到運(yùn)行的行程pid


看到webapi的接口及端口號(hào)


第5步:用Postman發(fā)送Post請(qǐng)求---添加用戶--添加的用戶存儲(chǔ)在Map內(nèi)存中
localhost:8080/person/save
在postman中添加地址及post參數(shù)

post添加用戶請(qǐng)求,添加的用戶存儲(chǔ)在Map內(nèi)存中
第6步:編寫路由器函數(shù) 配置:RouteFunctionConfiguration
/**
* 路由器函數(shù) 配置
*/
@Configuration
public class RouteFunctionConfiguration {
/**
* Servlet
* 請(qǐng)求接口:ServletRequet 或者 HttpServletRequest
* 響應(yīng)接口:ServletResponse 或者 HttpServletResponse
*
* Spring 5.0重新定義了服務(wù)請(qǐng)求和響應(yīng)接口
* 請(qǐng)求接口 :ServerRequest
* 響應(yīng)接口 :ServerResponse
* 即可支持Servlet規(guī)范,也可以支持自定義,比如Netty (Web Server)
*
* 以本例:
* 定義GET請(qǐng)求,并且返回所以的用戶對(duì)象 URI:/person/find/all
*
* Flux 是0--n個(gè)對(duì)象集合
* Mono 是0--1個(gè)對(duì)象集合
* Reactive 中的Flux或Mone它是異步處理(非阻塞式)
* 集合對(duì)象基本上是同步處理(阻塞式)
*
* Flux或者M(jìn)ono 都是Publisher
*/
@Bean
@Autowired //方法參數(shù)注入
public RouterFunction<ServerResponse> personFindAll(UserRepostory userRepostory){
return RouterFunctions.route(RequestPredicates.GET("/person/find/all"),
request -> {
//返回所有的用戶對(duì)象
Collection<User> users = userRepostory.findAll();
Mono<ServerResponse> response = null;
Flux<User> userFlux =Flux.fromIterable(users); //把Collection對(duì)象轉(zhuǎn)換為Flux對(duì)象
return ServerResponse.ok().body(userFlux,User.class);
}
);
}
}
關(guān)于Spring WebFlux) 參考官方文檔
https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html

第7步:重新debug模式運(yùn)行項(xiàng)目

安裝前面的Post方式提交多次添加用戶請(qǐng)求,讓Map中有多個(gè)用戶數(shù)據(jù)
用Postman發(fā)送查詢
localhost:8080/person/find/all


Spring boot構(gòu)建項(xiàng)目的方式
圖形化方式(http://start.spring.io/) --上面介紹的是圖形化方式
命令行方式(Maven)
命令行方式(Maven)構(gòu)建spring boot項(xiàng)目
maven命令方式--第一步 ---了解基礎(chǔ)知識(shí)
#apache 的Maven project主頁(yè)
http://maven.apache.org/archetype/
http://maven.apache.org/archetype/maven-archetype-plugin/generate-mojo.html
#必要參數(shù)Required Parameters
#interactiveMode 交互模式,提示一步步執(zhí)行
#可選參數(shù)Optional Parameters(幫助我們構(gòu)建相應(yīng)的項(xiàng)目)


例子(注-D是java命令行模式傳遞參數(shù)的表示):mvn archetype:generate -DinteractiveMode=false -DgroupId="com.younghare" -DartifactId=czgFirs-app-by-moven -Dversion=1.0.0-SNAPSHOT
這個(gè)命令生成的有點(diǎn)慢,需要到manen倉(cāng)庫(kù)上下載不少東東(依賴包),有時(shí)會(huì)失敗,做幾次能成功
奇怪地址是不是變了:https://projects.spring.io/spring-boot
maven命令方式-第2步--生成工程
cd D:\czg\czgIdea
d:
mvn archetype:generate -DinteractiveMode=false -DgroupId="com.younghare" -DartifactId=czgFirs-app-by-moven -Dversion=1.0.0-SNAPSHOT



注:用mvn命令方式生成項(xiàng)目有時(shí)會(huì)失敗,而且可能會(huì)比較慢,可多試幾次。
maven命令方式-第3步--用idea工具打開工程,并修改pom.xml文件
#添加依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.9.BUILD-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.younghare</groupId>
...
...
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<dependencies>
<!-- junit 的寫測(cè)試不適合spring boot ,spring boot 的測(cè)試用:https://www.baeldung.com/spring-boot-starters-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
maven命令方式-第4步--修改app.java及創(chuàng)建一個(gè)HelloWorldController.java
HelloWorldController.java
@RestController
public class HelloWorldController {
@GetMapping("")
public String index(){
return "Hello ,World";
}
}
App.java修改如下
@SpringBootApplication //注解是一個(gè)SpringBoot的應(yīng)用
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
SpringApplication.run(App.class, args); //第一參數(shù)就是App本身,第二個(gè)參數(shù)是傳遞的參數(shù)
}
}
maven命令方式-第5步--運(yùn)行



maven命令方式-第6步--用Postman測(cè)試看看結(jié)果

其他查閱資料
Flux簡(jiǎn)介-Flux是Facebook用于構(gòu)建客戶端Web應(yīng)用程序的一個(gè)系統(tǒng)架構(gòu)
Spring Webflux
Spring WebFlux快速上手——響應(yīng)式Spring的道法術(shù)器
Springboot2.0中webflux到底優(yōu)秀在哪里--優(yōu)秀
SpringBoot 2.0 Webflux 介紹 和Demo示例
spring5.0 函數(shù)式web框架 webflux
Flux 會(huì)取代 Web MVC,或可不再基于 Servlet 容器了?
java!!Spring RestTemplate 極簡(jiǎn)入門 --今日頭條
IntelliJ IDEA使用Alibaba Cloud Toolkit插件自動(dòng)發(fā)布Web程序