天天看点

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生态中一些功能来降低硬编码带来的耦合度问题。

继续阅读