微服务搭建——注册

案例搭建(用微服务架构思想实现微服务搭建)

        使⽤微服务架构的分布式系统,微服务之间通过⽹络通信。我们通过服务提供者与服务消费者来描述微服 务间的调⽤关系。

        服务提供者:服务的被调⽤⽅,提供调⽤接⼝的⼀⽅

        服务消费者:服务的调⽤⽅,依赖于其他服务的⼀⽅

        我们以电商系统中常⻅的⽤户下单为例,⽤户向订单微服务发起⼀个购买的请求。在进⾏保存订单之前 需要调⽤商品微服务查询当前商品库存,单价等信息。在这种场景下,订单微服务就是⼀个服务消费 者,商品微服务就是⼀个服务提供者

        咱们这个电商共有三个模块:用户管理、商品管理和订单管理。 以业务为参照物拆分成三个项目订单、商品、用户

1.创建数据库表

        shop_order订单表

        shop_product商品表

        shop_user⽤户表

 

 

商品表中version这里用不到不用写 

 

2. 服务模块

创建公共⽗模块springcloud_alibaba

        父项目文件可以创建Springboot文件+

        目的造三个独立的窗口包含三个独立的项目,三个项目为一个工程,所以最终还是一个项目,项目打开有多个模块,所以创建一个父文件。

        父项目角色:文件夹,这是一个项目,里面有很多子模块

                              聚合集中管理坐标

父项目只保留pom文件其余均删掉

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>org.example</groupId>
    <artifactId>springcloud_alibaba</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--pom:父文件-->
    <!--共三种jar包war包和pom父文件 -->
    <packaging>pom</packaging>

    <!--父项目的子模块-->
    <modules>
        <module>shop_common</module>
        <module>shop_order</module>
        <module>shop_product</module>
        <module>shop_user</module>
    </modules>

    <!--父工程-->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.1.3.RELEASE</version>
    </parent>

    <!--依赖版本的锁定-->
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
        <spring-cloud-alibaba.version>2.1.1.RELEASE</spring-cloud-alibaba.version>
    </properties>

    <!--
    dependencyManagement所包含的坐标,子项目不会直接继承,需要声明才可继承
    -->
    <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>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

创建公共模块 shop_common ,⽤于存放公共的实体类和⼯具类

        三个项目都要实现增删改查,所以我们把坐标写在公共模块的pom文件里,我们在要实现下点单的功能时,要频繁的调用我们的实体类,所以将它写在公共模块里,届时让三个项目模块导入该公共模块的坐标。

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud_alibaba</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <!--
    公共模块代码编辑
    工具类、实体类、
    -->
    <artifactId>shop_common</artifactId>
    <version>1.0-SNAPSHOT</version>
    <groupId>org.example</groupId>


    <!--依赖-->
    <dependencies>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.7</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>

</project>
 实体类

这里我们使用了Lombok插件,@Date帮助我们生成了gette、setter和toString方法

                @TableName("shop_order") 使用 Tablename  注解的目的是为了当类名或对象名与数据库中的表名不一致时,能够明确指出映射关系,同时也方便其他开发者理解数据库结构。

实体类order
package org.example.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

/**
 * @since 2024/8/20
 */
//订单
@TableName("shop_order")
@Data
public class Order {

    @TableId(value = "oid",type = IdType.AUTO)//主键
    private Long oid;//订单id

    //用户
    @TableField("uid")
    private Integer uid;//用户id
    @TableField("username")
    private String username;//用户名

    //商品
    @TableField("pid")
    private Integer pid;//产品id
    @TableField("pname")
    private String pname;//产品名称
    @TableField("pprice")
    private double pprice;//产品单价

    //数量
    @TableField("number")
    private int number;//购买数量

}
  实体类product
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

/**
 * @since 2024/8/20
 */
//商品
@TableName(value = "shop_product")
@Data
public class Product {

    @TableId(value = "pid", type = IdType.AUTO)
    private Integer pid;//产品id
    @TableField("pname")
    private String pname;//产品名称
    @TableField("pprice")
    private double pprice;//产品单价
    @TableField("stock")
    private Integer syock;//库存
}
 实体类user
