02.微服务基础环境搭建
创建父工程,用于聚合其他微服务模块
设置项目
配置父工程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>com.hspedu.springcloud</groupId>
<artifactId>e-commerce-center</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 表名是一个父工程,聚合管理其他模块-->
<packaging>pom</packaging>
<name>e-commerce-center</name>
<!-- 父工程进行指定版本控制-->
<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.version>2.17.2</log4j.version>
<lombok.version>1.18.20</lombok.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.17</druid.version>
<mybatis.spring.boot.version>2.2.0</mybatis.spring.boot.version>
</properties>
<!-- dependencyManagement 配置各个依赖和版本-->
<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>
<!-- 配置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>
<version>${mysql.version}</version>
</dependency>
<!-- 配置druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 配置spring.boot整合 mybatis starter-->
<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>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
创建会员中心微服务模块 -service provider
- 创建Model 完成配置
- 创建member-service-provider-10000
- 修改member-service-provider-10000,加入相关依赖
<?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.hspedu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!-- 该项目继承父项目的 groupId 是com.hspedu.springcloud 因此这里就不需要在指定groupId-->
<artifactId>member-service-provider-10000</artifactId>
<!-- 引入相关的依赖-->
<dependencies>
<!-- 引入web-starter 我们指定版本仲裁(从父项目继承了版本)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 说明:starter-actuator 是springboot程序的监控系统,可以实现系统的监控检测
可以通过http://localhost:10000/actuator 看到相关的连接,和信息
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 引入mybatis-starter-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- 引入druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<!-- 这里需要指定版本,因为父项目没有指定-->
<version>1.1.17</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>
</dependency>
<!-- starter-test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
- 创建resources/application.yml
server:
port: 10001
spring:
application:
name: member-service-provider-10000 #配置应用的名称
datasource:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/security_demo?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml #指定mapper.xml文件位置
type-aliases-package: com.hspedu.springcloud.entity #实体类所在的包,这样通过类名可以引用
- 创建主启动类MemberApplication
package com.hspedu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MemberApplication {
public static void main(String[] args) {
SpringApplication.run(MemberApplication.class,args);
}
}
- 创建数据库/表
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;
- 创建entity
- 创建Member实体类
package com.hspedu.springcloud.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Member implements Serializable{
private Long id;
private String name;
private String pwd;
private String mobile;
private String email;
private Integer gender;
}
- 创建Result返回结果实体类
package com.hspedu.springcloud.entity;
/**
* @author jiang
* @version 1.0
* 老韩说明
* 1. Result<T> 自定义泛型类
* 2. Result<T> 对象就是后端返回给前端的数据,是以json格式返回
*/
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() {
}
//带参构造器-指定返回的data
public Result(T data) {
this.data = data;
}
//编写方法-返回需要的Result对象-表示成功的Result
public 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对象-表示失败的Result
public static Result error(String code, String msg) {
Result result = new Result<>();
result.setCode(code);
result.setMsg(msg);
return result;
}
//编写方法-返回需要的Result对象-表示失败的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;
}
}
- 创建Dao:
- 创建接口:memberDao
package com.hspedu.springcloud.dao;
import com.hspedu.springcloud.entity.Member;
public interface MemberDao {
// 定义方法
// 根据id返回member数据
public Member queryMemberById(Long id);
// 添加member
public int save(Member member);
}
- 创建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">
<mapper namespace="com.hspedu.springcloud.dao.MemberDao">
<resultMap id="BaseResultMap" type="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>
<!-- 配置save
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>
</mapper>
- 完成测试
package com.hspedu.springcloud;
import com.hspedu.springcloud.dao.MemberDao;
import com.hspedu.springcloud.entity.Member;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
@Slf4j
public class MemberApplicationTest {
// 装配MemberDao
@Resource
private MemberDao memberDao;
@Test
public void queryMemberById(){
Member member = memberDao.queryMemberById(1L);
log.info("member={}",member);
}
@Test
public void save(){
Member nmw = new Member(null, "牛魔王", "123", "13000000000", "nmw@131.com", 1);
memberDao.save(nmw);
}
}
- 创建Service
- 创建接口MemberService
package com.hspedu.springcloud.service;
import com.hspedu.springcloud.entity.Member;
public interface MemberService {
// 定义方法
// 根据id返回member数据
public Member queryMemberById(Long id);
// 添加member
public int save(Member member);
}
- 创建impl实现类 MemberServiceImpl
package com.hspedu.springcloud.service.impl;
import com.hspedu.springcloud.dao.MemberDao;
import com.hspedu.springcloud.entity.Member;
import com.hspedu.springcloud.service.MemberService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class MemberServiceImpl implements MemberService {
@Resource
private MemberDao memberDao;
@Override
public Member queryMemberById(Long id) {
return memberDao.queryMemberById(id);
}
@Override
public int save(Member member) {
return memberDao.save(member);
}
}
- 完成测试
package com.hspedu.springcloud;
import com.hspedu.springcloud.dao.MemberDao;
import com.hspedu.springcloud.entity.Member;
import com.hspedu.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
@Slf4j
public class MemberApplicationTest {
// 装配MemberDao
@Resource
private MemberDao memberDao;
// 装配memberService
@Resource
private MemberService memberService;
@Test
public void queryMemberById(){
Member member = memberService.queryMemberById(2L);
log.info("member={}",member);
}
@Test
public void save(){
Member nmw = new Member(null, "狐狸精", "123", "13000000000", "hlj@131.com", 1);
memberService.save(nmw);
}
}
- 创建Controller
- 创建MemberController
package com.hspedu.springcloud.controller;
import com.hspedu.springcloud.entity.Member;
import com.hspedu.springcloud.entity.Result;
import com.hspedu.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.RestController;
import javax.annotation.Resource;
@Slf4j
@RestController
public class MemberController {
// 装配MemberService
@Resource
private MemberService memberService;
// 查询接口
@GetMapping("member/getMemberById/{id}")
public Result getMemberById(@PathVariable Long id) {
Member member = memberService.queryMemberById(id);
if (member != null) {
return Result.success("查询成功", member);
} else {
return Result.error("402", "ID=" + id + "不存在");
}
}
//编写方法,完成添加
//老韩说明
//1. 我们的前端如果是以json格式来发送添加信息furn, 那么我们需要使用@RequestBody
// , 才能将数据封装到对应的bean, 同时保证http的请求头的 content-type是对应
//2. 如果前端是以表单形式提交了,则不需要使用@RequestBody, 才会进行对象参数封装, 同时保证
// http的请求头的 content-type是对应
//3. 一会老师给小伙伴测试
@PostMapping("member/save")
public Result save(@RequestBody Member member) {
log.info("service-provider member={}",member);
int affected = memberService.save(member);
if (affected > 0) {
return Result.success("添加会员成功", affected);
} else {
return Result.error("401", "添加会员失败");
}
}
}
创建使用会员微服务模块-service consumer
- 示意图
- 测试查询会员:http://localhost/member/consumer/get/1
- 测试添加会员:http://localhost/member/consumer/save
创建Moduel & 完成配置
创建member-service-consumber-80
修改member-service-consumber-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>
<artifactId>e-commerce-center</artifactId>
<groupId>com.hspedu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>member-service-consumber-80</artifactId>
<!-- 引入相关的依赖-->
<dependencies>
<!-- 引入web-starter 我们指定版本仲裁(从父项目继承了版本)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 说明:starter-actuator 是springboot程序的监控系统,可以实现系统的监控检测
可以通过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>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
创建resorces/application.yml
server:
port: 80
spring:
application:
name: member-service-consumber-80
创建主启动类MemberConsumerApplication.java
package com.hspedu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MemberConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(MemberConsumerApplication.class,args);
}
}
业务实现
entity
创建Member
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Member implements Serializable{
private Long id;
private String name;
private String pwd;
private String mobile;
private String email;
private Integer gender;
}
创建Result
/**
* @author jiang
* @version 1.0
* 老韩说明
* 1. Result<T> 自定义泛型类
* 2. Result<T> 对象就是后端返回给前端的数据,是以json格式返回
*/
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() {
}
//带参构造器-指定返回的data
public Result(T data) {
this.data = data;
}
//编写方法-返回需要的Result对象-表示成功的Result
public 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对象-表示失败的Result
public static Result error(String code, String msg) {
Result result = new Result<>();
result.setCode(code);
result.setMsg(msg);
return result;
}
//编写方法-返回需要的Result对象-表示失败的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;
}
}
注入RestTemplate
- 基本介绍
- 创建配置CustomizationBean.java
package com.hspedu.springcloud.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* CustomizationBean:配置类
* 配置注入RestTemplate bean/对象
*/
@Configuration
public class CustomizationBean {
// 配置注入RestTemplate bean/对象
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
- 创建MemberConsumerController.java
package com.hspedu.springcloud.controller;
import com.hspedu.springcloud.entity.Member;
import com.hspedu.springcloud.entity.Result;
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.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class MemberConsumerController {
// 定义member_service_provider_url 这是一个基础url地址
public static final String MEMBER_SERVICE_PROVIDER_URL =
"http://localhost:10001";
// 装配RestTemplate
@Resource
private RestTemplate restTemplate;
// 方法/接口,根据id调用服务接口返回member对象
@GetMapping("member/consumer/getMemberById/{id}")
public Result getMemberById(@PathVariable Long id) {
return restTemplate.getForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/getMemberById/"+id,Result.class);
}
// 方法/接口 添加member对象到数据库表
@PostMapping("member/consumer/save")
public Result<Member> save(Member member){
log.info("service-consumer member={}",member);
// 拼接url
// member:就是通过restTemplate 发出的post请求携带数据
//Result.class :返回对象类型
return restTemplate.postForObject(MEMBER_SERVICE_PROVIDER_URL + "/member/save", member, Result.class);
}
}
创建共用模块-供其它模块使用
创建Moduel & 完成配置
创建 e_commerce_center-common-api
修改e_commerce_center-common-api的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>
<artifactId>e-commerce-center</artifactId>
<groupId>com.hspedu.springcloud</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>
<!-- true表示两个项目之间依赖不传递-->
<optional>true</optional>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
创建entity,把共用的实体类放到对应的包下
抽取共用API/类
entity从前面的工程拷贝即可
工程重构
使用Maven打包成jar
在member-service-consumer-80引入e_commerce_center-common-api-1.0-SNAPSHOT.jar
member-service-consumer-80 pom.xml文件引入
<!-- 引入e_commerce_center-common-api-->
<dependency>
<groupId>com.hspedu.springcloud</groupId>
<artifactId>e_commerce_center-common-api</artifactId>
<version>${project.version}</version>
</dependency>
在member-service-provider-10000引入e_commerce_center-common-api-1.0-SNAPSHOT.jar
member-service-provider-10000 pom.xml文件引入
<!-- 引入e_commerce_center-common-api-->
<dependency>
<groupId>com.hspedu.springcloud</groupId>
<artifactId>e_commerce_center-common-api</artifactId>
<version>${project.version}</version>
</dependency>
完成测试
http://localhost:81/member/consumer/getMemberById/2