2. Spring Cloud 微服务基础环境搭建

2. Spring Cloud 微服务基础环境搭建

文章目录

  • 2. Spring Cloud 微服务基础环境搭建
  • 前言
  • 1. 微服务需求解析
  • 2. 具体搭建微服务步骤:
    • 2.1 创建父工程 ,用于聚合其它微服务模块
      • 2.1.1 需求说明/图解
      • 2.1.2 具体实现步骤
      • 2.1.3 注意事项和具体细节
    • 2.2 创建会员中心微服务模块 -service provider
      • 2.2.1 需求说明/图解
      • 2.2.2 具体实现步骤:
      • 2.2.3 注意事项和具体细节
    • 2.3 创建使用会员微服务模块 -service consumer
      • 2.3.1 需求说明/图解
      • 2.3.2 具体实现步骤
      • 2.3.3 注意事项和具体细节
  • 3. 补充:开启 Run DashBoard
    • 2.4 创建共用模块-供其它模块使用
      • 2.4.1 需求说明/图解
      • 2.4.2 具体实现步骤
      • 2.4.3 测试
  • 3. 总结:
  • 4. 最后:

前言

  • 对应上一篇学习内容:🌟🌟🌟 1. 初始认识 Spring Cloud-CSDN博客
  • 对应下一篇学习内容:🌟🌟🌟

1. 微服务需求解析

在这里插入图片描述

说明:

我们通过浏览器输入: http://localhost//member/consumer/get/1 这样一个服务消费微服务模块 ,这个服务消费微服务模块,底层访问——> 服务提供 消费微服务模块(当中所提供的接口/方法)进行对数据库的查询和添加数据的操作。

简单的说就是两个模块,处理业务

  • member-service-consumer-80 : 作为服务消费微服务模块,提供给客户端显示处理,连接浏览器

  • member-service-provider-10000 : 作为服务提供 消费微服务模块,处理前端实际提交的业务,进行处理

  • 特别说明:这里每个模块,用于区分用的是那个端口,我们在模块名后面-追加一个 端口信息 。如下:

    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

特别说明: 这里我们对于**每个模块的 Spring Boot 的场景启动器上的类后面追加上一个“该模块所占用的端口号” ** ,方便我们查找该明确所占用的端口信息。如下图所示:

在这里插入图片描述

2. 具体搭建微服务步骤:

对于一个微服务 的搭建,这里我们采用父工程,利用 Maven版本仲裁 简化配置。

所以,我们就需要创建一个父项目,通过父项目管理我们的多个微服务的各个所提供的功能的模块。

2.1 创建父工程 ,用于聚合其它微服务模块

2.1.1 需求说明/图解

在这里插入图片描述

2.1.2 具体实现步骤

  1. 我们需要先创建一个父项目/父工程 ,该父工程会去管理我们父工程下的多个微服务模块(module) ,如下图所示:( 该图是我们学习微服务内容的所有内容上该微服务配置好的内容 )

在这里插入图片描述

  1. 创建父项目步骤:- 灵活配置方式。

在这里插入图片描述

在这里插入图片描述

特别的: 当我们创建一个项目成功后,要修改对应该项目所选配的配置。比如:

  1. 指明该项目我们所要运行的 Java 的版本,这里我们选择 Java 8 的版本

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  1. 配置我们项目的字符集的编码,这里我们选择配置 utf-8 的编码

在这里插入图片描述

  1. 配置指明我们本地的 maven 工具,不要用 idea 所提供的的 maven 工具

在这里插入图片描述

这里我们将父项目作为一个简单纯净的环境(因为我们的这个微服务项目,这个父模块部分,不需要编写代码,仅仅作为一个管理多个模块的管理器) ,所以我们可以将其 idea 自动为我们生成 src 目录删除。作为一个简单的纯净的开发环境。

在这里插入图片描述

配置父工程 pom.xml, 作为聚合其它模块

我们在父工程 e-commerce-center 当中的 pom.xml 文件当中配置相关所需要的 jar的依赖。

如下:相关的依赖。

在这里插入图片描述

在 <propertis> 标签当中指明:相关我们所需要的所需的依赖的 jar 包当中版本的内容。进行一个版本仲裁

在这里插入图片描述

    <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><!--        在父项目当中:定义版本仲裁--><junit.version>4.12</junit.version><!--    说明: 使用最新版本 log4j ,防止安全漏洞--><log4j.version>2.17.2</log4j.version><lombok.version>1.18.20</lombok.version><!--    老师的 5.1.47  本电脑安装的是   8.0.26--><mysql.version>8.0.26</mysql.version><druid.version>1.1.17</druid.version><mybatis.spring.boot.version>2.2.0</mybatis.spring.boot.version></properties>

同时我们需要在: <dependencyManagement> 配置各个依赖和版本

当我们在父项目/父工程当中配置了该 <dependencyManagement\> 的标签内容,需要注意的一点是: 这里的依赖的 jar 并没有引入到项目当中,仅仅这是一个声明而已
<dependencyManagement> 里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要的添加依赖相对应的依赖信息。

在这里插入图片描述

<!--  <dependencyManagement> 配置各个依赖和版本子模块继承后,锁定版本,子模块不用再写 version 了需要注意的一点是: 这里的依赖的 jar 并没有引入到项目当中,仅仅这是一个声明而已<dependencyManagement> 里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要的依赖 --><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.2.2.RELEASE</version><!--1.type:pom 和 scope: import 配合使用2.表示父项目的子模块,在引入 springboot 相关依赖时,锁定版本为 2.2.2.RELEASE3.通过 pom + import 解决maven单继承机制4. 子模块之间可以多继承--><type>pom</type><scope>import</scope></dependency><!--            配置 Spring Cloud--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.SR1</version><type>pom</type><scope>import</scope></dependency><!--            配置 Spring Cloud Alibaba--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.1.0.RELEASE</version><type>pom</type><scope>import</scope></dependency><!--            mysql 数据库--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><!--             ${mysql.version} 锁定引用上面<mysql.version>标签配置的版本信息 --><version>${mysql.version}</version></dependency><!--            druid 数据库连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>${druid.version}</version></dependency><!--            spring boot --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.spring.boot.version}</version></dependency><!--       log4j 日志     --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j</artifactId><version>${log4j.version}</version></dependency><!--            junit 配置--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version></dependency><!--            lombok 配置--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version></dependency></dependencies></dependencyManagement>

特别说明: type: pom 和 scope: import 配置使用 的作用:让多个模块之间可以多继承,解决 maven 单继承机制。

            <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.2.2.RELEASE</version><!--1.type:pom 和 scope: import 配合使用2.表示父项目的子模块,在引入 springboot 相关依赖时,锁定版本为 2.2.2.RELEASE3.通过 pom + import 解决maven单继承机制4. 子模块之间可以多继承--><type>pom</type><scope>import</scope></dependency>

删除不需要的配置节点。