package org.example.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.time.Year;

/**
 * @since 2024/8/20
 */
//用户
    @TableName(value = "shop_user")
    @Data
public class User {
   //用户
    @TableId(value = "uid",type = IdType.AUTO)
    private Integer uid;//用户id
    @TableField("username")
    private String username;//用户名
    @TableField("password")
    private String password;//密码
    @TableField("telephone")
    private String telephone;//手机号
}

创建订单微服务模块 shop_order 端⼝809X

        先写pom文件

        导入公共模块common

<?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_alibaba</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>shop_order</artifactId>

    <dependencies>
        <!--springboot-web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--shop-common-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>shop_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>
         配置yml

        着重注意数据库名称

server:
  port: 8091 #端口号
spring:
  application:
    name: service-order #服务名称
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://shop?serverTimezone=UTC&useUnicode   #数据源
    username: root
    password:123456
  搭建三层Dao、service、controller实现该功能表的增删改查

        建议创建Springboot文件这里我创建的是maven,springboot自动帮我们创建启动类。

        这里我们在公共模块导入了mybatis-plus-boot-starter,在搭建三层时,加入注解,一些简单的SQL语句就不用我们写了

 先写Dao层
package org.example.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.example.domain.Order;

/**
 * @since 2024/8/20
 */
@Mapper
public interface IorderMapper extends BaseMapper<Order> {
}
再写Service层
        接口IOrderService
package org.example.service;

import com.baomidou.mybatisplus.extension.service.IService;
import org.example.domain.Order;

/**
 * @since 2024/8/21
 */
public interface IOrderService extends IService<Order> {

}
        实现类OrderServiceImp
package org.example.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.dao.IorderMapper;
import org.example.domain.Order;
import org.springframework.stereotype.Service;

/**
 * @since 2024/8/21
 */
@Service
public class OrderServiceImp extends ServiceImpl<IorderMapper, Order> implements IOrderService{
}
最后写控制层 
package org.example.controller;


import org.example.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
impor

/**
 * @since 2024/8/20
 */
@RestController
public class OrderController {
    @Autowired
    private IOrderService iOrderService;

}

        其余两个模块与这一个模块相同 

创建商品微服务模块 shop_product 端⼝808X

1.要写三层Dao、service、controller实现该功能表的增删改查,导入mysql,plus,写三层是只要加入注解,继承已写好的建议创建Springboot文件这里我创建的是maven,springboot自动帮我们创建启动类。

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud_alibaba</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>shop_product</artifactId>

    <dependencies>
        <!--springboot-web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--shop-common-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>shop_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>
yml文件
server:
  port: 8081
spring:
  application:
    name: service-product
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://shop?serverTimezone=UTC&useUnicode
    username: root
    password:123456
搭建三层 
Dao层
@Mapper
public interface IProductMapper extends BaseMapper<Product> {
}
service层
 接口
public interface IProductService extends IService<Product> {
}
实现类
@Service
public class ProductServiceImp extends ServiceImpl<IProductMapper, Product> implements IProductService{

}
 controller层
@RestController
public class ProductController {
    @Autowired
    private IProductService iProductService;

}

创建⽤户微服务模块 shop_user 端⼝807X

1.要写三层Dao、service、controller实现该功能表的增删改查,导入mysql,plus,写三层是只要加入注解,继承已写好的建议创建Springboot文件这里我创建的是maven,springboot自动帮我们创建启动类。

        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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud_alibaba</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>shop_user</artifactId>

    <dependencies>
        <!--springboot-web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--shop-common-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>shop_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

        yml文件

server:
  port: 8071
spring:
  application:
    name: service-user
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://shop?serverTimezone=UTC&useUnicode
    username: root
    password:1234

        类比以上两个模块搭建user的三层 

实现下订单功能

        1.先写product里的功能
                product控制controller层
package org.example.controller;

import org.example.domain.Product;
import org.example.service.IProductService;
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.RestController;

@RestController
public class ProductController {
    @Autowired
    private IProductService iProductService;

