Spring Boot 1第一個(gè)項(xiàng)目-helloWorld

環(huán)境準(zhǔn)備

  • jdk(1.8)
  • Maven (也可以采用gridle,這里采用mavne)
  • IDEA ULTIMATE 2018.2.7(idea中配置moven 和jdk),也可以采用Springboot官方推薦的sts開發(fā)ide,是eclpise的定制版本

idea配置導(dǎo)入源碼

其他知識(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/
spring boot 項(xiàng)目信息
spring boot 配置選項(xiàng)

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

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

idea 導(dǎo)入gradle項(xiàng)目
idea導(dǎo)入后的目錄結(jié)構(gòu)

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


idea導(dǎo)入spring boot 碰到問題

使用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)


項(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


idea 中debug運(yùn)行調(diào)試
log上看到的pid和任務(wù)管理器的pid一致

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

webapi的接口及端口號(hào)
日志上有看到是用Netty 服務(wù)的8080端口

第5步:用Postman發(fā)送Post請(qǐng)求---添加用戶--添加的用戶存儲(chǔ)在Map內(nèi)存中

localhost:8080/person/save

在postman中添加地址及post參數(shù)

Postman發(fā)送Post請(qǐng)求、及斷點(diǎn)情況

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
Spring -Web Flux的官網(wǎng)文檔

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

看到路由配置信息

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

localhost:8080/person/find/all
路由斷點(diǎn)情況
postman上看到的查詢結(jié)果

Spring boot構(gòu)建項(xiàng)目的方式


命令行方式(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)目)
image.png
spring boot maven 命令行的幫助

例子(注-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

image.png
mvn 手動(dòng)創(chuàng)建spring boot項(xiàng)目的成功
生成的spring boot項(xiàng)目

注:用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)行

運(yùn)行App

注意controller的映射情況
運(yùn)行效果

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

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程序

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容