这里我们删除 buildreporting 节点下的内容信息即可。

2.1.3 注意事项和具体细节

dependencyManagement 细节说明

  1. Maven 使用 <dependencyManagement> 元素来提供了一种管理依赖版本号的方式,
    通常在项目 packaging为POM,中使用 <dependencyManagement> 元素
  2. 使用 pom.xml 中的 <dependencyManagement> 标签元素能让所有在子项目中引用一个依赖,
    Maven 会沿着父子层次向上走,直到找到一个拥有 <dependencyManagement> 标签元素的项目,
    然后它就会使用这个 <dependencyManagement> 元素中指定的版本号。
    3.好处: 如果有多个项目都引用同一样依赖,则可以避免在每个使用的子项目里都声明一个版本号,
    当升级或切换到另一个版本时,只需要在顶层父容器更新,而不需要分别在子项目的修改;另外
    如果某个子项目需要另外一个版本,只需要声明 version 就可以。
  3. <dependencyManagement> 里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要的依赖
  4. 如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且 versionscope 都读取自父 pom 所配置的 <dependencyManagement> 的内容。

在这里插入图片描述

在这里插入图片描述

  1. 如果子项目中指定了版本号,那么会使用子项目中指定的 jar 版本

2.2 创建会员中心微服务模块 -service provider

2.2.1 需求说明/图解

通过浏览器可以获取会员信息(通过会员中心微服务模块)

在这里插入图片描述

同样的使用 Postman 工具可以进行一个访问操作的问题。

在这里插入图片描述

通过 Postman 进行一个添加用户的操作。如下图所示:

在这里插入图片描述

准备工作:我们创建对应所需的数据库和数据表的内容

如下:创建数据库,创建数据表,添加初始表当中的内容的 SQL 所执行的脚本

这里我们创建的e_commerce_center_db 的数据库的内容目前仅仅只是添加了一张数据表 member 员工的数据表。

