天天看點

spring-cloud之服務提供者和服務消費者

        springcloud是目前比較成熟的微服務的完整方案,所謂微服務就是基于SOA基礎之上,将服務進一步拆分,使得粒度更細化。比如原有的服務可能包含多個功能子產品,而微服務則是每個服務代表一個功能。由于粒度細化,那麼會涉及到服務之間的互相調用,那麼就涉及到服務提供者和服務消費者。所謂服務提供者就是表示該服務提供給其他服務調用,服務消費者則是調用其他服務的服務,每個服務既可以是服務提供者又可以是服務消費者。本文通過一個簡單的例子來說明服務提供者和服務消費者的關系,為了更加明顯,本文消費者調用的方式采用寫死的形式。

1.服務提供者---學生微服務

        作為服務提供者,就跟普通的springboot項目一緻,通過controller層的REST風格的http接口對外提供調用。本文介紹的服務提供者是一個學生基本資訊的微服務。首先還是通過IDEA上建立基于Maven管理的spring inittializr的項目,然後選擇相應的依賴。

1.1 pom檔案

<?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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.carson</groupId>
    <artifactId>microservice-student</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>microservice-student</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
           

1.2entity包中的Student類

        Student類作為實體類,就是與存入jpa資料庫的每條記錄映射的對象,具體如下:

import javax.persistence.*;

/**
 * ClassName Student
 *建立學生實體類
 * @author carson
 * @description
 * @Version V1.0
 * @createTime 2019-09-01 20:06
 */
@Entity
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long studentid;

    @Column
    private String studentname;

    @Column
    private String grade;

    @Column
    private Integer age;

    @Column
    private String sex;

    public Long getStudentid() {
        return studentid;
    }

    public void setStudentid(Long studentid) {
        this.studentid = studentid;
    }

    public String getStudentname() {
        return studentname;
    }

    public void setStudentname(String studentname) {
        this.studentname = studentname;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}
           

1.3 dao層的StudentRepository類

import com.carson.microservicestudent.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * InterfaceName StudentRepository
 *spring JPA操作的dao操作類
 * @author carson
 * @description
 * @Version V1.0
 * @createTime 2019-09-01 20:11
 */
public interface StudentRepository extends JpaRepository<Student,Long> {
}
           

       該類實作了JpaRepository接口,用于對jpa資料庫操作,其中JpaRepository接口中對jpa資料庫操作的功能比較強大。是以,隻要構造一個實作JpaRepository接口的StudentRepository類來對student資料庫進行操作。

1.4 controller層的StudentController類

        StudentController類是學生服務對外調用的http接口。

import com.carson.microservicestudent.dao.StudentRepository;
import com.carson.microservicestudent.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


/**
 * ClassName StudentController
 *
 * @author carson
 * @description
 * @Version V1.0
 * @createTime 2019-09-01 20:23
 */
@RestController
public class StudentController {

    @Autowired
    private StudentRepository studentRepository;

    @RequestMapping(value = "/{studentid}",method = RequestMethod.GET)
    public Student findById(@PathVariable Long studentid){
        Student student = this.studentRepository.findById(studentid).get();
        return student;
    }
}
           

1.5 application.yaml檔案

server:
  port: 8081

spring:
  jpa:
    generate-ddl: false
    show-sql: true
    hibernate:
      ddl-auto: none
    datasource:
      platform: h2
      schema: classpath:schema.sql
      data: classpath:data.sql
logging:
  level:
    root: INFO
    org.hibernate: INFO
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
           

1.6 sql檔案

資料表建立的sal:

drop table student if exists ;
create table student(studentid bigint generated by default as identity,studentname varchar(40),grade varchar(20),age int(3),sex varchar(20),primary key(studentid))
           

表中資料初始化的sql:

insert into student (studentid,studentname,grade,age,sex) values (10001,'Carson','third',25,'male');
insert into student (studentid,studentname,grade,age,sex) values (10002,'Amy','sixth',25,'female');
insert into student (studentid,studentname,grade,age,sex) values (10003,'Bob','five',25,'male');
insert into student (studentid,studentname,grade,age,sex) values (10004,'Cuz','second',25,'male');
insert into student (studentid,studentname,grade,age,sex) values (10005,'Max','fourth',25,'female');
           

        以上schema.sql建立了student表,該表中的字段以及類型都是與Student實體類一一對應的。data.sql則是在student表中插入了幾條資料進行初始化。

1.7 服務啟動類

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MicroserviceStudentApplication {

    public static void main(String[] args) {
        SpringApplication.run(MicroserviceStudentApplication.class, args);
    }

}
           

1.8 啟動服務

在浏覽器中輸入http://localhost:8081/10001 檢視運作結果,結果運作如下:

spring-cloud之服務提供者和服務消費者

2.服務消費者---老師服務

        比如有個服務是老師服務,該服務中如果需要擷取學生的資訊,則會需要調用學生服務,是以這裡老師服務就是服務消費者。

2.1 Student類

該類在服務提供者中需要作為實體類與資料庫進行映射,而在這不需要映射,而是對資料庫操作的結果進行1封裝,是以不需要與之前相同的注釋。

/**
 * ClassName Student
 *此類作為一個pojo類,作為服務消費者對資料庫操作時的記錄所對應的對象
 * @author carson
 * @description
 * @Version V1.0
 * @createTime 2019-09-01 23:05
 */
public class Student {

    private Long studentid;
    private String studentname;
    private String grade;
    private Integer age;
    private String sex;
    public Long getStudentid() {
        return studentid;
    }

    public void setStudentid(Long studentid) {
        this.studentid = studentid;
    }

    public String getStudentname() {
        return studentname;
    }

    public void setStudentname(String studentname) {
        this.studentname = studentname;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}
           

2.2 TeacherController 類

該類用RestTemplate請求服務提供者的API,并且需要在啟動類對RestTemplate進行執行個體化。然後在Controller中的接口中通過RestTemplate進行對Student服務的調用。具體如下:

import com.carson.microserviceteacher.pojo.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * ClassName TeacherController
 * 老師controller類
 * @author carson
 * @description
 * @Version V1.0
 * @createTime 2019-09-01 23:05
 */
@RestController
public class TeacherController {

    @Autowired
    private RestTemplate restTemplate;


    @RequestMapping(value = "/student/{studentid}",method = RequestMethod.GET)
    public Student findStudentInfo(@PathVariable Long studentid){
        return this.restTemplate.getForObject("http://localhost:8081/"+studentid,Student.class);
    }

}
           

2.3 啟動類

上述controller類中用到了RestTemplate,是以在啟動類中需要執行個體化,具體如下:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class MicroserviceTeacherApplication {

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(MicroserviceTeacherApplication.class, args);
    }

}
           

2.4 application.yaml

server:
  port: 8082
           

2.5 啟動服務

    啟動服務後,浏覽器中輸入:http://localhost:8082/student/10001可以看到如下結果:

spring-cloud之服務提供者和服務消費者

3.小結

    老師服務通過RestTemplate進行對學生服務的調用進行操作student資料庫,進而擷取學生的資訊。這就是簡單的服務消費者與服務提供者之間的關系。但我們也會發現,這個例子中通過寫死的形式調用服務可能會使耦合度過高,如果學生服務換了url,則需要對老師服務的代碼進行修改再釋出,這不便于後期維護。這在後面會講到springcloud生态中一些功能來降低寫死帶來的耦合度問題。

繼續閱讀