SpringCloud簡介
SpringCloud是一系列框架的有序集合,它利用SpringBoot的開發便利性巧妙地簡化了分佈式系統基礎設施的開發,如服務發現註冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,都可以用SpringBoot的開發風格做到一鍵啓動和部署。SpringCloud並沒有重複製造輪子,它只是將目前各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,通過SpringBoot風格進行再封裝屏,蔽掉了複雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分佈式系統開發工具包。
詳細介紹: https://baike.so.com/doc/25751000-26884657.html
配套參考資料:
springcloud項目官方主頁:https://projects.spring.io/spring-cloud
springcloud中文網(有很詳細的翻譯文檔):https://springcloud.cc
springcloud中文論壇:http://springcloud.cn
SpringCloud入門案例(使用的是jpa)
使用SpringBoot開發項目的好處在於能夠快速的開發單體項目,很多框架整合無需配置,極大的提高了開發效率。使用SpringBoot開發項目依然屬於傳統的開發模式,因爲所有的代碼都寫在一個工程內。
Mvc模式相信已經被大家所熟知,Mvc模式是爲了使代碼層次分明,便於維護,提高代碼的健壯性;當項目過於臃腫的話,MVC模式的項目依然難於維護。而SpringCloud作爲分佈式服務技術的代表,其實就是對MVC模式的一種延伸。將整個項目的model層、dao層、service層、controller層等等進行拆分,使其獨立出來成爲一個單獨的項目,解決由於項目過於臃腫不便於維護所帶來的一系列問題。
最簡單的微服務架構會有四個工程:
父工程:microservice(主要就是一個pom,用於管理module,以及管理依賴,規範所有jar包版本等)
通用模塊(M):microservice-common(主要是放一些其他項目公用的東西,比如實體類,工具類等等)
服務提供者(C):microservice-student-provider-1001(用於操作數據庫並且被瀏覽器所訪問)
服務消費者(C):microservice-student-consumer-80(用於通過restful api來調用服務提供者的接口)
微服務架構注意點:
1、SpringBoot、SpringCloud版本在父工程定義
2、由於通用模塊無需操作數據庫,但SpringBoot項目啓動是默認會讀取數據庫,所以得在啓動類添加以下註解@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
3、分佈式jpa需要在啓動類上添加@EntityScan("com.ue.entity")跟@EnableJpaRepositories("com.ue.repository")
4、消費者需要添加配置類獲取org.springframework.web.client.RestTemplate,因爲SpringCloud底層是通過RestTemplate來調用服務提供者提供的服務的
傳統項目拆分成微服務架構圖如下:
創建父工程(microservice)
父工程是一個maven項目,用一般創建方式即可,父工程的主要用途是鎖定pom依賴包版本。由於springcloud2.x停止更新,這裏我們採用穩定的低版本,配套的springboot版本爲1.x版本
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.ue</groupId>
<artifactId>microservice</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<druid.version>1.1.10</druid.version>
</properties>
<!--鎖定pom依賴jar包版本,但並不實際引用(即用於繼承)-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.13.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--連接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
創建通用模塊(microservice-common)
通用模塊主要存放實體類、工具包等被整個微服務框架所使用的代碼,創建一個簡單的springboot模塊即可,相關代碼如下
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.ue</groupId>
<artifactId>microservice</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>microservice-common</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
MicroserviceCommonApplication.java:
package com.ue;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class MicroserviceCommonApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceCommonApplication.class, args);
}
}
Student.java:
package com.ue.entity;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name = "t_springcloud_student")
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Integer id;
@Column(length = 50)
private String name;
@Column(length = 50)
private String grade;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
}
創建服務提供者(microservice-student-provider-1001)
創建一個簡單的springboot模塊,這裏需要操作數據庫並且被瀏覽器所訪問,故需要添加相關代碼如下
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.ue</groupId>
<artifactId>microservice</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>microservice-student-provider-1001</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- 修改後立即生效,熱部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>com.ue</groupId>
<artifactId>microservice-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
application.yml:
server:
port: 1001
context-path: /
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/demosite1?useUnicode=true&characterEncoding=utf8
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true
MicroserviceStudentProvider1001Application.java:
package com.ue;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
@EntityScan("com.ue.entity")
@EnableJpaRepositories("com.ue.repository")
public class MicroserviceStudentProvider1001Application {
public static void main(String[] args) {
SpringApplication.run(MicroserviceStudentProvider1001Application.class, args);
}
}
StudentRepository.java:
package com.ue.repository;
import com.ue.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface StudentRepository extends JpaRepository<Student, Integer>, JpaSpecificationExecutor<Student> {
}
StudentService.java:
package com.ue.service;
import com.ue.entity.Student;
import java.util.List;
/**
* 學生信息Service接口
* @author Administrator
*/
public interface StudentService {
/**
* 添加或者修改學生信息
* @param student
*/
public void save(Student student);
/**
* 根據id查找學生信息
* @param id
* @return
*/
public Student findById(Integer id);
/**
* 查詢學生信息
* @return
*/
public List<Student> list();
/**
* 根據id刪除學生信息
* @param id
*/
public void delete(Integer id);
}
StudentServiceImpl.java:
package com.ue.service.impl;
import java.util.List;
import javax.annotation.Resource;
import com.ue.entity.Student;
import com.ue.repository.StudentRepository;
import com.ue.service.StudentService;
import org.springframework.stereotype.Service;
/**
* 學生信息Service實現類
* @author Administrator
*/
@Service("studentService")
public class StudentServiceImpl implements StudentService {
@Resource
private StudentRepository studentRepository;
@Override
public void save(Student student) {
studentRepository.save(student);
}
@Override
public Student findById(Integer id) {
return studentRepository.findOne(id);
}
@Override
public List<Student> list() {
return studentRepository.findAll();
}
@Override
public void delete(Integer id) {
studentRepository.delete(id);
}
}
StudentProviderController.java:
package com.ue.controller;
import java.util.List;
import javax.annotation.Resource;
import com.ue.entity.Student;
import com.ue.service.StudentService;
import org.springframework.web.bind.annotation.*;
/**
* 服務提供者-學生信息控制器
* @author Administrator
*/
@RestController
@RequestMapping("/student")
public class StudentProviderController {
@Resource
private StudentService studentService;
/**
* 添加或者修改學生信息
* @param student
* @return
*/
@PostMapping(value="/save")
public boolean save(Student student){
try{
studentService.save(student);
return true;
}catch(Exception e){
return false;
}
}
/**
* 查詢學生信息
* @return
*/
@GetMapping(value="/list")
public List<Student> list(){
return studentService.list();
}
/**
* 根據id查詢學生信息
* @return
*/
@GetMapping(value="/get/{id}")
public Student get(@PathVariable("id") Integer id){
return studentService.findById(id);
}
/**
* 根據id刪除學生信息
* @return
*/
@GetMapping(value="/delete/{id}")
public boolean delete(@PathVariable("id") Integer id){
try{
studentService.delete(id);
return true;
}catch(Exception e){
return false;
}
}
}
創建服務消費者(microservice-student-consumer-80)
服務消費者主要是通過restful api來調用服務提供者的接口,故不需要操作數據庫,相關配置如下
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.ue</groupId>
<artifactId>microservice</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>microservice-student-consumer-80</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 修改後立即生效,熱部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>com.ue</groupId>
<artifactId>microservice-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
application.yml:
server:
port: 80
context-path: /
MicroserviceStudentConsumer80Application.java:
package com.ue;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class MicroserviceStudentConsumer80Application {
public static void main(String[] args) {
SpringApplication.run(MicroserviceStudentConsumer80Application.class, args);
}
}
SpringCloudConfig.java:
package com.ue.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* SpringCloud相關配置
* @author Administrator
*/
@Configuration
public class SpringCloudConfig {
/**
* 調用服務模版
* @return
*/
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
StudentConsumerController.java:
package com.ue.controller;
import java.util.List;
import javax.annotation.Resource;
import com.ue.entity.Student;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
/**
*
* @author Administrator
*
*/
@RestController
@RequestMapping("/student")
public class StudentConsumerController {
@Resource
private RestTemplate restTemplate;
/**
* 添加或者修改學生信息
* @param student
* @return
*/
@PostMapping(value="/save")
private boolean save(@RequestBody Student student){
return restTemplate.postForObject("http://localhost:1001/student/save", student, Boolean.class);
}
/**
* 查詢學生信息
* @return
*/
@GetMapping(value="/list")
public List<Student> list(){
return restTemplate.getForObject("http://localhost:1001/student/list", List.class);
}
/**
* 根據id查詢學生信息
* @return
*/
@GetMapping(value="/get/{id}")
public Student get(@PathVariable("id") Integer id){
return restTemplate.getForObject("http://localhost:1001/student/get/"+id, Student.class);
}
/**
* 根據id刪除學生信息
* @return
*/
@GetMapping(value="/delete/{id}")
public boolean delete(@PathVariable("id") Integer id){
try{
restTemplate.getForObject("http://localhost:1001/student/delete/"+id, Boolean.class);
return true;
}catch(Exception e){
return false;
}
}
}
測試時先啓動服務提供者再啓動服務消費者,部分測試結果如下:
注意:用postman測試新增接口的時候,服務提供端的實體參數前面要加上@RequestBody註解,否則會接收不到數據