CREATE DATABASE e_commerce_center_db;
USE e_commerce_center_db;
CREATE TABLE member
(`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'id',`NAME` VARCHAR(64) COMMENT '用户名',pwd CHAR(32) COMMENT '密码',mobile VARCHAR(20) COMMENT '手机号码',email VARCHAR(64) COMMENT '邮箱',gender TINYINT COMMENT '性别',PRIMARY KEY (id)
);INSERT INTO member VALUES
(NULL, 'smith', MD5('123'), '123456789000', 'smith@sohu.com', 1);
SELECT * FROM member

特别说明:为了方便后续的记忆操作,这里我们用户的密码都配置为了 123 ,因为我们对用户的密码进行了一个 MD5 的加密处理,所以我们无法明文的看到对应设置的密码。

在这里插入图片描述

2.2.2 具体实现步骤:

这里:我们创建 member-service-provider-10000 微服务模块[提供会员服务] 。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

member-service-provider-10000 模块当中的 pom.xml 文件当中引入相关的 jar 的依赖。如下图所示:

在这里插入图片描述

详细配置如下:

<?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"><!--    这是对应该子模块 module 上的父模块--><parent><artifactId>e-commerce-center</artifactId><groupId>com.rainbowsea</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><!--    该项目继承父项目的groupId 是 com.rainbowsea.sprngcloud-因此这里就不需要再指定 groupid 版本了 --><artifactId>member-service-provider-10000</artifactId><!--    引入相关的依赖--><dependencies><!--        引入web-starter 说明:这里我们使用版本仲裁(从父项目继承了版本)--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--1. starter-actuator 是sprng boot 程序的监控系统,可以实现健康检查,info 信息等2. 访问http://localhost:10000/actuator 可以看到相关链接,还可以做相关配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--        引入 mybatis-starter 整合到 springboot 当中--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><!--  这里我们重新指定一下 version 版本,因为父项目当中没有--><version>1.1.13</version></dependency><!--        引入 mysql依赖,使用版本仲裁--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--      spring-boot-starter-jdbc 引入  --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!--        lombok 引入--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--        引入 test-starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--        引入我们自己对 bean 封装成 api 的模块内容--><dependency><groupId>com.rainbowsea</groupId><artifactId>e_commerce_center-common-api</artifactId><version>${project.version}</version></dependency><!-- 引入 eureka-client 依赖  --><!--        注意:存在一个 starter 不要选错了--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></dependencies></project>

在这里插入图片描述

同时需要注意:所加载的 jar 的内容的版本是否与你在父项目/模块当中指定的版本一致;

在这里插入图片描述

在 在 member-service-provider-10000 模块当中的resources 目录下创建一个:application.yaml 文件,后缀为 yml 也是一样的,但是注意:文件名必须是 application 不可以是其它的。

在这里插入图片描述

在该 application.yaml 文件当中编写,相关的配置信息,比如: mybatis,springboot,springcloud 等等配置信息。如下图所示:

在这里插入图片描述

server:port: 10000
spring:application:name: member-service-provider-10000 # 配置应用的名称datasource:type: com.alibaba.druid.pool.DruidDataSource # 配置 alibaba 的数据库连接池password: MySQL123username: rooturl: jdbc:mysql://localhost:3306/e_commerce_center_db?useSSL=true&useUnicode=true&characterEncoding=UTF-8
mybatis:mapper-locations: classpath:mapper/*.xml # 指定 mapper.xml 文件位置 classpath 表示 resources 目录下type-aliases-package: com.rainbowsea.springcloud.entity # 实例 bean 类所在的包,这样可以通过类名的方式

我们在 member-service-provider-10000 模块当中创建一个 com.rainbowsea.springcloud 下创建一个场景启动类。

在这里插入图片描述

package com.rainbowsea.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@EnableEurekaClient 表示将该程序/项目/模块 标识为 eureka-client 端
//@EnableEurekaClient
@SpringBootApplication
public class MemberApplication10000 {public static void main(String[] args) {SpringApplication.run(MemberApplication10000.class, args);}
}

在该项目当中的创建一个包为 com.rainbowsea.springcloud.entity 下创建,我们所需要的 Java Bean 的类。两个:Result,以及 Member 两个 java 类。对于 Member 类我们使用 Lombak 插件进行自动生成,而这里的 Result 所需要的方法,需要自定义静态方法,使用 Lombak 自动生成的方法,不够使用,所以 Result 就自己手动编写了。

在这里插入图片描述

package com.rainbowsea.springcloud.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Member implements Serializable { // Serializable 表示传输时的序列化操作private Long id;private String name;private String pwd;private String mobile;private String email;private Integer gender;
}

Result 该类用于,前后端交互的一个返回结果,同时利于 json 格式的内容上的转换。这个工具类,我们可以在网上很轻松的找到

特别的该 Result 类当中有: 三个成员变量:

  • private String code; // 表示后端提交给前端所显示的 :状态码

  • private String msg; // 表示对后端提交的状态码的一个说明解释的内容,比如 404 提示找不到内容的提示 等等

  • private T data; // 表示对后端返回给前端的数据/携带的数据, 为了扩展性好,我们这里使用泛型,任何数据类型基本上都可以满足。

public class Result<T> implements Serializable {private String code; //状态码private String msg; //对状态说明private T data; // 返回时,携带的数据, 为了扩展性好,老师使用泛型
}

在这里插入图片描述

package com.rainbowsea.springcloud.entity;import java.io.Serializable;/*** 1. 用于返回结果, 利于 json 格式* 2. 这个工具类, 在网上也可找到*/
public class Result<T> implements Serializable {private String code; //状态码private String msg; //对状态说明private T data; // 返回时,携带的数据, 为了扩展性好,老师使用泛型//无参构造器public Result() {}//带参构造器-指定返回的datapublic Result(T data) {this.data = data;}//编写方法-返回需要的Result对象-表示成功的Resultpublic static Result success() {Result result = new Result<>();result.setCode("200");result.setMsg("success");return result;}//编写方法-返回需要的Result对象-表示成功的Result,同时可以携带数据//如果需要在static方法使用泛型,需要在 static <T>public static <T> Result<T> success(T data) {Result<T> result = new Result<>(data);result.setCode("200");result.setMsg("success");return result;}//编写方法-返回需要的Result对象-表示成功的Result,同时可以携带数据和指定msg//如果需要在static方法使用泛型,需要在 static <T>public static <T> Result<T> success(String msg, T data) {Result<T> result = new Result<>(data);result.setCode("200");result.setMsg(msg);return result;}//编写方法-返回需要的Result对象-表示失败的Resultpublic static Result error(String code, String msg) {Result result = new Result<>();result.setCode(code);result.setMsg(msg);return result;}public static <T> Result<T> error(String code, String msg, T data) {Result<T> result = new Result<>(data);result.setCode(code);result.setMsg(msg);return result;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public T getData() {return data;}//编写方法-返回需要的Result对象-表示失败的Result,同时可以携带数据public void setData(T data) {this.data = data;}
}

Result 类当中的方法说明:

如何在静态方法中使用泛型

我们知道在Java当中 泛型 是在 实例化对象 才确定的,而静态方法 则是,加载类的时候就确定了的,两个内容的加载时期对应不上,所以:直接在静态方法当中使用 泛型是会报错的。如下:

在这里插入图片描述

解决方法就是:我们只需要在静态方法中的 static 关键字的后面加上 <T> 其泛型即可。如下:public static <T> Result<T> error(String code, String msg, T data)

在这里插入图片描述

在该项目中member-service-provider-10000 模块当 创建一个 com.rainbowsea.springcloud.dao 该包下创建 mybatis 所执行SQL语句的方法/接口,如下:

注意:添加上 @Mapper 注解,让被 Spring IOC 容器管理起来。如果存在多个 需要添加 @Mapper 注解的类,可以在对应的该项目当中的场景启动项目 当中添加 @MapperScan(指明要扫描的路径)

这里我们目前就添加两个接口方法

  • Member queryMemberById(Long id); // 根据 id 返回 member 数据
  • int save(Member member); // 添加 member 数据到数据库,数据表当中

在这里插入图片描述

package com.rainbowsea.springcloud.dao;import com.rainbowsea.springcloud.entity.Member;
import org.apache.ibatis.annotations.Mapper;@Mapper  // 标注注解被扫描到,或是在 配置类/场景启动项中 @MapperScan(指明扫描路径)
public interface MemberDao {// 定义方法// 根据 id 返回 member 数据Member queryMemberById(Long id);/*** 添加 member** @param member* @return*/int save(Member member);
}

编写上述我们在 com.rainbowsea.springcloud.dao 包下所编写的执行SQL的接口方法,所对应的 SQL 脚本内容信息。如下:

在这里插入图片描述

如下我们编写相关的所需要执行的 SQL 语句的脚本信息:

在这里插入图片描述

在这里插入图片描述

特别的:这里我们启动的了 Mybatis 的别名机制,在该 member-service-provider-10000 模块当中我们所配置的 application.yaml 的内容。

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?> <!-- 这句不要动,表示xml的版本,以及读取的编码 -->
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rainbowsea.springcloud.dao.MemberDao"><!--    配置实现 queryMemberById--><!--1.这里可以使用 resultType="Member"2.当然也可以使用 resultMap="自定义的resultMap",这里我们使用resultMap--><resultMap id="BaseResultMap" type="com.rainbowsea.springcloud.entity.Member"><id column="id" property="id" jdbcType="BIGINT"></id><id column="name" property="name" jdbcType="VARCHAR"></id><id column="pwd" property="pwd" jdbcType="VARCHAR"></id><id column="mobile" property="mobile" jdbcType="VARCHAR"></id><id column="email" property="email" jdbcType="VARCHAR"></id><id column="gender" property="gender" jdbcType="TINYINT"></id></resultMap><!--实现查询--><select id="queryMemberById" parameterType="Long" resultMap="BaseResultMap">select * from `member` where `id`=#{id}</select><!--    实际开发中,我们使用的是 mybatis,还是 mybatis-plus 两者都要会--><!--  useGeneratedKeys="true" keyProperty="id" 表示如果插入的表id 以自证列为主键,那么允许jdbc自动生成主键,并可将自动生成的主键id返回,注意:useGeneratedKeys="true" 只针对 insert 语句生效, 默认为 false--><insert id="save" parameterType="member" useGeneratedKeys="true" keyProperty="id">insert into member(`NAME`,`pwd`,`mobile`,`email`,`gender`)values(#{name}, md5(#{pwd}), #{mobile},#{email}, #{gender});</insert>
</mapper>

编写相关的 service 层的内容信息。

在这里插入图片描述

编写 memberDao 和 Service 的内容的测试类,进行一个测试。

需要注意的是:如果要测试,该项目必须要有场景启动器,同时场景启动器添加上了 @SpringBootApplication 注解。才行。

@SpringBootTest // 如果指明的路径不同;要加上注解指明(场景启动的所在包路径)// 同时一定要有场景启动器注解
// 如果不想把测试类放到和启动类相同的包下,那就给测试类的注解加上@SpringBootTest(classes = {springbootJpaApplication.class}) 代

在这里插入图片描述

在这里插入图片描述

package com.rainbowsea.springcloud;import com.rainbowsea.springcloud.dao.MemberDao;
import com.rainbowsea.springcloud.entity.Member;
import com.rainbowsea.springcloud.service.MemberService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import javax.annotation.Resource;@SpringBootTest // 如果指明的路径不同;要加上注解指明(场景启动的所在包路径)// 同时一定要有场景启动器注解
// 如果不想把测试类放到和启动类相同的包下,那就给测试类的注解加上@SpringBootTest(classes = {springbootJpaApplication.class}) 代
@Slf4j
public class MemberApplicationTest {@Resourceprivate MemberDao memberDao;@Resourceprivate MemberService memberService;@Test  // 注意选择: org.junit.jupiter.api.Test; 包当中的// 注意方法不能定义为 private 私有的,不然无法测试运行的public void testQueryMemberById() {Member member = memberDao.queryMemberById(1L);log.info("member={}", member);}@Testpublic void testMemberDaosave() {Member member = new Member(null, "牛魔王", "123", "1300000", "nmw@shou.com", 1);int affected = memberDao.save(member);log.info("affected={}", affected);}@Test  // 注意选择: org.junit.jupiter.api.Test; 包当中的// 注意方法不能定义为 private 私有的,不然无法测试运行的public void testMemberServiceQueryMemberById2() {Member member = memberService.queryMemberById(1L);log.info("member={}", member);}@Testpublic void testMemberServiceSave() {Member member = new Member(null, "狐狸精", "123", "1300000", "hlj@shou.com", 2);int affected = memberService.save(member);log.info("affected={}", affected);}
}

编写相关的 controller 控制器,进行业务上的处理。

在这里插入图片描述

在这里插入图片描述

package com.rainbowsea.springcloud.controller;import com.rainbowsea.springcloud.entity.Member;
import com.rainbowsea.springcloud.entity.Result;
import com.rainbowsea.springcloud.service.MemberService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
@Slf4j
public class MemberController {@Resourceprivate MemberService memberService;/*说明:1. 我们的前端如果是以 json 格式来发送添加信息的Member,那么我们需要使用 @RequestBody才能将数据封装到对应的 bean,同时保证http的请求的 content-type 是对应2. 如果前端是以表单形式提交了,则不需要使用@RequestBody,才会进行对象bean参数封装,同时保证 http的请求的 content-type 是对应*//*** 添加方法/接口** @param member* @return*/@PostMapping("/member/save")public Result save(@RequestBody Member member) {// 注意:微服务组件通信的坑点:// 这里我们使用 RestTemplate 传输发送的数据格式是以 json 格式的所以要添加撒谎给你 @RequestBody// 将json 格式的字符串转换为 bean对象进行赋值// 同时,我们 bean 对象传输过程中是需要序列化的。log.info("member-service-provider-10000 save member={}", member);int affected = memberService.save(member);if (affected > 0) { // 说明添加成功return Result.success("添加会员成功", affected);} else {return Result.error("401", "添加会员失败");}}/*** 这里我们使用 url占位符 + @PathVariable** @param id* @return*/@GetMapping("/member/get/{id}")public Result getMemberById(@PathVariable("id") Long id) {Member member = memberService.queryMemberById(id);// 使用 Result 把查询到的结果返回if (member != null) {return Result.success("查询会员成功", member);} else {return Result.error("402", "ID" + id + "不存在");}}}

特别说明:

说明:
1. 我们的前端如果是以 json 格式来发送添加信息的Member,那么我们需要使用 @RequestBody
才能将数据封装到对应的 bean,同时保证http的请求的 content-type 是对应
2. 如果前端是以表单形式提交了,则不需要使用@RequestBody,才会进行对象bean参数封装,同时保证 http的请求的 content-type 是对应

在这里插入图片描述

测试:

测试查询

启动 member-service-provider-10000 模块,打开浏览器输入: 浏览器: http://localhost:10000/member/get/1 看看是否能够查询成功:

在这里插入图片描述

在这里插入图片描述

测试删除:

使用 Postman 看看能否添加成功。

在这里插入图片描述

在这里插入图片描述

2.2.3 注意事项和具体细节

  1. 我们的前端如果是以 json 格式来发送添加信息 furn,那么我们需要使用@RequestBody, 才能将数据封装到对应的 bean, 同时保证 http 的请求头的 content-type 是对应。

在这里插入图片描述

  1. 如果前端是以表单形式提交了/或者是以 parameters,则不需要使用@RequestBody, 才 会进行对象参数封装, 同时保证 http 的请求头的 content-type 是对应
  2. 在进行 SpringBoot 应用程序测试时,引入的 JUnit 是 org.junit.jupiter.api.Test
  3. 在运行程序时,一定要确保你的 XxxxMapper.xml 文件 被自动放到的 target 目录的 classes 指定目录

在这里插入图片描述

2.3 创建使用会员微服务模块 -service consumer

2.3.1 需求说明/图解

在这里插入图片描述

简单的说:就是让我们的 member-service-consumer-80模块,通过调用 member-service-provider-10000 模块的里的方法/接口,处理前端的业务请求。

本质:就是前端提交的业务让我们这个**member-service-provider-10000,服务提供微服务模块处理** 。

浏览器: http://localhost/member/consumer/get/1

在这里插入图片描述

测试添加会员 : http://localhost/member/consumer/save

2.3.2 具体实现步骤

  1. 创建 Moduel(member-service-consumer-80) & 完成配置

创建 member-service-consumer-80 微服务模块[使用会员服务]

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

父工程的 pom.xml-会做相应变化,管理 member-service-consumer-80 微服务 子模块

在这里插入图片描述

  1. 编写 member-service-consumer-80 的 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"><!--    parent 父项目/模块内容--><parent><artifactId>e-commerce-center</artifactId><groupId>com.rainbowsea</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>member-service-consumer-80</artifactId><!--    引入相关的依赖:我们引入了当前所需要的依赖,后面如果有其它的需要,再灵活添加--><dependencies><!--        引入 web-starter 说明:我们使用版本仲裁(从父项目继承了版本)--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--1. starter-actuator 是sprng boot 程序的监控系统,可以实现健康检查,info 信息等2. 访问http://localhost:10000/actuator 可以看到相关链接,还可以做相关配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--        lombok 引入--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--        引入 test-starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
</project>
  1. 创建 resources/application.yml 配置相关信息

在这里插入图片描述

  1. 创建主启动类 com/rainbowsea/springcloud/MemberConsumerApplication.java

在这里插入图片描述

  1. 在该项目当中的创建一个包为 com.rainbowsea.springcloud.entity 下创建,我们所需要的 Java Bean 的类。两个:Result,以及 Member 两个 java 类。对于 Member 类我们使用 Lombak 插件进行自动生成,而这里的 Result 所需要的方法,需要自定义静态方法,使用 Lombak 自动生成的方法,不够使用,所以 Result 就自己手动编写了。

    在这里插入图片描述

package com.rainbowsea.springcloud.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Member implements Serializable { // Serializable 表示传输时的序列化操作private Long id;private String name;private String pwd;private String mobile;private String email;private Integer gender;
}

在这里插入图片描述

package com.rainbowsea.springcloud.entity;import java.io.Serializable;/*** 1. 用于返回结果, 利于 json 格式* 2. 这个工具类, 在网上也可找到*/
public class Result<T> implements Serializable {private String code; //状态码private String msg; //对状态说明private T data; // 返回时,携带的数据, 为了扩展性好,老师使用泛型//无参构造器public Result() {}//带参构造器-指定返回的datapublic Result(T data) {this.data = data;}//编写方法-返回需要的Result对象-表示成功的Resultpublic static Result success() {Result result = new Result<>();result.setCode("200");result.setMsg("success");return result;}//编写方法-返回需要的Result对象-表示成功的Result,同时可以携带数据//如果需要在static方法使用泛型,需要在 static <T>public static <T> Result<T> success(T data) {Result<T> result = new Result<>(data);result.setCode("200");result.setMsg("success");return result;}//编写方法-返回需要的Result对象-表示成功的Result,同时可以携带数据和指定msg//如果需要在static方法使用泛型,需要在 static <T>public static <T> Result<T> success(String msg, T data) {Result<T> result = new Result<>(data);result.setCode("200");result.setMsg(msg);return result;}//编写方法-返回需要的Result对象-表示失败的Resultpublic static Result error(String code, String msg) {Result result = new Result<>();result.setCode(code);result.setMsg(msg);return result;}public static <T> Result<T> error(String code, String msg, T data) {Result<T> result = new Result<>(data);result.setCode(code);result.setMsg(msg);return result;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public T getData() {return data;}//编写方法-返回需要的Result对象-表示失败的Result,同时可以携带数据public void setData(T data) {this.data = data;}
}

重点: 注入 RestTemplate

RestTemplate 是 Spring 提供的用于访问 Rest 服务的模块类。

  1. RestTemplate 提供了多种便捷访问远程Http服务 的方法
  2. 说明: 大家可以这样理解,通过 RestTemplate ,我们可以发出 Http请求(支持Restful风格),
    去调用Controller 提供的 API接口,就像我们使用浏览器发出http请求,调用该 API 接口一样。
  3. 使用简单便捷

对应的官方地址: https://docs.spring.io/spring-framework/docs/6.0.11/javadoc-api/org/springframework/web/client/RestTemplate.html

在这里插入图片描述

创建配置类: com/rainbowsea/springcloud/config/CustomizationBean.java

配置 RestTemplate 模块信息的内容。

在这里插入图片描述

package com.rainbowsea.springcloud.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration  // 标注配置类
public class CustomizationBean {// 交给 spring ioc 容器管理@Beanpublic RestTemplate getRestTemplate() {return new RestTemplate();}
}

配置好 RestTemplate 后,我们就可以写该项目的 Controller 控制器了。

com.rainbowsea.springcloud.controller 包下,创建一个名为 MemberConsumerController 的场景控制器。

在这里插入图片描述

特别说明:


@RestController
@Slf4j
public class MemberConsumerController {// 定义 MEMBER_SERVICE_PROVIDER_URL 这是一个基础 url地址// 使用 shift+ctrl+u 进行字母大小写的切换private static final String MEMBER_SERVICE_PROVIDER_URL = "http://localhost:10000";// 装配 RestTemplate bean/对象@Resourceprivate RestTemplate restTemplate;@PostMapping("/member/consumer/save")public Result<Member> save(Member member) {// 1.第1个参数: 就是请求的完整的url:MEMBER_SERVICE_PROVIDER_URL + "/member/save" => http://localhost:10000/member/save// 表示你向将该请求,发送给那个微服务处理,注意无论是返回值,还是参数, @PostMapping() 请求方式都要一一对应上对应处理的微服务上的内容//2. 第2个参数: member : 就是通过 restTemplate 发出的 post 请求携带数据或者对象//3. 第3个参数: Result.class ,微服务当中的对应处理的方法的,返回值,也就是返回对象类型// 注意:坑点log.info("member-service-consumer-80 save member={}", member);return restTemplate.postForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/save", member, Result.class);}
}
 // 1.第1个参数: 就是请求的完整的url:MEMBER_SERVICE_PROVIDER_URL + "/member/save" => http://localhost:10000/member/save// 表示你向将该请求,发送给那个微服务处理,注意无论是返回值,还是参数, @PostMapping() 请求方式都要一一对应上对应处理的微服务上的内容//2. 第2个参数: member : 就是通过 restTemplate 发出的 post 请求携带数据或者对象//3. 第3个参数: Result.class ,微服务当中的对应处理的方法的,返回值,也就是返回对象类型restTemplate.postForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/save", member, Result.class);

在这里插入图片描述

重点:特别的这里有个坑点

我们可以先测试运行试试,看看是否能够添加成功数据到数据表当中。

在这里插入图片描述

数据库添加数据失败:我们可以看到:在postman 当中返回显示添加成了,但是我们这里数据表当中,添加的都是 null 值,所以添加失败了。为什么这样呢。

我们查看后端,控制台的 Log.inof 的打印显示的内容如下:

在这里插入图片描述

解决方法:添加会员数据库中为 null 的解决方案

在 1000 端口微服务的 save 方法当中的参数列表当中添加上: @RequestBoday

添加上: @RequestBoday 因为我们使用的 RestTemplate 传输发生的数据的格式是以JSON 格式传输的。

在这里插入图片描述

在这里插入图片描述

运行测试看看是否能够添加成功了,同时看看控制台列表。注意测试的时候,因为这里我们这里修改了源码,要重新启动一下,我们的当前修改的模块。

在这里插入图片描述

member-service-provider-10000 模块当中的 Controller 的完整内容

package com.rainbowsea.springcloud.controller;import com.rainbowsea.springcloud.entity.Member;
import com.rainbowsea.springcloud.entity.Result;
import com.rainbowsea.springcloud.service.MemberService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
@Slf4j
public class MemberController {@Resourceprivate MemberService memberService;/*说明:1. 我们的前端如果是以 json 格式来发送添加信息的Member,那么我们需要使用 @RequestBody才能将数据封装到对应的 bean,同时保证http的请求的 content-type 是对应2. 如果前端是以表单形式提交了,则不需要使用@RequestBody,才会进行对象bean参数封装,同时保证 http的请求的 content-type 是对应*//*** 添加方法/接口** @param member* @return*/@PostMapping("/member/save")public Result save(@RequestBody Member member) {// 注意:微服务组件通信的坑点:// 这里我们使用 RestTemplate 传输发送的数据格式是以 json 格式的所以要添加撒谎给你 @RequestBody// 将json 格式的字符串转换为 bean对象进行赋值// 同时,我们 bean 对象传输过程中是需要序列化的。log.info("member-service-provider-10000 save member={}", member);int affected = memberService.save(member);if (affected > 0) { // 说明添加成功return Result.success("添加会员成功", affected);} else {return Result.error("401", "添加会员失败");}}/*** 这里我们使用 url占位符 + @PathVariable** @param id* @return*/@GetMapping("/member/get/{id}")public Result getMemberById(@PathVariable("id") Long id) {Member member = memberService.queryMemberById(id);// 使用 Result 把查询到的结果返回if (member != null) {return Result.success("查询会员成功", member);} else {return Result.error("402", "ID" + id + "不存在");}}}

补充说明:

这里我们对我们的 Java Bean 实现 implementsSerializable 接口,支持反序列化操作。因为 Java Bean 在网络中出传输。

在这里插入图片描述

# 对象流 ObjectInputStreamObjectOutPutStream
看一个需求:
1.int num = 100 这个int 数据保存到文件中,注意不是 100 数字,而是 int 100,并且能够从
文件中直接恢复成 int 100
2.Dog dog = new Dog("小黄",3) 这个 dog 对象保存到文件中,并且能够从文件中恢复成 Dog dog
3. 上面的要求,就是能够将基本数据类型或者对象进行“序列化” 和 “反序列化”## 序列化 和 反序列化
1.序列化就是在保存数据时,保存数据的值和数据类型
2.反序列化就是在恢复数据时,恢复数据的值和数据类型
3.需要让某个对象,支持序列化,则必须让其类是序列化的,为了让某个类是可序列化的,则
该类必须实现如下“两个接口”的其中一个
* Serializable // 这是一个标记接口,没有方法
* Externalizable // 该接口有方法需要实现,因此我们一般实现上面的 Serializable 接口,即可。

2.3.3 注意事项和具体细节

  1. 如 果 member-service-consumer-80 启 动 报 错 : springBoot 启 动 If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.

在这里插入图片描述

  1. 添加会员数据库中为 null 的解决方案

注意 微服务组件之间通信的的一个坑点 @RequestBody
注意:微服务组件通信的坑点:
这里我们使用 RestTemplate 传输发送的数据格式是以 json 格式的所以要添加撒谎给你 @RequestBody
将json 格式的字符串转换为 bean对象进行赋值同时,我们 bean 对象传输过程中是需要序列化的

在这里插入图片描述

在这里插入图片描述

3. 补充:开启 Run DashBoard

什么是 Run Dashboard

当 springcloud 的服务有多个时,管理多个服务的启动使用 run 会不好管理,这样我们就可以使用 Run Dashboard。如图:

在这里插入图片描述

新版的 2020 的 IDEA 当你同时启动两个微服务时,不会弹出启动 Run Dashboard 窗口的提示,是因为 IDEA2020 将 Run Dashboard 添加到控制台 Service 中

开启 Run Daahboard/Service 的步骤

  1. 找到你的项目/.idea/workspace.xml 文件在其中添加下面的代码即可

在这里插入图片描述

component name="RunDashboard">
<option name="configurationTypes">
<set>
<option value="SpringBootApplicationConfigurationType" />
</set>
</option>
<option name="ruleStates">
<list>
<RuleState><option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
  1. 重新启动 idea2020.2 , 会看到如下界面 , 如果没有看到这个 Services, 参考第 3 步添加一下即可。
  2. 如果没有看到这个 Services, 添加一下即可

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  1. 启动你的微服务,就会在 Service 面板上看到各个微服务模块, 也可以进行管理

在这里插入图片描述

提醒: 不同版本的 IDEA 开启 Run DashBoard 有区别,如果 IDEA 版本不同,百度下解决,即可

2.4 创建共用模块-供其它模块使用

2.4.1 需求说明/图解

具体需求如下图:

member-service-provider-10000member-service-consumer-80 两个项目模块当中都有一个共同的 Jave Bean 的内容(Meber 和 Result ) ,我们可以将其共用的共同的部分抽取出来,然后使用 maven 打包成 jar 包,然后引入到其它的模块当中使用,那么其它模块当中的 Java Bean 的内容就可以删除了,使用 打包好的 jar 包即可,提高了减少了代码的冗余度。

在这里插入图片描述

  1. 创建 Moduel & 完成配置
  2. 创建 entity, 把共用的实体类放到对应的包下
  3. 完成测试

2.4.2 具体实现步骤

  1. 创建 e_commerce_center-common-api

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

父工程的 pom.xml-会做相应变化,管理 e_commerce_center-common-api 子模块

在这里插入图片描述

尽量养成好习惯,每次添加的时候,都看上一眼,防止添加失败后,后面一些列的错误,后续找起来也比较麻烦。

  1. 编写e_commerce_center-common-api 的 pom.xml

因为当前我们的这个 api 封装的 member-service-provider-10000member-service-consumer-80 两个项目模块的共同内容,仅仅只是两个 Java Bean 所以我们目前只需要引入:lombok 一个 jar 包即可。

在这里插入图片描述

<!--  lombok 配置--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><!--<optional>true</optional>1. true 表示两个项目之间依赖不传递2. 大家可以理解 <optional>true</optional>:防止经该依赖传递到其它模块中说的再具体一些,比如: member-service-consumer-80 模块依赖了本项目,那么本项目不会把 lombok 传递给 member-service-consumer-803. 不设置 optional 或者 optional 是 false ,表示传递依赖--><optional>true</optional></dependency>
<?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>e-commerce-center</artifactId><groupId>com.rainbowsea</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>e_commerce_center-common-api</artifactId><!--    引入公共模块需要的依赖--><dependencies><!--  lombok 配置--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><!--<optional>true</optional>1. true 表示两个项目之间依赖不传递2. 大家可以理解 <optional>true</optional>:防止经该依赖传递到其它模块中说的再具体一些,比如: member-service-consumer-80 模块依赖了本项目,那么本项目不会把 lombok 传递给 member-service-consumer-803. 不设置 optional 或者 optional 是 false ,表示传递依赖--><optional>true</optional></dependency></dependencies></project>
  1. 抽取共用 API/类 这里我们需要抽取的是:Java Bean 的内容,

注意: 这里我们所设置的包名也尽量和 member-service-provider-10000member-service-consumer-80 两个项目模块的包名一致为com.rainbowsea.springcloud.entity,这样可以避免一些导包的错误。

在这里插入图片描述

package com.rainbowsea.springcloud.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Member implements Serializable { // Serializable 表示传输时的序列化操作private Long id;private String name;private String pwd;private String mobile;private String email;private Integer gender;
}
package com.rainbowsea.springcloud.entity;import java.io.Serializable;/*** 1. 用于返回结果, 利于 json 格式* 2. 这个工具类, 在网上也可找到*/
public class Result<T> implements Serializable {private String code; //状态码private String msg; //对状态说明private T data; // 返回时,携带的数据, 为了扩展性好,老师使用泛型//无参构造器public Result() {}//带参构造器-指定返回的datapublic Result(T data) {this.data = data;}//编写方法-返回需要的Result对象-表示成功的Resultpublic static Result success() {Result result = new Result<>();result.setCode("200");result.setMsg("success");return result;}//编写方法-返回需要的Result对象-表示成功的Result,同时可以携带数据//如果需要在static方法使用泛型,需要在 static <T>public static <T> Result<T> success(T data) {Result<T> result = new Result<>(data);result.setCode("200");result.setMsg("success");return result;}//编写方法-返回需要的Result对象-表示成功的Result,同时可以携带数据和指定msg//如果需要在static方法使用泛型,需要在 static <T>public static <T> Result<T> success(String msg, T data) {Result<T> result = new Result<>(data);result.setCode("200");result.setMsg(msg);return result;}//编写方法-返回需要的Result对象-表示失败的Resultpublic static Result error(String code, String msg) {Result result = new Result<>();result.setCode(code);result.setMsg(msg);return result;}public static <T> Result<T> error(String code, String msg, T data) {Result<T> result = new Result<>(data);result.setCode(code);result.setMsg(msg);return result;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public T getData() {return data;}//编写方法-返回需要的Result对象-表示失败的Result,同时可以携带数据public void setData(T data) {this.data = data;}
}
  1. 使用 Maven 打包成 jar

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

可以解压 e_commerce…jar 可以看到打包后的.class 文件

在这里插入图片描述

member-service-consumer-80 引入 e_commerce_center-common-api-1.0-SNAPSHOT.jar

删除: 删除原来 member-service-provider-10000member-service-consumer-80 两个项目模块 的 entity 包,引入:e_commerce_center-common-api 模块的打包的jar 内容。

在这里插入图片描述

member-service-consumer-80 引入e_commerce_center-common-api 模块的打包的 jar 内容

在这里插入图片描述

member-service-provider-10000 引入e_commerce_center-common-api 模块的打包的 jar 内容。

在这里插入图片描述

        <!--        引入我们自己对 bean 封装成 api 的模块内容--><dependency><groupId>com.rainbowsea</groupId><artifactId>e_commerce_center-common-api</artifactId><version>${project.version}</version></dependency>

2.4.3 测试

  1. 首先启动微服务模块: member-service-provider-10000 和 member-service-consumer-80

浏览器: http://localhost/member/consumer/get/1

在这里插入图片描述

PosMan : 测试添加会员 : http://localhost/member/consumer/save

在这里插入图片描述

3. 总结:

  1. 搭建 Spring Cloud 微服务基本环境简易架构图:

在这里插入图片描述

简单的说就是两个模块,处理业务

  • member-service-consumer-80 : 作为服务消费微服务模块,提供给客户端显示处理,连接浏览器
  • member-service-provider-10000 : 作为服务提供 消费微服务模块,处理前端实际提交的业务,进行处理
  1. 对于一个微服务 的搭建,这里我们采用父工程,利用 Maven版本仲裁 简化配置。

  2. 当我们在父项目/父工程当中配置了该 <dependencyManagement\> 的标签内容,需要注意的一点是: 这里的依赖的 jar 并没有引入到项目当中,仅仅这是一个声明而已
    <dependencyManagement> 里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要的添加依赖相对应的依赖信息。

    在这里插入图片描述

  3. 特别说明: type: pom 和 scope: import 配置使用 的作用:让多个模块之间可以多继承,解决 maven 单继承机制。

                <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.2.2.RELEASE</version><!--1.type:pom 和 scope: import 配合使用2.表示父项目的子模块,在引入 springboot 相关依赖时,锁定版本为 2.2.2.RELEASE3.通过 pom + import 解决maven单继承机制4. 子模块之间可以多继承--><type>pom</type><scope>import</scope></dependency>
  4. dependencyManagement 细节说明

  5. Result 该类用于,前后端交互的一个返回结果,同时利于 json 格式的内容上的转换。这个工具类,我们可以在网上很轻松的找到

    特别的该 Result 类当中有: 三个成员变量:

    • private String code; // 表示后端提交给前端所显示的 :状态码

    • private String msg; // 表示对后端提交的状态码的一个说明解释的内容,比如 404 提示找不到内容的提示 等等

    • private T data; // 表示对后端返回给前端的数据/携带的数据, 为了扩展性好,我们这里使用泛型,任何数据类型基本上都可以满足。

    public class Result<T> implements Serializable {private String code; //状态码private String msg; //对状态说明private T data; // 返回时,携带的数据, 为了扩展性好,老师使用泛型
    }
    

    如何在静态方法中使用泛型

    我们知道在Java当中 泛型 是在 实例化对象 才确定的,而静态方法 则是,加载类的时候就确定了的,两个内容的加载时期对应不上,所以:直接在静态方法当中使用 泛型是会报错的。如下:

    在这里插入图片描述

    解决方法就是:我们只需要在静态方法中的 static 关键字的后面加上 <T> 其泛型即可。如下:public static <T> Result<T> error(String code, String msg, T data)

    在这里插入图片描述

  6. 注意:在Spring Cloud 和 Spring Boot 当中运行测试类的话:该项目必须要有场景启动器,同时场景启动器添加上了 @SpringBootApplication 注解。才行。

    @SpringBootTest // 如果指明的路径不同;要加上注解指明(场景启动的所在包路径)// 同时一定要有场景启动器注解
    // 如果不想把测试类放到和启动类相同的包下,那就给测试类的注解加上@SpringBootTest(classes = {springbootJpaApplication.class}) 代
    

    在这里插入图片描述

在进行 SpringBoot 应用程序测试时,引入的 JUnit 是 org.junit.jupiter.api.Test

  1. 重点: 注入 RestTemplate

    RestTemplate 是 Spring 提供的用于访问 Rest 服务的模块类。

    1. RestTemplate 提供了多种便捷访问远程Http服务 的方法
    2. 说明: 大家可以这样理解,通过 RestTemplate ,我们可以发出 Http请求(支持Restful风格),
      去调用Controller 提供的 API接口,就像我们使用浏览器发出http请求,调用该 API 接口一样。
    3. 使用简单便捷

    对应的官方地址: https://docs.spring.io/spring-framework/docs/6.0.11/javadoc-api/org/springframework/web/client/RestTemplate.html

 // 1.第1个参数: 就是请求的完整的url:MEMBER_SERVICE_PROVIDER_URL + "/member/save" => http://localhost:10000/member/save// 表示你向将该请求,发送给那个微服务处理,注意无论是返回值,还是参数, @PostMapping() 请求方式都要一一对应上对应处理的微服务上的内容//2. 第2个参数: member : 就是通过 restTemplate 发出的 post 请求携带数据或者对象//3. 第3个参数: Result.class ,微服务当中的对应处理的方法的,返回值,也就是返回对象类型restTemplate.postForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/save", member, Result.class);

在这里插入图片描述

  1. 注意 微服务组件之间通信的的一个坑点 @RequestBody注意:微服务组件通信的坑点:
    这里我们使用 RestTemplate 传输发送的数据格式是以 json 格式的所以要添加撒谎给你 @RequestBody 将json 格式的字符串转换为 bean对象进行赋值同时,我们 bean 对象传输过程中是需要序列化的

    在这里插入图片描述

  2. 如何开启 IDEA 的 Run DashBoard

4. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/12798.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

微信朋友圈营销

朋友圈营销4567法则

【赵渝强老师】MySQL InnoDB的表空间

InnoDB存储引擎目前是MySQL默认的存储引擎&#xff0c;它主要由三部分组成&#xff0c;分别是&#xff1a;存储结构、内存结构和线程结构。InnoDB的存储结构又可以分为逻辑存储结构和物理存储结构。InnoDB存储引擎的逻辑存储结构和Oracle大致相同&#xff0c;所有数据都被逻辑地…

docker安装redis

1、拉取镜像 docker pull redis:latest运行之前需要再/data/redis创建redis.conf配置文件 内容如下 # bind 192.168.1.100 10.0.0.1 # bind 127.0.0.1 ::1 #bind 127.0.0.1protected-mode noport 6379tcp-backlog 511requirepass roottimeout 0tcp-keepalive 300daemonize no…

vue项目多入口文件。vue.config.js如何修改配置

我们知道vue项目是单入口。指定一个入口文件去加载他所有的依赖。如果我们希望他有多个入口文件怎么办呢&#xff1f; 我们可以在public下面新建一个html的文件 然后src下新增一个文件夹&#xff0c;用来放APP.vue和 main.js。 然后修改vue.config.js。把他的pages改成2个入…

NCC前端调用查询弹框

系统自带的查询模板 弹框 调启使用默认的 查询模板 是在 单据模板的 列表模板中&#xff0c;有个查询区域 &#xff0c;查询区域就是查询模板内容如果在列表页做客开 新增按钮 调启查询模板 无问题&#xff0c;但是目前需求是需要再卡片页面下调启系统标准的调启模板代码 //调…

SpringBoot中的注解详解(二)

四、Param() &#xff08;mapper包 Dao层&#xff09; Param()&#xff1a; 功能&#xff1a; 用于在Mapper接口的方法参数上标记参数名称&#xff0c;以便在SQL语句中引用这些参数。 参数命名&#xff1a;在Mapper接口的方法参数上使用Param注解&#xff0c;可以为参数指定一…

一文1800字使用Jmeter进行http接口性能测试!

接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。 为什么要做接口测试&#xff1f; 越底层发现b…

新版flask pin码计算

Python debug pin码计算 需开启debug from flask import Flask app Flask(__name__) app.route("/") def index():return "Hello World" app.run(debugTrue) /console路由填入上方控制台的 PIN 码即可执行 Python 命令 Flask 的 PIN 码计算仅与 werkze…

比 PyTorch 更快的嵌入Python库:FastEmbed

嵌入生成 已成为自然语言处理&#xff08;NLP&#xff09;中不可或缺的一部分。 无论是智能推荐、文本相似度计算&#xff0c;还是聊天机器人&#xff0c;嵌入技术都扮演着重要角色。然而&#xff0c;我们常常会陷入繁重的库和庞大的模型中&#xff0c;耗时费力。 今天&#…

大模型部署解决方案之TorchServe+vLLM

TorchServe 是PyTorch 中将模型部署到生产环境的一个解决方案。它用HTTP 或HTTPS API 封装模型&#xff0c;可以处理多种任务&#xff0c;包括为部署模型分配workers、负责客户端和服务器之间通信等。 10月份发布的TorchServe 0.12 增加了对GenAI的支持&#xff0c;简化了大语…

博弈论(零和博弈)英文版题解

翻译&#xff1a; 假设我们有一个两人零和游戏&#xff0c;每个玩家有两种行动&#xff0c;行收益矩阵如下&#xff1a; 计算行和列玩家的最小最大最优策略以及游戏的价值。 X Y A a11 a12 B a21 a22 选项&#xff1a; 1. 行玩家&#x…

虚拟现实辅助工程技术应用于员工培训

你还在使用传统的入职方法吗&#xff0c;比如印刷指南、演示、课堂培训、讲座等等&#xff1f;是时候改变了。虚拟现实辅助工程技术提供了一个机会&#xff0c;可以让新员工的入职过程更高效、更有趣&#xff0c;也更令人兴奋。想象一下这样一个场景&#xff0c;新员工可以在第…

【健康警钟】胆已切除,生活调理有“胆”更精彩!必看指南!

在现代社会&#xff0c;由于生活习惯、饮食习惯等多种因素&#xff0c;一些人可能不得不面对胆囊切除手术。虽然手术能够有效解决胆囊结石、胆囊炎等问题&#xff0c;但胆囊作为人体的一部分&#xff0c;其功能的丧失无疑会对生活带来一定影响。那么&#xff0c;胆被割了之后&a…

windows NGIMX配置WebSocket反向代理

linux下 据说nginx是要有 stream的模块 Linux安装Nginx步骤之后续&#xff0c;带stream模块-CSDN博客 Nginx从1.3.13版本就开始支持WebSocket linux 下参考如下链接 配置 Nginx 反向代理 WebSocket - 哈喽哈喽111111 - 博客园 (cnblogs.com) SSL的配置参考 【Linux】采用…

三种读取配置文件的方式

在编写JDBC的util包以读取文件时&#xff0c;配置文件的位置会影响其读取方式。当前&#xff0c;默认配置文件直接放置在src文件夹下。 当读取.properties文件代码写法为&#xff1a; Properties props new Properties(); props.load(new FileInputStream("db.propertie…

丹摩征文活动|CogVideoX-2b:从安装到上线,轻松搞定全过程!

CogVideoX-2b&#xff1a;从安装到上线&#xff0c;轻松搞定全过程&#xff01; CogVideoX简介 CogVideoX的推出标志着视频生成技术的一次重大突破。过去&#xff0c;如何在保持高效的同时提升视频质量一直是一个难题&#xff0c;但CogVideoX 通过其先进的3D变分自编码器&…

工位管理优化:Spring Boot企业级系统

3系统分析 3.1可行性分析 通过对本企业级工位管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本企业级工位管理系统采用SSM框架&#xff0c;JAVA作为开…

EMQX服务器的搭建,实现本地机和虚拟机之间的MQTT通信(详细教程)

前言 MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的&#xff0c;这些特点使它适用范围非常广泛。 MQTT协议中有三种身份&#xff1a;发布者&#xff08;Publish&#xff09;、代理&#xff08;Broker&#xff09;&#xff08;…

Unity 热更新 之 一篇文章完全入门AssetBundle

本篇知识来源于unity官方手册以及siki学院的相关教程,链接如下,仅作学习分享 AssetBundle&#xff08;创建打包&#xff09;入门学习(基于Unity2017) - SiKi学院|SiKi学堂 - unity|u3d|虚幻|ue4/5|java|python|人工智能|视频教程|在线课程 目录 0.热更新是什么 1.AssetBundl…

图片怎么去水印?5个简单好用的图片去水印方法分享!

在日常生活中&#xff0c;图片水印的去除需求时常涌现&#xff0c;无论是出于个人兴趣还是工作需求&#xff0c;掌握去水印技巧能让我们更自由地利用图片资源。今天&#xff0c;我们为您精心挑选并介绍五种实用的图片去水印方法&#xff0c;让您轻松上手&#xff0c;即刻提升图…