前言
本萌新從今天開始進入對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
返回結果完全一致。