    //商品信息查询
    @RequestMapping("/product/{pid}")
    public Product product(@PathVariable("pid") Integer pid){
        Product product = iProductService.getById(pid);
        return product;
    }
}
         2.然后写order模块里的功能
                Service层的接口
package org.example.service;

import com.baomidou.mybatisplus.extension.service.IService;
import org.example.domain.Order;

public interface IOrderService extends IService<Order> {
    //创建订单
    void createOrder(Order order);
}
                service层的实现类
package org.example.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.dao.IorderMapper;
import org.example.domain.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderServiceImp extends ServiceImpl<IorderMapper, Order> implements IOrderService{

    @Autowired
    private IorderMapper iorderMapper;


    @Override
    public void createOrder(Order order) {
        iorderMapper.insert(order);
    }
}
                controller层
package org.example.controller;

import com.sun.org.apache.xml.internal.resolver.helpers.PublicId;
import org.example.domain.Order;
import org.example.domain.Product;
import org.example.service.IOrderService;
import org.example.service.OrderServiceImp;
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.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private IOrderService iOrderService;

    //下单
    @RequestMapping("/order/prod/{pid}")
    public Order order(@PathVariable("pid") Integer pid){

        //调用商品微服务,查询商品信息
        Product product = restTemplate.getForObject("http://localhost:8081/product/"+pid,Product.class);

        //下单(创建订单)
        Order order = new Order();
        order.setUid(1);
        order.setUsername("测试用户");
        order.setPid(pid);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(2);
        iOrderService.createOrder(order);
        return order;
    }
}

3.3 服务调⽤

前⽂已经编写了三个基础的微服务,在⽤户下单时需要调⽤商品微服务获取商品数据。那应该怎么做 呢?总⼈皆知商品微服务提供了供⼈调⽤的HTTP接⼝。所以可以再下定单的时候使⽤http请求的相关⼯ 具类完成,如常⻅的HttpClient ,OkHttp,当然也可以使⽤Spring提供的RestTemplate

3.5.1 RestTemplate介绍

Spring框架提供的RestTemplate类可⽤于在应⽤中调⽤rest服务,它简化了与http服务的通信⽅式,统 ⼀了RESTful的标准,封装了http链接, 我们只需要传⼊url及返回值类型即可。相较于之前常⽤的

HttpClient ,RestTemplate是⼀种更优雅的调⽤RESTful服务的⽅式。

在Spring应⽤程序中访问第三⽅REST服务与使⽤Spring RestTemplate类有关。 RestTemplate类的设 计 原则与许多其他Spring 模板类(例如JdbcTemplate、JmsTemplate)相同,为执⾏复杂任务提供了⼀ 种具有默认⾏为的简化⽅法。

RestTemplate默认依赖JDK提供http连接的能⼒(HttpURLConnection),如果有需要的话也可以通过 setRequestFactory⽅法替换为例如 Apache HttpComponents、 Netty或OkHttp等其它HTTP library。 考虑到RestTemplate类是为调⽤REST服务⽽设计的,因此它的主要⽅法与REST的基础紧密相连就不⾜ 为奇了,后者是HTTP协议的⽅法:HEAD、GET、 POST、 PUT、 DELETE和OPTIONS。例如, RestTemplate类具有headForHeaders()、getForObject()、 postForObject()、 put()和delete()等⽅法。

3.5.2 RestTemplate⽅法介绍

3.5.3 通过RestTemplate调⽤微服务

( 1 )在 shop_order⼯程中配置RestTemplate

//配置RestTemplate交给spring管理
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}

(2 )编写下订单⽅法

//通过restTemplate调⽤商品微服务
restTemplate .getForObject("http://127.0.0.1:8081/product/1" , Product.class);

3.5.4 硬编码存在的问题

⾄此已经可以通过RestTemplate调⽤商品微服务的RESTFul API接⼝。但是我们把提供者的⽹络地址 (ip,端⼝)等硬编码到了代码中,这种做法存在许多问题: 应⽤场景有局限 ⽆法动态调整 就需要通过注册中⼼动态的对服务注册和服务发现

  • 15
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值