微服务是:
微服务架构是一种架构模式,或者说是一种架构风格, 它提倡将单一的应用程序划分成一 组小的服务,每个服务运行在其独立的自己的进程内,服务之间互相协调,互相配置,为用户提供最终 价值。服务之间采用轻量级的通信机制互相沟通,每个服务都围绕着具体的业务进行构建,并且能够被 独立的部署到生产环境中,另外,应尽量避免统一的,集中式的服务管理机制,对具体的一个服务而 言,应根据业务上下文,选择合适的语言,工具对其进行构建,可以有一个非常轻量级的集中式管理来 协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储;
简单来说,就是把一个业务拆分成一个个小的模块,彻底的去耦合,,每一个微服务提供单个业务功能的服务,一个服务做一件事情,每一个服务都可以有单独的启动或销毁,拥有自己的数据库。
优点:
缺点:
springCloud入门:
SpringCloud, 基于SpringBoot提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监 控,服务网关,负载均衡,熔断器等组件,除了基于NetFlix的开源组件做高度抽象封装之外,还有一些 选型中立的开源组件。
SpringCloud利用SpringBoot的开发便利性,巧妙地简化了分布式系统基础设施的开发,SpringCloud为 开发人员提供了快速构建分布式系统的一些工具,包括配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞选,分布式会话等等,他们都可以用SpringBoot的开发风格做到一键启动和部署。
SpringBoot并没有重复造轮子,它只是将目前各家公司开发的比较成熟,经得起实际考研的服务框架组 合起来,通过SpringBoot风格进行再封装,屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套 简单易懂,易部署和易维护的分布式系统开发工具包
SpringBoot专注于快速、方便的开发单个个体微服务,SpringCloud关注全局的服务治理框架
Rest微服务构建
构建项目的步骤
先创建父项目springCloud的maven项目
并在pom添加
<!-- 打包方式--> <packaging>pom</packaging> <!-- 配置包的版本--> <properties> <junit.version>4.12</junit.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.16.18</lombok.version> </properties>
<dependencyManagement> <dependencies> <!-- spring-cloud-dependencies --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2021.0.4</version> <type>pom</type> <scope>import</scope> </dependency> <!-- spring-boot-dependencies --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.1.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!-- mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!-- druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.6</version> </dependency> <!-- mybatis-spring-boot-starter --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> </dependencies> </dependencyManagement>
删除掉src的文件夹
创建模块springcloud-api
pom.xml
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
创建dept的pojo类
package com.xflsh.springcloud.pojo; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.io.Serializable; /* 链式写法: Dept dept = new Dept() dept.setDeptno(11L).setDname("school").setDb_source("DB01"); **/ @NoArgsConstructor @Data @Accessors(chain = true) //链式写法 public class Dept implements Serializable {//Dept(实体类) orm mysql->Dept(表) 类表关系映射 private Long deptno; //主键 private String dname; //部门名称 //来自哪个数据库,因为微服务架构可以一个服务对应一个数据库,同一个信息被存到多个不同的数据库 private String db_source; public Dept(String dname) { this.dname = dname; } }
创建服务者模块springcloud-provider-dept-8001
pom.xml
<dependencies> <!-- eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.4.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <!--引入自定义的模块,我们就可以使用这个模块中的类了--> <dependency> <groupId>org.example</groupId> <artifactId>springcloud-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> </dependency> <!-- spring-boot-devtools --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies>
application.yml
server: port: 8001 #mybatis的配置 mybatis: config-location: classpath:mybatis/mybatis-config.xml type-aliases-package: com.xflsh.springcloud.pojo mapper-locations: classpath:mybatis/mapper/*.xml #spring的相关配置 spring: application: name: springcloud-provider-dept datasource: type: com.alibaba.druid.pool.DruidDataSource # 数据源 driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动 url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8 #数据库名称 username: root password: a1814995041
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <!--开启二级缓存--> <setting name="cacheEnabled" value="true"/> </settings> </configuration>
DeptDao.class
package com.xflsh.springcloud.service; import com.xflsh.springcloud.pojo.Dept; import org.springframework.stereotype.Service; import java.util.List; @Mapper public interface DeptService { public boolean addDept(Dept dept); //添加一个部门 public Dept queryById(Long id); //根据id查询部门 public List<Dept> queryAll(); //查询所有部门 }
DeptMapper.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.xflsh.springcloud.dao.DeptDao"> <insert id="addDept" parameterType="Dept"> insert into dept (dname,db_source) values (#{dname},DATABASE()); </insert> <select id="queryById" resultType="Dept" parameterType="Long"> select deptno,dname,db_source from dept where deptno = #{deptno}; </select> <select id="queryAll" resultType="Dept"> select deptno,dname,db_source from dept; </select> </mapper>
DeptService.class
package com.xflsh.springcloud.service; import com.xflsh.springcloud.pojo.Dept; import org.springframework.stereotype.Service; import java.util.List; public interface DeptService { public boolean addDept(Dept dept); //添加一个部门 public Dept queryById(Long id); //根据id查询部门 public List<Dept> queryAll(); //查询所有部门 }
DeptServiceImpl.class
package com.xflsh.springcloud.service.impl; import com.xflsh.springcloud.pojo.Dept; import com.xflsh.springcloud.dao.DeptDao; import com.xflsh.springcloud.service.DeptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class DeptServiceImpl implements DeptService { @Autowired private DeptDao deptDao; @Override public boolean addDept(Dept dept) { return deptDao.addDept(dept); } @Override public Dept queryById(Long id) { return deptDao.queryById(id); } @Override public List<Dept> queryAll() { return deptDao.queryAll(); } }
DeptController.class
package com.xflsh.springcloud.controller; import com.xflsh.springcloud.pojo.Dept; import com.xflsh.springcloud.service.DeptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/dept") public class DeptController{ @Autowired DeptService deptservice; // @RequestBody // 如果参数是放在请求体中,传入后台的话,那么后台要用@RequestBody才能接收到 @PostMapping("/add") public boolean addDept(@RequestBody Dept dept) { return deptservice.addDept(dept); } @GetMapping("/get/{id}") public Dept get(@PathVariable("id") Long id) { return deptservice.queryById(id); } @GetMapping("/list") public List<Dept> queryAll() { return deptservice.queryAll(); } }
编写启动器DeptProvider8001 .class
package com.xflsh.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DeptProvider8001 { public static void main(String[] args){ SpringApplication.run(DeptProvider8001.class,args); } }
访问http://localhost:8001/dept/list就会出数据
创建消费者模块springcloud-consumer-dept-80
<artifactId>springcloud-consumer-dept-80</artifactId> <description>部门微服务消费者</description> <dependencies> <dependency> <groupId>org.example</groupId> <artifactId>springcloud-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies>
application.yml
server: port: 80
编写配置类configBean
package com.xflsh.springcloud.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class configBean { // RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集 // 使用RestTemplate访问restful接口非常的简单粗暴且无脑 //(url,requsetMap,ResponseBean.class) 这三个参数分别代表REST请求地址,请求参数, // Http响应转换 被 转换成的对象类型 @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); } }
DeptConsumerController .class
package com.xflsh.springcloud.controller; import com.xflsh.springcloud.pojo.Dept; 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; import java.util.List; @RestController public class DeptConsumerController { //理解:消费者,不应该有service层 // 使用RestTemplate访问restful接口非常的简单粗暴且无脑 // (url,requestMap,ResponseBean.class) 这三个参数分别代表 // REST请求地址,请求参数,Http响应转换 被 转换成的对象类型 @Autowired private RestTemplate restTemplate; private static final String REST_URL_PREFIX = "http://localhost:8001"; @RequestMapping("/consumer/dept/add") public boolean add(Dept dept){ return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class); } @RequestMapping("/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id){ return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class); } @RequestMapping("/consumer/dept/list") public List<Dept> list(){ return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class); } }
启动类DeptConsumer80 .class
package com.xflsh.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DeptConsumer80 { public static void main(String[] args) { SpringApplication.run(DeptConsumer80.class,args); } }
访问http://localhost/consumer/dept/list就会出提供者一样的数据,因为80端口可以不加localhost的后面
知识盲区;
RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集 使用RestTemplate访问restful接口非常的简单粗暴且无脑 (url,requsetMap,ResponseBean.class) 这三个参数分别代表REST请求地址,请求参数, Http响应转换 被 转换成的对象类型