1. 程式人生 > ><Spring Cloud>入門二 Eureka Client

<Spring Cloud>入門二 Eureka Client

1.搭建一個通用工程

1.1 pom 檔案

<?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>spring-cloud-learning</artifactId> <groupId>org.maple</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>ms-common-api</artifactId> <dependencies>
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> </project>

1.2 資料庫表

Create Table

CREATE TABLE `dept` (
  `deptno` bigint(20) NOT NULL AUTO_INCREMENT,
  `dname` varchar(60) DEFAULT NULL,
  `db_source` varchar(60) DEFAULT NULL,
  PRIMARY KEY (`deptno`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8

1.3 實體類

  此處使用了 lombok,省去了getter/setter 等編寫

package org.maple.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * @author mapleins
 * @Date 2019-01-08 21:35
 * @Desc 部門實體類
 **/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true) //可以鏈式程式設計
public class Dept implements Serializable {

    private Long deptNo;
    private String dName;
    private String db_source;//來自哪個資料庫

//    public static void main(String[] args) {
//        Dept dept = new Dept();
//        dept.setDeptNo(11l).setDName("技術部").setDb_source("dept"); //鏈式程式設計
//        System.out.println(dept);
//    }
}

2. 建立一個Department 的提供方,並且註冊服務到 eureka server 上

  實現了查詢一個部門,查詢所有部門,新增一個部門的介面

  專案結構:

    

2.1 pom 檔案

<?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>spring-cloud-learning</artifactId>
        <groupId>org.maple</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

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

    <dependencies>
        <dependency>
            <groupId>org.maple</groupId>
            <artifactId>ms-common-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </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-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
</project>

2.2 編寫 application.yml 檔案

  defaultZone 標識 註冊到哪個 Eureka Server 上

server:
  port: 8001

eureka:
  client:
    service-url:
      defaultZone: http://eureka-server01:8761/eureka/,http://eureka-server02:8762/eureka/

mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml
  type-aliases-package: org.maple.entity
  mapper-locations: classpath:mybatis/mapper/**/*.xml
spring:
  application:
    name: ms-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloudDB01
    username: root
    password: root
    dbcp2:
      min-idle: 5
      initial-size: 5
      max-total: 5
      max-wait-millis: 200

 2.3 編寫 mybatis 配置檔案,由於和spring整合後會將配置內容轉移到 Spring 配置檔案中,此處只是寫出來

<?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>

2.4 編寫Dao層以及對映檔案mapper

package org.maple.dao;

import org.apache.ibatis.annotations.Mapper;
import org.maple.entity.Dept;

import java.util.List;

/**
 * @author mapleins
 * @Date 2019-01-08 22:31
 * @Desc
 **/
@Mapper
public interface DeptDao {

    boolean addDept(Dept dept);

    Dept findById(Long deptNo);

    List<Dept> findAll();
}
<?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">
<!--namespace 名稱空間
         作用:用於繫結介面,即使用namespace將對映檔案和介面繫結,就不需要寫實現類了
-->
<mapper namespace="org.maple.dao.DeptDao">

    <select id="findById" resultType="org.maple.entity.Dept">
        SELECT deptno deptNo,dname dName,db_source
        FROM dept
        WHERE deptno = #{deptNo}
    </select>

    <select id="findAll" resultType="org.maple.entity.Dept">
        SELECT deptno deptNo,dname dName,db_source
        FROM dept
    </select>

    <insert id="addDept">
        insert into dept(dname,db_source) VALUES (${dName},DATABASE());
    </insert>
</mapper>

2.5 編寫Service層

package org.maple.service;

import org.maple.entity.Dept;

import java.util.List;

/**
 * @author mapleins
 * @Date 2019-01-08 22:41
 * @Desc
 **/
public interface DeptService {

    boolean add(Dept dept);

    Dept find(Long deptNo);

    List<Dept> list();
}
package org.maple.service.impl;

import org.maple.dao.DeptDao;
import org.maple.entity.Dept;
import org.maple.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author mapleins
 * @Date 2019-01-08 22:42
 * @Desc
 **/
@Service
public class DeptServiceImpl implements DeptService {

    @Autowired
    private DeptDao deptDao;

    @Override
    public boolean add(Dept dept) {
        return deptDao.addDept(dept);
    }

    @Override
    public Dept find(Long deptNo) {
        return deptDao.findById(deptNo);
    }

    @Override
    public List<Dept> list() {
        return deptDao.findAll();
    }
}

2.6 編寫controller 層

package org.maple.controller;

import org.maple.entity.Dept;
import org.maple.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author mapleins
 * @Date 2019-01-08 22:45
 * @Desc
 **/
@RestController
public class DeptController {

    @Autowired
    private DeptService service;

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

    @GetMapping("/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){
        return service.find(id);
    }

    @GetMapping("/dept/list")
    public List<Dept> list(){
        return service.list();
    }

}

2.7 編寫啟動類

  此處新增 @EnableEurekaClient ,說明這是一個Eureka的客戶端,並將這個工程註冊到 Eureka註冊中心上

package org.maple;

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

/**
 * @author mapleins
 * @Date 2019-01-12 17:13
 * @Desc
 **/
@SpringBootApplication
@EnableEurekaClient
public class App_Provider_Dept_8001 {

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

2.8 啟動工程

  我們可以看到 eureka 註冊中心出現了該服務的名字,說明註冊成功

  

  服務的自己調自己也是成功的

  

3. 服務的發現

3.1 在 Controller 層 注入 @DiscoveryClient ,就可以顯示服務資訊

    /**
     * 獲取服務資訊
     */
    @Autowired
    private DiscoveryClient client;

    @GetMapping("/dept/discovery")
    public Object discovery(){
        List<String> services = client.getServices();
        System.out.println("所有服務資訊:"+services);

        List<ServiceInstance> instances = client.getInstances("ms-provider-dept");
        for (ServiceInstance instance : instances) {
            System.out.println("===========serviceId:"+instance.getServiceId());
            System.out.println("===========host:"+instance.getHost());
            System.out.println("===========port:"+instance.getPort());
            System.out.println("===========uri:"+instance.getUri());
        }

        return this.client;
    }

  控制檯輸出

    

 

4. 配置 eureka info 中的資訊

 4.1 父工程pom配置

  新增maven外掛,將所有以  $[ ] 過濾

    <build>
        <!--設定info下的資訊-->
        <resources>
            <resource>
                <directory>src\main\resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <delimiters>
                        <delimiter>$[*]</delimiter>
                    </delimiters>
                </configuration>
            </plugin>
        </plugins>
    </build>

4.2 在當前服務新增依賴

        <!--管理監控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

4.3 修改application.yml

info:
  app.name: spring-cloud-learning
  company.name: mapleins
  build.artifactId: $[project.artifactId]
  build.version: $[project.version]

4.4 點進eureka介面的下列位置後

  出現如下:

     

 

5. 搭建一個消費者 來消費Department 的服務

  工程結構:

    

5.1 pom檔案

<?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>spring-cloud-learning</artifactId>
        <groupId>org.maple</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

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

    <dependencies>
        <dependency>
            <groupId>org.maple</groupId>
            <artifactId>ms-common-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

5.2 編寫yml檔案

server:
  port: 80

5.3 配置config

  @Configuration 代替了以前的 application.xml

  注入一個 RestTemplate 來實現restful 呼叫

package org.maple.cfgbean;

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

/**
 * @author mapleins
 * @Date 2019-01-09 20:07
 * @Desc spring application.xml -> @Configuration
 **/
@Configuration
public class ConfigBean {

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

5.4 編寫controller層

package org.maple.controller;

import org.maple.entity.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;

/**
 * @author mapleins
 * @Date 2019-01-09 20:10
 * @Desc
 **/
@RestController
public class DeptController_Consumer {

    private static final String REST_URL_PREFIX= "http://localhost:8001";

    /**
     * 類似httpclient (url,requestMap,ResponseBean.class)
     * 請求地址,請求引數,http響應轉換的物件型別
     */
    @Autowired
    private RestTemplate restTemplate;

    @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")
    @SuppressWarnings("unchecked")
    public List<Dept> list(){
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
    }

    @RequestMapping("/consumer/dept/discovery")
    public Object discovery(){
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery",Object.class);
    }

}

5.5 編寫啟動類 並啟動

package org.maple;

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

/**
 * @author mapleins
 * @Date 2019-01-09 20:26
 * @Desc
 **/
@SpringBootApplication
public class App_Consumer_Dept_80 {

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

  頁面呼叫: