SpringCloud初體驗之REST服務與消費

前言

本萌新從今天開始進入對springcloud的學習階段了,說實話之前剛學完Java的時候對編程信心十分的匱乏,學的Java基礎稀裏糊塗,說做網頁吧連登陸註冊增刪改查都寫不出來。試圖從基礎的spring開始學,但是那複雜的配置讓我望而卻步。於是從簡化配置的springboot開始學習了,最開始學習的時候只是零散的學習,沒有方向,只能做做簡單的登陸啊註冊啊(還十分的困難)。在bilibili上看了很多springboot系列的教程,可是自己的技術始終沒有進步,原地徘徊三四個月終於決定突破這層阻礙,直接上項目。沒錯,就是在基礎打得稀裏糊塗的情況下,直接做項目。我把以前用Python的flask框架寫的小程序用springboot重新寫了一遍,還在之前的基礎上加了幾個功能,寫完之後,覺得基本的crud能力完全打通,還通過這個項目學到了很多,包括小程序,這也對我學習vue奠定了一丟丟丟的基礎。

後來進階買了松哥(江南一點雨)的springboot+vue寫的vhr項目,說實話我跟着他的視頻一點點的敲一點點的吸收,現在做基本的前後端開發沒什麼問題,但是這個項目做完也同樣發現了自己好多的知識盲點,所以學無止境嘛,一邊掃盲一邊拓展。總不能原地踏步是不是?

我也跟很多有點Java基礎的兄弟聊過天,他們對自己web端學習的方法不明確,我自己一開始學的時候也走了很多彎路。現在想來我覺得學習編程首要的還是要打好自己的基礎,每天的學習最好能寫個博客記錄下來,這樣自己手機端也能查看,時時勤拂拭,莫使惹塵該嘛。學完之後一定要寫個不大不小的項目,作爲融會貫通。可能你會說,學的時候沒問題,一上手項目就腦子一片空白啥也不會了。肯定的呀,寫項目就是補你的空白的。寫好項目,這樣你再回頭看,你就會對自己所學出有理解,這個時候想向上進階,我建議去找網上高級的進階資料或者買視頻看,關於買什麼樣的視頻,當然是那種中大型的前後端分離的項目,最好能帶一些自己還沒學但是想學的技術,比如我買的就是松哥的微人事項目視頻,因爲他用了vue來做前端,而vue又是現在最主流的前端開發框架,所以成了我的首選。這樣一邊學習一邊總結,後面的就是看能不能在他的基礎上對項目進行改造,不要求你會原創,能在人的基礎上進行加功能改造功能,就足以說明自己能力又上升了一個檔次。

好了,下面就看現在比較流行的springcloud框架,關於springcloud的介紹我這裏就不做介紹了,很多博客都有,我這不贅述。直接看乾貨吧。

創建聚合工程

添加父工程依賴

<?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.study</groupId>
    <artifactId>springcloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>SpringCloud-API</module>
        <module>SpringCloud-Provider</module>
        <module>SpringCloud-Consumer</module>
    </modules>
    <packaging>pom</packaging>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.4.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.10</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.16</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.2.3</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

創建API工程

我這裏用了lombok插件,你們沒有插件的就setget。
然後這裏是給其他工程提供實體類的,所以需要實現序列化

package com.study.cloud.bean;

import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * @description:
 * 1.實體類必須實現序列化
 * @author: Leo
 * @createDate: 2020/2/8
 * @version: 1.0
 */
@Data
//@Accessors(chain = true)//開啓鏈式寫法
public class Book implements Serializable
{
    private Integer bookID;
    private String bookName;
    private Integer bookCounts;
    private String detail;
    private String db_source;

    public Book()
    {
    }

    public Book(String bookName, Integer bookCounts, String detail, String db_source)
    {
        this.bookName = bookName;
        this.bookCounts = bookCounts;
        this.detail = detail;
        this.db_source = db_source;
    }
}

創建服務者工程

添加依賴

<?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">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.study</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>provider</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.study</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>

</project>

yml配置文件

server:
  port: 8001
mybatis:
  type-aliases-package: com.study.cloud.bean
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml

#服務提供者
spring:
  application:
    name: springcloud-provider
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/leotemp?useUnicode=true&useSSL=false&characterEncodig=utf-8
    username: root
    password: 123456

