Spring Cloud(一)入门

本贴最后更新于 1252 天前,其中的信息可能已经物是人非

一、微服务概述

  微服务架构是一种架构模式,或者说是一种架构风格, 它提倡将单一的应用程序划分成一组小的服务,每个服务运行在其独立的自己的进程内,服务之间互相协调,互相配置,为用户提供最终价值。

  服务之间采用轻量级的通信机制互相沟通,每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境中,另外,应尽量避免统一的,集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言,工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储。

优点:

  • 开发简单,开发效率提高,一个服务可能就是专一的只干一件事;
  • 微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的;
  • 微服务能使用不同的语言开发;
  • 每个微服务都有自己的存储能力,可以有自己的数据库,也可以有统一数据库。

缺点:

  • 开发人员要处理分布式系统的复杂性;
  • 多服务运维难度,随着服务的增加,运维的压力也在增大;
  • 系统部署依赖;
  • 服务间通信成本;
  • 数据一致性等等。

微服务技术栈:

image.png

二、Spring Cloud 概述

  SpringCloud 利用 SpringBoot 的开发便利性,巧妙地简化了分布式系统基础设施的开发,SpringCloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞选,分布式会话等等,他们都可以用 SpringBoot 的开发风格做到一键启动和部署。

  SpringBoot 可以离开 SpringClooud 独立使用,开发项目,但是 SpringCloud 离不开 SpringBoot,属于依赖关系。

Dubbo 和 SpringCloud 对比

image.png

最大区别:

  SpringCloud 抛弃了 Dubbo 的 RPC 通信,采用的是基于 HTTP 的 REST 方式。严格来说,这两种方式各有优劣。虽然从一定程度上来说,后者牺牲了服务调用的性能,但也避免了原生 RPC 带来的问题。而且 REST 相比 RPC 更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更加合适。

三、项目构建

总体介绍:

一个父工程带着多个子 Module 子模块

SpringCloud 父工程(Project)下依次带着 3 个子模块(Module)

  • springcloud-api 【封装的整体 entity / 接口 / 公共配置等】
  • springcloud-provider-dept-8001【服务提供者】
  • springcloud-consumer-dept-80【服务消费者】

创建父工程

新建父工程 Maven 项目 springcloud-parent,切记 Packageing 是 pom 模式。

主要是定义 POM 文件,将后续各个子模块公用的 jar 包等统一提取出来,类似一个抽象父类。

image.png

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.wlgzs</groupId>
    <artifactId>springcloud</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--打包方式 pom-->
    <packaging>pom</packaging>

    <properties>

    </properties>

    <dependencyManagement>
        <dependencies>
            <!--springCloud的依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>


            <!--SpringBoot-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.4.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.16</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.10</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</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>4.12</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.12</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

创建 api 公共模块

image.png

可以观察发现,在父工程中多了一个 Modules

image.png

编写 springcloud-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>springcloud</artifactId>
        <groupId>com.wlgzs</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-api</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

编写实体类

package com.wlgzs.springcloud.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 部门表(Dept)表实体类
 */
@Data
@AllArgsConstructor
@NoArgsConstructor

public class Dept implements Serializable {

    /**
     * 部门ID
     */
    private Integer deptId;

    /**
     * 部门名称
     */
    private String deptName;

    /**
     * 数据库
     */
    private String dbSource;

    public Dept(String deptName){
        this.deptName=deptName;
    }
}

创建 provider 模块

新建 springcloud-provider-dept-8001 模块

编辑 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>springcloud</artifactId>
        <groupId>com.wlgzs</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcolud-provider-dept-8001</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.wlgzs</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>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </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>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
</project>

编辑 application.yml

server:
  port: 8001
mybatis:
  type-aliases-package: com.wlgzs.springcloud.entity
  configuration:
    map-underscore-to-camel-case: true
spring:
  application:
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: root

编写部门的 dao 接口

package com.wlgzs.springcloud.dao;

import com.wlgzs.springcloud.entity.Dept;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;


import java.util.List;

@Mapper
public interface DeptDao {

    @Insert("insert into dept (dept_name,db_source)\n" +
            "values (#{deptName},DATABASE())")
    boolean addDept(Dept dept);

    @Select("select * from dept where dept_id = #{deptId}")
    Dept queryById(int deptId);

    @Select("select * from dept")
    List<Dept> queryAll();
}

创建 Service 服务层接口

package com.wlgzs.springcloud.service;

import com.wlgzs.springcloud.entity.Dept;

import java.util.List;

public interface DeptService {
     boolean addDept(Dept dept);

     Dept queryById(int id);

     List<Dept> queryAll();
}

ServiceImpl 实现类

package com.wlgzs.springcloud.service;

import com.wlgzs.springcloud.dao.DeptDao;
import com.wlgzs.springcloud.entity.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;


@Service
public class DeptServiceImpl implements DeptService{
    @Resource
    private DeptDao deptDao;
  
    public boolean addDept(Dept dept) {
        return deptDao.addDept(dept);
    }

    public Dept queryById(int id) {
        Dept dept=deptDao.queryById(id);
        return dept;
    }

    public List<Dept> queryAll() {
        List<Dept> depts=deptDao.queryAll();
        return depts;
    }
}

DeptController 提供 REST 服务

package com.wlgzs.springcloud.controller;

import com.wlgzs.springcloud.entity.Dept;
import com.wlgzs.springcloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class DeptController {
    @Autowired
    DeptService deptService;

    @PostMapping("/")
    public boolean addDept(@RequestBody Dept dept){
        return deptService.addDept(dept);
    }

    @GetMapping("/{id}")
    public Dept getDeptById(@PathVariable int id){
        return deptService.queryById(id);
    }

    @GetMapping("/")
    public List getAll(){
        return deptService.queryAll();
    }
}

编写 DeptProvider 的主启动类

package com.wlgzs.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
public class DeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class,args);
    }
}

启动测试

image.png

创建 consumer 模块

新建 springcloud-consumer-dept-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>springcloud</artifactId>
        <groupId>com.wlgzs</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-consumer-dept-80</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.wlgzs</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>
</project>

application.yml 配置文件

server:
  port: 80

新建一个 ConfifigBean 包注入 RestTemplate

package com.wlgzs.springcloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ConfigBean {
  
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

}

创建 Controller 包,编写 DeptConsumerController 类

package com.wlgzs.springcloud.controller;

import com.wlgzs.springcloud.entity.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * @author wlgzs-sjl
 * @date 2020/11/21 22:17
 */
@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";

    @GetMapping("/{id}")
    public Dept get(@PathVariable("id") int id){
        return restTemplate.getForObject(REST_URL_PREFIX+"/"+id,Dept.class);
    }

    @GetMapping("/")
    public List getAll(){
        return restTemplate.getForObject(REST_URL_PREFIX,List.class);
    }

    @PostMapping("/")
    public boolean add(Dept dept){
        return restTemplate.postForObject(REST_URL_PREFIX,dept,Boolean.class);
    }


}


了解 RestTemplate

  RestTemplate 提供了多种便捷访问远程 Http 服务的方法,是一种简单便捷的访问 restful 服务模板类,是 Spring 提供的用于访问 Rest 服务的客户端模板工具集

  使用 RestTemplate 访问 restful 接口非常的简单粗暴且无脑(url,requsetMap,ResponseBean.class) 这三个参数分别代表 REST 请求地址,请求参数,Http 响应转换 被 转换成的对象类型。

主启动类

package com.wlgzs.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class,args);
    }
}

参考 B 站教程狂神说 Javahttps://www.bilibili.com/video/BV1jJ411S7xr

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    941 引用 • 1458 回帖 • 150 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...