一.创建父工程
用于聚合其他微服务模块
1 新建 Maven 项目
JDK8+Maven 项目+Web
2 项目设置
- 编码的选择 UTF8
- JDK 版本的选择
3 删除 src 目录
4 配置父级 pom.xml
SpringBoot:模块探究之spring-boot-dependencies-CSDN博客
子模块能够依赖当前父级 pom.xml 配置
【Mybatis】maven配置pom.xml时找不到依赖项(已解决)-CSDN博客
从这往后配置
<!-- 表明是一个父工程,聚合管理其他模块 -->
<packaging>pom</packaging>
<!-- 项目名-->
<name>E-Commerce-Centers Maven Webapp</name>
<!-- 项目描述-->
<description>初始化微服务项目</description>
<!-- 项目url-->
<url>http://maven.apache.org</url>
<!-- 项目开发年份-->
<inceptionYear>2024</inceptionYear>
<!-- 统一配置各个依赖版本 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 指定JDK版本:8-->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- 开发测试Test-->
<junit.version>4.12</junit.version>
<!-- 日志打印,使用最新的版本的log4j,防止安全漏洞-->
<log4j.version>2.17.2</log4j.version>
<!-- 简化JavaBean:get、set、toString-->
<lombok.version>1.18.20</lombok.version>
<!-- 数据库连接mysql:与数据库mysql版本要一致,否则报错-->
<mysql.version>8.0.27</mysql.version>
<!-- 德鲁伊数据库连接池-->
<druid.version>1.1.17</druid.version>
<!-- mybatis数据库操作 -->
<mybatis.spring.boot.version>2.2.0</mybatis.spring.boot.version>
</properties>
<!-- 1. dependencyManagement 作用: 子模块继承后, 锁定版本, 子模块不用再写 version
-->
<dependencyManagement>
<dependencies>
<!-- SpringBoot-->
<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.RELEASE
3. 通过 pom + import 解决 maven 单继承机制-别的子项目也可以继承其他项目的依赖
-->
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<!-- SpringCloud与SpringBoot版本要匹配对应-->
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud 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数据库连接-该版本与properties标签内指定的版本一致-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--druid德鲁伊数据库连接池:版本与properties标签内指定的版本一致-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- myBatis:增删改查-->
<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>
<!-- 测试Test-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!-- 简化JavaBean-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- build-暂时先不要,打包:构建项目的名称-->
<!-- <build>-->
<!-- <finalName>E-Commerce-Centers</finalName>-->
<!-- </build>-->
Maven 的 dependencyManagement 说明
二.创建会员中心(service-provider)
微服务模块 service provider
当前模块主要功能:用于简单的 CRUD 增删改查
1 创建 Module 模块
该模块被父项目的 pom.xml 所管理依赖版本
模块名: member-service-provider-10000( 会员-提供服务模块-端口)
微服务模块(提供会员服务)
注意:创建子模块的位置:必须在父项目内部
复制父级项目的绝对路径,创建项目的时候,在该路径下创建子模块
子模块在父模块内,就算成功创建了子模块
查看当前子模块在父级项目内部
待子模块项目生成了项目结构后
如果创建失败,则参考如下博客,删除模块后重新创建
1-2 Pom.xml 加入相关依赖
修改 子模块 的 pom.xml , 加入相关依赖
子模块在引入依赖的时候,如果父项目也存在该依赖
子项目不指定该依赖版本,则以父项目的依赖版本为准
比如:
父项目:springboot 版本 2.2.0
子模块引入了 springboot 未指定版本,默认版本(父项目) 2.2.0
dependencys 标签中引入如下依赖即可,引入后记得刷新 Maven
<!--SpringBoot版本与父项目一致-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 如果在子工程/模块指定了 version,则以指定为准 -->
</dependency>
<!-- 老师解读
1. starter-actuator 是 springboot 程序的监控系统,
可以实现健康检查,info 信息等
2. 访问 http://localhost:10000/actuator 可以看到相关链接, 还可以做相关设置. -->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
-->
<!-- 指定了监控系统版本-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
-->
<!-- mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<!-- springBoot cloud alibaba-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<!-- 这里我们重新指定一下 version -->
<version>1.1.13</version>
</dependency>
<!-- mysql-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc
-->
<!-- jdbc连接池-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<!-- lombok-->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
1-3 创建 resources/application.yml
子模块下,新建application.yml,
注意:数据库的账号密码与数据库的 url 一定要配置正确
server:
port: 10000 #服务端-端口号
spring:
application:
name: member-service-provider #当前模块的项目名称
datasource:
type: com.alibaba.druid.pool.DruidDataSource
# driver-class-name: org.gjt.mm.mysql.Driver
#数据库地址:
#jdbc:mysql://域名:端口/数据库名称?useUnicode=true&characterEncoding=utf-8&useSSL=false
url: jdbc:mysql://localhost:3306/furns_ssm?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root #数据库名称
password: abc123 #数据库密码
mybatis:
mapperLocations: classpath:mapper/*.xml #后面 mapper 文件的位置
type-aliases-package: com.wwf.entity #指定POJO扫描包来让mybatis自动扫描到自定义的POJO。
创建项目基本结构
1-4 创建主启动类 MemberApplication
/**
* @author 卒迹
* @version 1.0
*/
//指定注解的扫描路径MVC-@Controller、@Service等等...
@SpringBootApplication(scanBasePackages = {"com.wwf"})
//指定Mapping包扫描路径
@MapperScan(basePackages = {"com.wwf.dao"})
public class MemberApplication {
public static void main(String[] args) {
SpringApplication.run(MemberApplication.class, args);
}
}
1-5 测试 Controller 是否能够正常访问
/**
* @author 卒迹
* @version 1.0
*/
@RestController
public class MemberController {
@RequestMapping("/hi")
public String hi() {
return "hi springboot";
}
}
根据 application.yml 配置的端口访问
2 创建数据库/表
#1.创建数据库
CREATE DATABASE e_commerce_center_db
#2.使用数据库
USE e_commerce_center_db
#3.创建会员表
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)
);
#4.插入1条会员信息
INSERT INTO member VALUES
(NULL, 'smith', MD5('123'), '123456789000', 'smith@sohu.com', 1);
#5.查询该会员表
SELECT * FROM member
2-0 新建 JavaBean
@AllArgsConstructor
@NoArgsConstructor
@Data
//Serializable 加上,后面可能使用
public class Member implements Serializable {
private Long id;
private String name;
private String pwd;
private String mobile;
private String email;
private Integer gender;
}
2-1 导入 Result 工具类
/**
* 1. 用于返回结果, 利于 json 格式
* 2. 这个工具类, 在网上也可找到
*/
public class Result<T> {
private String code;
private String msg;
private T data;
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;
}
public void setData(T data) {
this.data = data;
}
public Result() {
}
public Result(T data) {
this.data = data;
}
public static Result success() {
Result result = new Result<>();
result.setCode("200");
result.setMsg("success");
return result;
}
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>(data);
result.setCode("200");
result.setMsg("success");
return result;
}
public static <T> Result<T> success(String msg, T data) {
Result<T> result = new Result<>(data);
result.setCode("200");
result.setMsg(msg);
return result;
}
public 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;
}
}
2-2 新建 MemberDAO 接口
注意:一定要在启动类中,添加扫描 Mapper 的注解
@Mapper
public interface MemberDao {
// 根据id,查询会员
Member queryMemberById(Long id);
// 添加会员
int save(Member member);
}
2-3 在 /resources/mapper 资源文件下创建 MemberMapper.xml
<?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">
<!--1.先指定Mapper定义的接口的路径-->
<mapper namespace="com.wwf.dao.MemberDao">
<!--insert添加数据SQL语句-->
<!--1. id:方法名
2. parameterType:方法形参
3. useGeneratedKeys="true" keyProperty="id": id是否是自增长-->
<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>
<!--1. id:结果集映射
2. type:JavaBean路径-->
<resultMap id="BaseResultMap" type="com.wwf.entity.Member">
<!--column 表的字段
property JavaBean的字段
jdbcType 字段数据类型-->
<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>
<!-- 1. id:方法名-->
<!-- 2. parameterType:方法形参-->
<!-- 3. resultMap:其实就是返回值Member-->
<!--将查询的结果:保持到当前结果集中,该结果集是1个PoJo对象(Member)-->
<select id="queryMemberById" parameterType="Long" resultMap="BaseResultMap">
select *
from member
where id = #{id}
</select>
</mapper>
2-4 创建 Service 接口
/**
* @author 卒迹
* @version 1.0
*/
public interface MemberService {
// 查询方法(通过id获取到Member(PoJo/entity))
Member queryMemberById(Long id);
// 插入1条数据
int save(Member member);
}
2-5 创建 ServiceImpl 实现类
/**
* @author 卒迹
* @version 1.0
*/
@Service
public class MemberServiceImpl implements MemberService {// 实现了MemberService接口
@Resource
private MemberDao memberDao;// 从IOC容器中得到该DAO对象-Service层调用DAO层的方法
// 调用DAO对象的查询方法(id)
@Override
public Member queryMemberById(Long id) {
return memberDao.queryMemberById(id);
}
// 调用DAO对象的添加方法
@Override
public int save(Member member) {
return memberDao.save(member);
}
}
2-6 Controller 层
/**
* @author 卒迹
* @version 1.0
*/
@RequestMapping("/member")// 请求路径根目录
@RestController//@Controller+@ResponseBody
@Slf4j// 日志
public class MemberController {
@RequestMapping("/hi")
public String hi() {
return "hi springboot";
}
// Controller调用Service层方法
@Resource
private MemberService memberService;
//添加会员
// 接口:http://localhost:10000/member/add
// 提交的数据类型:{
// "name":"jack",
// "pwd":"123",
// "mobile":"123456789000",
// "email":"jack@sohu.com",
// "gender":"0"
// }
@PostMapping("/add")
public Result<Member> add(@RequestBody Member member) {
log.info("Member=" + member);
int affect = memberService.save(member);
if (affect < 0) {// 添加失败
return Result.error("-1", "添加失败");
}
// 添加成功-将Member以JSON格式响应给浏览器
return Result.success("添加成功", member);
}
// 查询会员-id
// 接口:http://localhost:10000/member/queryMemberById?id=1;
@GetMapping("/queryMemberById")
public Result<Member> queryMemberById(@RequestParam(value = "id") Long id) {
Member member = memberService.queryMemberById(id);
if (member == null) {
return Result.error("-1", "该用户不存在!");
}
return Result.success("查询成功", member);
}
}
2-7 修改 application.yml 配置文件中数据库的配置
2-8 PostMan 测试
添加
接口:http://localhost:10000/member/add
提交的数据类型 JSON:
{
"name":"jack",
"pwd":"123",
"mobile":"123456789000",
"email":"jack@sohu.com",
"gender":"0"
}
查询
2-9 查看数据库-添加
三.创建使用微服务模块
各个模块之间接口的相互调用的关系
service consumer-消费模块的 Controller 层
调用 service provider-模块中的接口的Controller服务的功能
思路分析:
相互访问对方接口的模块必须都要启动SpringBoot主程序
3-1 复制主项目的绝对路径
3-2 新建模块
查看当前子模块是否在父模块中
3-3 加入相关依赖 pom.xml
dependencys 标签中加入如下的依赖
<!--springBoot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 如果在子工程/模块指定了 version,则以指定为准 -->
</dependency>
<!-- 监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
3-4 刷新 Maven 项目-查看当前子项目的依赖,是否与父项目的依赖版本是一致的
3-5 配置 application.yml
/resources/ application.yml
分析:只需要配置端口即可
我们直接通过当前的接口去调用到另外的模块的接口进行增删改查
server:
port: 80
思路分析:
我们只需要启动 SpringBoot,并在 Controller 的接口方法中
调用到 service-provider 模块中 Controller 层中接口的方法
3-6 创建启动类-springBoot
/**
* @author 卒迹
* @version 1.0
*/
// scanBasePackages = {"com.wwf"} 配置包扫描注解的路径
@SpringBootApplication(scanBasePackages = {"com.wwf"})
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
3-7 创建 JavaBean
3-8 新建工具类 Result
/**
* @author 卒迹
* @version 1.0
* @author 卒迹
* @version 1.0
*/
/**
* 1. 用于返回结果, 利于 json 格式
* 2. 这个工具类, 在网上也可找到
*/
public class Result<T> {
private String code;
private String msg;
private T data;
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;
}
public void setData(T data) {
this.data = data;
}
public Result() {
}
public Result(T data) {
this.data = data;
}
public static Result success() {
Result result = new Result<>();
result.setCode("200");
result.setMsg("success");
return result;
}
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>(data);
result.setCode("200");
result.setMsg("success");
return result;
}
public static <T> Result<T> success(String msg, T data) {
Result<T> result = new Result<>(data);
result.setCode("200");
result.setMsg(msg);
return result;
}
public 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;
}
}
3-9 新建配置类
/**
* @author 卒迹
* @version 1.0
*/
@Configuration// 自动将Bean对象注入到IOC容器中
public class CustomizationBean {
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
3-10 Controller 层
通过当前模块 Controller 层的接口,
去访问另外模块中的 Controller 的接口
前提是服务的端口都要是启动的
10000 端口和80端口服务是启动的状态
3-11 测试访问当前端口为 80 的接口的方法
该端口为 80 的接口的方法
会去请求转发访问 10000 端口的 Controller 层接口的方法
http://localhost:80/member/consumer/save
80 端口的查询的接口
访问该 80 端口 的接口:
http://localhost:80/member/consumer/get/1
会去调用 10000 端口的接口
四.创建共用模块-供其他模块使用
我们可以发现在 80 和 10000 端口两个服务中,都用到了相同的 Bean
4-1 创建公共的模块 Moduel
创建 e_commerce_center-common-api
验证是否创建成功-查看父项目 pom.xml 的子模块导入情况
查看当前子模块 pom 的父级项目的依赖关系
查看当前子模块是否在父级项目内
4-2 修改当前子模块 的 pom.xml 配置
这里按照项目的实际情况,引入相应的需要封装公共模块的 api
当前我的项目,现在只需要封装 Bean,所以只需要引入 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-80
3. 不设置 optional 或者 optional 是 false,表示传递依赖
-->
<optional>true</optional>
</dependency>
<!-- 以后需要什么可以这里在引入. -->
4-3 抽取共用 API/类
@AllArgsConstructor
@NoArgsConstructor
@Data
//Serializable 加上,后面可能使用
public class Member implements Serializable {
private Long id;
private String name;
private String pwd;
private String mobile;
private String email;
private Integer gender;
}
/**
* @author 卒迹
* @version 1.0
* @author 卒迹
* @version 1.0
*/
/**
* 1. 用于返回结果, 利于 json 格式
* 2. 这个工具类, 在网上也可找到
*/
public class Result<T> {
private String code;
private String msg;
private T data;
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;
}
public void setData(T data) {
this.data = data;
}
public Result() {
}
public Result(T data) {
this.data = data;
}
public static Result success() {
Result result = new Result<>();
result.setCode("200");
result.setMsg("success");
return result;
}
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>(data);
result.setCode("200");
result.setMsg("success");
return result;
}
public static <T> Result<T> success(String msg, T data) {
Result<T> result = new Result<>(data);
result.setCode("200");
result.setMsg(msg);
return result;
}
public 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;
}
}
4-4 使用 Maven 打包成 jar
确保当前打包方式为 jar
在其他需要使用到公共部分的 模块中,引入当前打包的 Jar
该 Jar 为提取的公共的模块
<!-- 引入 e_commerce_center-common-api -->
<!-- 这里的groupId 你在创建模块的时候的groupId -->
<dependency>
<groupId>com.hspedu.springcloud</groupId>
<artifactId>e_commerce_center-common-api</artifactId>
<version>${project.version}</version>
</dependency>
删除其他服务(端口)中抽取出来的公共 entity 和 response
我这里抽取出来的 entity 和 response 这两个包
在引入 Jar 包后,在当前模块中删除这两个
如果报错了,
可以看看 maaper.xml 中,JavaBean 配置的路径是否是正确的