mybatis配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.cloud.mapper.BookMapper">
    <insert id="addBook" parameterType="com.study.cloud.bean.Book">
        insert into books(bookName,bookCounts,detail,db_source)
        values (#{bookName},
        #{bookCounts},
        #{detail},
        #{db_source})
    </insert>
    <select id="queryById" parameterType="java.lang.Integer" resultType="com.study.cloud.bean.Book">
        select * from books where bookID=#{bookID};
    </select>
    <select id="queryAll" resultType="com.study.cloud.bean.Book">
        select * from books
    </select>
</mapper>

mapper層

package com.study.cloud.mapper;

import com.study.cloud.bean.Book;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @description:
 * @author: Leo
 * @createDate: 2020/2/10
 * @version: 1.0
 */
@Mapper
@Repository
public interface BookMapper
{
    boolean addBook(Book book);
    Book queryById(Integer bookID);
    List<Book> queryAll();
}

service層

package com.study.cloud.service;

import com.study.cloud.bean.Book;

import java.util.List;

public interface BookService
{
    boolean addBook(Book book);

    Book queryById(Integer bookID);

    List<Book> queryAll();
}

實現類

package com.study.cloud.service;

import com.study.cloud.bean.Book;
import com.study.cloud.mapper.BookMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @description:
 * @author: Leo
 * @createDate: 2020/2/10
 * @version: 1.0
 */
@Service
public class BookServiceImp implements BookService
{
    @Autowired
    BookMapper bookMapper;

    public boolean addBook(Book book)
    {
        return bookMapper.addBook(book);
    }

    public Book queryById(Integer bookID)
    {
        return bookMapper.queryById(bookID);
    }

    public List<Book> queryAll()
    {
        return bookMapper.queryAll();
    }
}

控制層

package com.study.cloud.controller;

import com.study.cloud.bean.Book;
import com.study.cloud.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @description:
 * @author: Leo
 * @createDate: 2020/2/10
 * @version: 1.0
 */
@RestController
@RequestMapping("/book/provide")
public class BookController
{
    @Autowired
    BookService bookService;

    @PostMapping("/")
    public boolean addBook(@RequestBody Book book)
    {
        return bookService.addBook(book);
    }

    @GetMapping("/{bookID}")
    public Book queryById(@PathVariable("bookID") Integer bookID)
    {
        return bookService.queryById(bookID);
    }

    @GetMapping("/")
    public List<Book> queryAll()
    {
        return bookService.queryAll();
    }
}

最後定義啓動類
上面就是最基本的數據的添加和查詢。但是現在我們又要創建一個工程,這個工程是我們的消費者。

創建消費者模塊

添加依賴

<?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">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.study</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>consumer</artifactId>
<!--需要實體類和web-->
    <dependencies>
        <dependency>
            <groupId>com.study</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

二 修改端口,不要和之前那個工程一樣 建議80
三、springcloud調用遠程服務的話可以通過RestTemplate方法
第一步,要把RestTemplate註冊到bean裏

首先解釋以下@configuration,它的主要作用就是在spring容器啓動的時候,初始化IOC,使用了這個註解,那麼該類就會在spring啓動的時候,把@Bean註解標識的類進行依賴注入。@Bean理解的話,就好比在配置文件中配置.接下來就是在restTemplate的構造方法中添加httpRequest的工廠,使用連接池來優化http通信,默認使用長連接時間爲30秒,再設置路由讓http連接定向到指定的IP,然後設置併發數。再就是設置請求配置的超時時間,爲了防止請求時間過長而引起資源的過渡浪費。如果在超過設置的timeout還沒有數據返回,就直接斷開連接。headers是添加默認的請求頭,這裏設置了傳送的格式爲json,語言爲中-英等等屬性。HttpClientBuilder.create設置請求頭到HttpClient,然後在設置保持的時間,重試的次數,注入給httpClient進行封裝。

package com.study.cloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @description:
 * @author: Leo
 * @createDate: 2020/2/10
 * @version: 1.0
 */
@Configuration //這是springboot中的註解,他的作用相當於spring中的applicationContext.xml
public class ConfigBean
{
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

RestTemplate

說明:
現在restful接口越來越廣泛,而如今很多接口摒棄了傳統的配置複雜的webService開發模式,在java領域只需要很簡單的springMvc就可以聲明爲一個控制器,再加上service層,就可以直接操作數據庫成爲一個靈活的接口。而我們請求接口的次數也會越來越多(最近我在和一個工具對接的時候,對方公司提供的接口全部由我們主動去調用),一般我們請求接口,都採用Apache Httpclient工具,這個工具穩定,既可以建立長連接,保持不錯的性能,而它唯一的不足就是使用起來麻煩多變,並且要很多層判斷處理,今天我要談的就是spring對httpClient的再封裝工具類,restTemplate,採用模板模式抽象出來的高效工具。有點類似於jdbcTemplate,今天我們就來一步步揭開它的使用方法

內置方法
在這裏插入圖片描述

客戶端調用服務端

package com.study.cloud.controller;

import com.study.cloud.bean.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * @description: 這裏我是消費者,我在消費的時候需要自己有service層嗎?我覺得顯然是否定,那麼問題來了,如果
 * controller沒有service他該如何去調用service呢?
 * 通過RestTemplate
 * @author: Leo
 * @createDate: 2020/2/10
 * @version: 1.0
 */
@RestController
public class BookConSumController
{
    @Autowired
    RestTemplate restTemplate;//提供多種便捷訪問遠程http服務的方法,是一個簡單的restful服務模板

    private static final String REST_URL_PREFIX="http://localhost:8001/book/provide";
    //public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
    // throws RestClientException
    @RequestMapping("/book/consumer/post")
    public boolean addBook(Book book){
        return restTemplate.postForObject(REST_URL_PREFIX+"/",book,Boolean.class);
    }
    @RequestMapping("/book/consumer/get/{bookID}")
    public Book getBookById(@PathVariable("bookID") Integer bookID){
        return restTemplate.getForObject(REST_URL_PREFIX+"/"+bookID,Book.class);
    }
    @RequestMapping("/book/consumer/get")
    public List<Book> getAllBook(){
        return restTemplate.getForObject(REST_URL_PREFIX+"/",List.class);
    }

}

這裏調用的是**ForObject,他需要的參數是服務端的請求路徑、參數、當前對象的類型

測試效果

服務端本地測試
http://localhost:8001/book/provide/
在這裏插入圖片描述
請求完全沒毛病!
再看消費者端的調用
http://localhost/book/consumer/get
在這裏插入圖片描述
返回結果完全一致。

Author By 朝花不遲暮

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章