SpringCloud學習記錄(一)第一個服務提供者與服務消費者

參考資料:《SpringCloud與Docker微服務架構實戰》

 

服務提供者:服務的被調用方(即:爲其他服務提供服務的服務)

服務消費者:服務的調用方(即:依賴其他服務的服務)

用戶購票時,向電影微服務發起一個購票請求,在進行購票的業務操作前,電影微服務需要調用用戶微服務的接口,查詢當前用戶的餘額是多少,是不是符合購票標準等。

在這個例子中,用戶微服務就是一個服務提供者,電影微服務則是一個服務消費者

圍繞該場景,先編寫一個用戶微服務,再編寫一個電影微服務

 

編寫一個服務提供者,該服務通過主鍵查詢用戶信息

再寫一個消費者,通過調用提供者來查詢用戶

原書中使用的是SpringDataJPA 而我手頭正好有以前學習springboot的時候寫的簡單Demo 方便起見就把實體類和持久層複製過來了 使用的是MySQL+MyBatis

 

提供者項目結構:

配置文件application:

## 數據源配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdemo?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

## Mybatis 配置
mybatis.typeAliasesPackage=com.example.springbootdemo.domain
mybatis.mapperLocations=classpath:mapper/*.xml

簡單對象User只有int類型的id String類型的username和realname

UserDao:

package com.example.springbootdemo.dao;
import com.example.springbootdemo.domain.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;


@Mapper
@Repository
public interface UserDao
{
    //根據uid查詢用戶
    User findByUid(@Param("uid") int uid);
}

mapper:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.springbootdemo.dao.UserDao">
    <resultMap id="BaseResultMap" type="com.example.springbootdemo.domain.User">
        <result column="uid" property="uid" />
        <result column="username" property="username" />
        <result column="realname" property="realname" />
    </resultMap>

    <select id="findByUid" resultMap="BaseResultMap" parameterType="Integer">
        select
        *
        from user
        where uid = #{uid}
    </select>

</mapper>

Service和實現:

Controller:

package com.example.springbootdemo.controller;

import com.example.springbootdemo.domain.User;
import com.example.springbootdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController
{
    @Autowired
    private UserService userService;

    @RequestMapping(value="/getuser",method = RequestMethod.GET)
    public User findOneUser(@RequestParam(value="uid",required=true) int uid)
    {
        return userService.findByUid(uid);
    }
}

啓動類是自動生成的 由於在同包下所以不需要用Scan Dao層也加入了Mapper註解

 

依賴:

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

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

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

</project>

運行後測試一下:

 

接下來編寫消費者

User類與提供者保持一致

controller:

package com.example.consumer.controller;

import com.example.consumer.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class controller
{
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("/user/{id}")
    public User findById(@PathVariable int id)
    {
        return this.restTemplate.getForObject("http://localhost:8080/getuser?uid="+id,User.class);
    }
}

提供者項目的端口號使用默認8080接口 消費者項目設置爲其他 我使用的是8081

server.port=8081

兩個項目都運行起來之後

也可以將提供者的url配置在配置文件中

這樣就可以將Controller修改爲:

 

然而這種簡單的固定接口調用的方式存在許多問題比如:

  • 適用場景有侷限:如果服務提供者的網絡地址(IP和端口)發生了變化,會影響服務消費者,消費者需要修改代碼並重新發布 
  • 無法動態伸縮:在生產環境中,每個微服務一般都會部署多個實例,從而實現容災和負載均衡,還需要動態的增減節點等,硬編碼的形式也無法滿足這個需求
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章