Ecology后端二次開發(fā)架構(gòu)說明

1 二次開發(fā)現(xiàn)狀分析

1.1 目前二次開發(fā)的痛點

  1. 過于依賴Ecology的JDK及Jar包吹菱,對于JDK及新版本工具jar包的使用具有局限性楣黍。

  2. 模塊耦合度太高,代碼關(guān)聯(lián)性太強田巴,變量修改容易造成全局污染钠糊,class代碼升級需要停ecology服務(wù),正式環(huán)境影響用戶使用壹哺,測試環(huán)境影響項目及開發(fā)的工作效率抄伍。

  3. 二次開發(fā)的代碼和標準產(chǎn)品代碼的粘合度太高,無法提取獨立的二次開發(fā)代碼管宵,不利于知識沉淀和后期復(fù)用截珍,之前我們的代碼復(fù)用大部分是類級復(fù)用而非模塊級復(fù)用。

  4. 問題排查困難箩朴,由于代碼和標準產(chǎn)品代碼摻雜在一起岗喉,日志無法切割,排查困難炸庞。

  5. 對比產(chǎn)品開發(fā)钱床,二次開發(fā)往往未經(jīng)過針對性的壓力或系統(tǒng)測試,二次開發(fā)引發(fā)的宕機往往會波及整個EC服務(wù)埠居。

1.2 微服務(wù)的優(yōu)勢

  1. 不依賴于Ecology查牌,JDK、Jar包版本無限制滥壕,利用Maven導(dǎo)入Java依賴纸颜,易于和第三方應(yīng)用集成,支持使用不同的開發(fā)語言绎橘,允許整合最新的技術(shù)胁孙。

  2. 微服務(wù)是松耦合的,無論是開發(fā)階段還是部署階段都是獨立的。

  3. 能夠快速響應(yīng)涮较,局部修改容易稠鼻,一個服務(wù)出現(xiàn)問題不會影響整個應(yīng)用。

  4. Springboot有成熟的整合方案狂票,對于主流的開發(fā)框架無配置集成枷餐。

  5. 內(nèi)嵌Servlet容器,無需單獨安裝容器即可獨立運行項目(默認是使用tomcat苫亦,整體以jar包的形式運行)。

  6. 利用SpringBoot整合Mybatis實現(xiàn)Sql統(tǒng)一管理和優(yōu)化怨咪,簡化Dao層代碼編寫屋剑,同時支持SQL熱部署。

  7. 微服務(wù)可以使不同的團隊專注于更小范圍的工作職責诗眨、使用獨立的技術(shù)唉匾、更安全更頻繁地部署。

1.3 待解決問題

  1. 微服務(wù)代碼版本管理及備案問題

  2. 微服務(wù)代碼部署問題(每次都打一個比較大的jar包)

  3. 微服務(wù)環(huán)境啟動問題(每次需要啟動很多個應(yīng)用服務(wù)和基礎(chǔ)設(shè)施服務(wù)匠楚,初步考慮單獨寫啟動腳本)

  4. Ecology的無侵入整合巍膘。

2 二次開發(fā)微服務(wù)架構(gòu)說明

2.1 微服務(wù)二次開發(fā)架構(gòu)圖

必讀:二次開發(fā)的微服務(wù)架構(gòu)因項目而異,對于大型的項目可以按照功能模塊拆分每個服務(wù)芋簿,只要涉及到多個微服務(wù)的情況必須搭建nacos和SpringCloudGetWay基礎(chǔ)設(shè)施來保障EC到微服務(wù)峡懈、微服務(wù)到微服務(wù)之前的通信,反之項目體量不大与斤、需求量不多則可以考慮拋棄nacos和springCloudGetWay(可以跳過本文章的2.4\2.5\2.6\2.7)肪康,只部署單體的SpringBoot服務(wù)即可

[圖片上傳失敗...(image-a737a4-1593312061480)]

2.2 后端代碼結(jié)構(gòu)分層

[圖片上傳失敗...(image-4680b4-1593312061480)]

2.2.1 結(jié)構(gòu)****說明

|

包名

|

說明

|
|

entity

|

實體類層撩穿。與需要操作的表結(jié)構(gòu)一致磷支,生成set和get方法,使用Lomok減少大量的模板代碼(IDE需要單獨安裝LomokPlugin)食寡。(必須)

|
|

dao

|

數(shù)據(jù)庫操作層雾狈。每個數(shù)據(jù)表的操作放在一個dao的中。Dao層的每個方法完成一個完整的數(shù)據(jù)庫操作抵皱;如果操作包含多條sql善榛,需要放在一個方法中,可以根據(jù)實際情況決定是否采用“事務(wù)”處理叨叙,該層只有方法名锭弊,方法名和Mapper.xml做一一對應(yīng)。(必須)

|
|

service

|

業(yè)務(wù)服務(wù)層擂错,調(diào)用Dao層味滞。可以通過調(diào)用多個Dao類,組合業(yè)務(wù)操作的結(jié)果剑鞍。Service層提供“方法代理”昨凡。(必須)

|
|

controller

|

控制層,用于和EC或View層通信蚁署。(必須)

|
|

aop

|

切面層,用于定義切面類便脊,方便針對于二次開發(fā)代碼進行無侵入修改。(非必須)

|
|

util

|

工具類光戈。非必須哪痰,如果有需要獨立編寫的工具類,需要放在此處久妆。(非必須)

|

2.3 構(gòu)建第一個SpringBoot工程

2.3.1 創(chuàng)建工程

直接在Idea中Create New Project --> Spring Initializr --> 填寫group晌杰、artifact -->鉤上SpringWeb(SpringBoot版本建議選擇2.3.0) --> 點下一步

[圖片上傳失敗...(image-fc9aca-1593312061480)]

[圖片上傳失敗...(image-e06e54-1593312061480)]

[圖片上傳失敗...(image-5220ff-1593312061480)]

填寫”ProjectName”后點擊”Finish”,完成項目創(chuàng)建

[圖片上傳失敗...(image-a78128-1593312061480)]

2.3.2 工程目錄結(jié)構(gòu)

|

-src

-main

    -java

        -package

            #主函數(shù),啟動類筷弦,運行它如果運行了 Tomcat肋演、Jetty、Undertow 等容器

            -SpringbootApplication  

    -resouces

        #存放靜態(tài)資源 js/css/images 等

        - statics

        #存放 html 模板文件

        - templates

        #主要的配置文件烂琴,SpringBoot啟動時候會自動加載application.yml/application.properties      

        - application.properties

#測試文件存放目錄       

-test

pom.xml 文件是Maven構(gòu)建的基礎(chǔ)爹殊,里面包含了我們所依賴JAR和Plugin的信息

  • pom.xml

|

2.3.3 調(diào)整工程目錄

  1. 在src目錄下新建包com.weavernorth.模塊名

  2. 將IDE生成的SpringbootApplication.java文件放置在模塊包的根目錄下(注:由于Controller層、Dao層要和啟動類有共同的父包奸绷,否則會出現(xiàn)掃描不到的問題,如果啟動類和 controller 沒有共同的父包梗夸,則需要在啟動上增加@ComponentScan注解

  3. File->Project Structure->Modules將src設(shè)置為”Sources”,刪除src/main下面的java文件夾健盒。

[圖片上傳失敗...(image-7079b8-1593312061480)]

  1. 修改application.properties后綴绒瘦,改為application.yml。

  2. 在新建的“com.weavernorth.模塊名”包下按照<u>“后端代碼分層</u><u>”</u><u>(2.2)</u>創(chuàng)建java分層路徑扣癣,最終效果如下:

[圖片上傳失敗...(image-9599d2-1593312061479)]

2.3.4 修改maven配置

IEDA中惰帽, File--->Settings--->Maven

查看當前的settings.xml文件路徑。

[圖片上傳失敗...(image-82ab57-1593312061479)]

打開settings.xml文件,將下圖的maven源配置進settings.xml文件中

<mirrors>

<mirror>  

    <id>nexus-aliyun</id>  

    <mirrorOf>central</mirrorOf>    

    <name>Nexus aliyun</name>  

    <url>http://maven.aliyun.com/nexus/content/groups/public</url>  

</mirror> 

</mirrors>

2.3.5 pom.xml

在創(chuàng)建Springboot工程時自動生成好父虑,不需要更改该酗,以下為示例:

|

<?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/POM/4.0.0)?[https://maven.apache.org/xsd/maven-4.0.0.xsd](https://maven.apache.org/xsd/maven-4.0.0.xsd)">  

<modelVersion>4.0.0</modelVersion>  

<parent>  

    <groupId>org.springframework.boot</groupId>  

    <artifactId>spring-boot-starter-parent</artifactId>  

    <version>2.3.0.RELEASE</version>  

    <relativePath/> <!-- lookup parent from repository -->  

</parent>  

<groupId>com.weavernorth</groupId>  

<artifactId>salary</artifactId>  

<version>0.0.1-SNAPSHOT</version>  

<name>salary</name>  

<description>The First SpringBoot Project</description>  

<properties>  

    <java.version>1.8</java.version>  

</properties>  

<dependencies>  

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

        <scope>test</scope>  

        <exclusions>  

            <exclusion>  

                <groupId>org.junit.vintage</groupId>  

                <artifactId>junit-vintage-engine</artifactId>  

            </exclusion>  

        </exclusions>  

    </dependency>  

</dependencies>  

<build>  

    <plugins>  

        <plugin>  

            <groupId>org.springframework.boot</groupId>  

            <artifactId>spring-boot-maven-plugin</artifactId>  

        </plugin>  

    </plugins>  

</build>  

</project>

|

2.3.6 創(chuàng)建實體類

com/weavernorth/salary/entity/Salary.java(建議使用Lomok生成setter/getter)

package com.weavernorth.salary.entity;

import org.springframework.stereotype.Component;

/**

  • 工資單

*/

@Component

public class Salary {

private int Hrmid;

private String HrmName;

//實發(fā)工資

private Double doubleNetSalary;

//發(fā)放日期

private String strDate;

public int getHrmid() {

    return Hrmid;

}

public void setHrmid(int hrmid) {

    Hrmid = hrmid;

}

public String getHrmName() {

    return HrmName;

}

public void setHrmName(String hrmName) {

    HrmName = hrmName;

}

public Double getDoubleNetSalary() {

    return doubleNetSalary;

}

public void setDoubleNetSalary(Double doubleNetSalary) {

    this.doubleNetSalary = doubleNetSalary;

}

public String getStrDate() {

    return strDate;

}

public void setStrDate(String strDate) {

    this.strDate = strDate;

}

}

2.3.7 創(chuàng)建Controller

com/weavernorth/salary/controller/SalaryController.java

package com.weavernorth.salary.controller;

import com.weavernorth.salary.entity.Salary;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

@RestController

@RequestMapping(value = "/api/weavernorth/hrm")

public class SalaryController {

@Autowired

Salary salary;

/**

 * 計算工資

 * @param hrmid 人員id

 * @param NetSalary 實發(fā)工資

 * @param Date 發(fā)放日期

 * @return

 */

@RequestMapping(value = "/salary/computeSalary",method= RequestMethod.GET)

public Salary computeSalary(@RequestParam int hrmid,@RequestParam Double NetSalary,@RequestParam String Date){

    salary.setHrmid(hrmid);

    salary.setDoubleNetSalary(NetSalary);

    salary.setStrDate(Date);

    return salary;

}

}

2.3.8 Maven打包

1.在IDE最右邊的側(cè)欄找到”Maven Projects”

[圖片上傳失敗...(image-2b51f6-1593312061478)]

  1. 打包步驟clean->重新編譯src->install,install成功后會在控制臺中顯示”BUILD SUCCESS”成功標志士嚎,在target目錄下會生成一個[artifactId]+[version].jar格式的jar包呜魄,此jar包則為我們打包好的微服務(wù)應(yīng)用。

[圖片上傳失敗...(image-78c3fa-1593312061478)]

2.3.9 啟動工程

2.3.9.1 本地啟動

方法一:直接運行SpringBootFirstAppApplication中的main方法

|

package com.weavernorth.salary;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public class SalaryApplication {

public static void main(String[] args) {

    SpringApplication.run(SalaryApplication.class, args);

}

}

|

啟動類的mian()方法中調(diào)用了Spring Boot的SpringApplication.run() 方法來啟動一個應(yīng)用莱衩。不同于以往的web應(yīng)用爵嗅,Spring Boot應(yīng)用沒有一行xml配置,也沒有web.xml文件笨蚁。

[圖片上傳失敗...(image-2fc4f9-1593312061478)]

方法二:以java -jar的方式啟動

maven打包完成后cd到target目錄下執(zhí)行以下命令睹晒,jar包名稱視自己情況而定

java -jar salary-0.0.1-SNAPSHOT.jar

2.3.9.2 客戶生成環(huán)境啟動(linux)

windows系統(tǒng)啟動參考 2.3.9.1

Linux環(huán)境:

(1) 確保打包無誤后趟庄,放到指定目錄(目錄隨意,不一定是lib)下

[圖片上傳失敗...(image-1b1e40-1593312061478)]

(2) 進入打包目錄下執(zhí)行:

nohup java -jar loongson-0.0.1-SNAPSHOT.jar &

[圖片上傳失敗...(image-72321b-1593312061478)]

21530是進程號

(3) 停止服務(wù)

運行成功后,查看進程 ps -aux | grep java

[圖片上傳失敗...(image-1ecbea-1593312061478)]

殺掉進程 kill -9 21530(進程號)

2.3.10 訪問工程

1.未在application.properties或application.yml設(shè)置指定端口號時,springboot應(yīng)用默認端口為8080伪很。

2.訪問http://localhost:8080出現(xiàn)以下頁面表示服務(wù)啟動正常戚啥。

[圖片上傳失敗...(image-b2e984-1593312061478)]

  1. 訪問我們剛才發(fā)布的rest接口并傳入?yún)?shù)(<u>http://localhost:8080/api/weavernorth/hrm/salary/computeSalary?hrmid=12&NetSalary=2000.0&Date=2020-05-02</u>),頁面打印我們傳入的參數(shù)表示接口測試成功锉试。

[圖片上傳失敗...(image-8439b1-1593312061478)]

2.4 SpringBoot整合Mybatis+Druid+log4j(必要)

2.4.1 添加依賴

1.在 pom.xml 中添加mybatis猫十、Druid、sqlserver呆盖、log4j依賴

|

<dependency>

<groupId>org.springframework.boot</groupId>  

<artifactId>spring-boot-starter-jdbc</artifactId> 

</dependency>

<dependency>

<groupId>com.microsoft.sqlserver</groupId>  

<artifactId>mssql-jdbc</artifactId>  

<scope>runtime</scope> 

</dependency>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>  

<artifactId>mybatis-spring-boot-starter</artifactId>  

<version>1.3.2</version> 

</dependency>

<dependency>

<groupId>com.alibaba</groupId>  

<artifactId>druid-spring-boot-starter</artifactId>  

<version>1.1.10</version> 

</dependency>

<dependency>

<groupId>log4j</groupId>  

<artifactId>log4j</artifactId>  

<version>1.2.17</version> 

</dependency>

|

2.4.2 application.yml相關(guān)配置

數(shù)據(jù)庫信息

spring:

application:

name: salary

datasource:

url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ecology2019

driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver

username: sa

password: 123456

#采用Druid連接池

type: com.alibaba.druid.pool.DruidDataSource

log4j

logging:

path: ./log

mybatis

mybatis:

mapper掃描映射文件位置

mapper-locations: classpath:config/mappers/weavernorth//.xml

configuration:

log-impl: org.apache.ibatis.logging.log4j.Log4jImpl

注意:如果將mybatis.mapper-locations配置為classpath:config/mappers//.xml即mapper接口所在的包路徑下拖云,而Spring Boot默認只打入java package -> *.java,所以我們需要給pom.xml文件添加以下內(nèi)容

 <build>

    <resources>

        <resource>

            <directory>src/main/resources</directory>

        </resource>

        <resource>

            <directory>src/main/java</directory>

            <includes>

                <include>**/*.xml</include>

            </includes>

            <filtering>true</filtering>

        </resource>

    </resources>

    <plugins>

        <plugin>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-maven-plugin</artifactId>

            <configuration>

                <includeSystemScope>true</includeSystemScope>

            </configuration>

        </plugin>

    </plugins>

</build>

2.4.3 設(shè)置log4j配置文件

在src/main/resource文件夾下新建log4j.properties文件復(fù)制以下代碼

log4j.rootLogger=DEBUG,Console

log4j.appender.Console=org.apache.log4j.ConsoleAppender

log4j.appender.Console.layout=org.apache.log4j.PatternLayout

log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

log4j.logger.org.apache=INFO

log4j.logger.com.weavernorth.salary.dao=DEBUG

2.4.4 編碼實戰(zhàn)

2.4.4.1 需求簡介

以Hrmresource為例应又,我們的目標是使用Mybatis查詢出Hrmresource中Id江兢、loginid、sex丁频、lastname字段映射到我們的User對象中,并展示在View層邑贴。

2.4.4.2 表結(jié)構(gòu)

[圖片上傳失敗...(image-65ce67-1593312061477)]

2.4.4.3 創(chuàng)建實體類

com/weavernorth/Salary/entity/User.java(建議使用Lomok生成setter/getter)

package com.example.springbootmybatis.entity;

import lombok.Data;

import org.springframework.stereotype.Component;

import javax.persistence.Id;

@Component

@Data

public class User {

/** 用戶id */

@Id

private Integer id;

/** 用戶名 */

private String loginid;

/** 性別 */

private String sex;

/** 姓名 */

private String lastname;

}

2.4.4.4 創(chuàng)建Dao類

com/weavernorth/Salary/dao/IUserDaoService.java

|

package com.weavernorth.salary.dao;

import com.weavernorth.salary.entity.User;

import org.springframework.stereotype.Repository;

import java.util.List;

@Repository

public interface IUserDaoService {

List<User> findAllUser();

}

|

2.4.4.5 創(chuàng)建Mapper配置文件

創(chuàng)建mapper的xml配置文件席里,在/src/main/resources/config/mappers/weavernorth(所有的mapper都存放在該目錄下,由于前面我們在application.yml中設(shè)置了mybatis.mapper-locations屬性拢驾,springboot會自動注冊我們設(shè)置路徑下的mapper奖磁,如果不放到該路徑下則mapper無法注冊到Mybatis中,****必要)路徑下創(chuàng)建Mapper文件:User.xml

Mapper中包含Dao類中所有需要執(zhí)行的查詢語句,命名空間要使用對應(yīng)Dao類的java路徑,sqlID和Dao類中的方法名需要一致繁疤。

注意:原則上每一個Dao類對應(yīng)至少一個mapper文件咖为,mapper的路徑分層盡量和Dao類的包功能層一致。

例如****IUserDaoService****類存在于****”****src/com/****weavernorth****/****salary****/dao****”****下稠腊,則mapper則創(chuàng)建在****”****src/main/resources****/config/mapper****s****/weavernorth/****salary****”

<?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](http://mybatis.org/dtd/mybatis-3-mapper.dtd)">

<mapper namespace="com.weavernorth.salary.dao.IUserDaoService">

<select id="findAllUser" resultType="com.weavernorth.salary.entity.User" parameterType="string">

SELECT id,loginid,lastname,sex FROM HRMRESOURCE

</select>

</mapper>

2.4.4.6 創(chuàng)建JunitTest類測試

|

package com.weavernorth.salary.dao;

import com.weavernorth.salary.dao.IUserDaoService;

import com.weavernorth.salary.entity.User;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@SpringBootTest

@RunWith(SpringRunner.class)

public class IUserMapperTest {

@Autowired

User user;

@Autowired

IUserDaoService iUserDaoService;

private static final Logger logger = LoggerFactory.getLogger(IUserMapperTest.class);

@Test

public void findAllUsers(){

    List<User> users=iUserDaoService.findAllUser();

    logger.info(users.toString());

}

}

|

2.4.4.7 執(zhí)行結(jié)果查看

運行IUserMapperTest.java躁染,查看Console中打印以下日志代表MyBatis整合成功。

[圖片上傳失敗...(image-13ee3a-1593312061476)]

2.4.5 Mapper.xml的屬性及標簽說明

2.4.5.1 常見屬性

|

屬性

|

作用

|
|

namespace

|

Dao類對應(yīng)接口的路徑

|
|

id

|

表示此段sql執(zhí)行語句的唯一標識架忌,也是接口的方法名稱【必須一致才能找到方法】

|
|

parameterType

|

表示該sql語句中需要傳入的參數(shù)吞彤, 類型要與對應(yīng)的接口方法的類型一致【可選】

|
|

resultMap

|

定義出參,調(diào)用已定義的映射管理器的id值

|
|

resultType

|

定義出參叹放,匹配普通Java類型或自定義的pojo【出參類型若不指定饰恕,將為語句類型默認類型,如語句返回值為int】

|

2.4.5.2 ${}和#{}的區(qū)別

{}會自動在你要插入字段兩端 加上引號井仰。例如:你寫的是order by #{username},傳的是 liujun,那么會解析成order by “l(fā)iujun”埋嵌。

{}是將傳入的數(shù)據(jù)直接顯示生成在sql中。如:order by{user_id}俱恶,如果傳入的值是111,那么解析成sql時的值為order by 111 如果傳入的值是id雹嗦,則解析成的sql為order by id.

{}: 解析為一個 JDBC 預(yù)編譯語句(prepared statement)的參數(shù)標記符,一個 #{ } 被解析為一個參數(shù)占位符 范舀。

{}: 僅僅為一個純碎的 string 替換,在動態(tài) SQL 解析階段將會進行變量替換俐银。在使用order by 時尿背,就需要使用

2.4.5.3 <sql>標簽

該標簽主要定義復(fù)用的sql語句片段,在執(zhí)行的sql語句標簽直接引用即可捶惜√锩辏可以提高編碼效率、簡化代碼和提高可讀性吱七。

需要配置id熟悉汽久,表示該sql片段的唯一標識。

引用:通過<include refid=" " />標簽引用踊餐,refid的值就是<sql>的id屬性的值景醇。

  1. <sql id="Base_Column_List">

  2. id, question, answer   
    
  3. </sql>

  4. <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">

  5. select   
    
  6. **<include** refid="Base_Column_List" **/>**  
    
  7. from java  
    
  8. where id = #{id,jdbcType=BIGINT}  
    
  9. </select>

在<sql>中也可以include其他的<sql>標簽,例如:

  1. <sql id="sometable">

  2. ${prefix}Table   
    
  3. </sql>

  4. <sql id="someinclude">

  5. from   
    
  6.     **<include** refid="${include_target}"**/>**   
    
  7. </sql>

  8. <select id="select" resultType="map">

  9. select   
    
  10.     field1, field2, field3   
    
  11. **<include** refid="someinclude"**>**   
    
  12.     **<property** name="prefix" value="Some"**/>**   
    
  13.     **<property** name="include_target" value="sometable"**/>**   
    
  14. **</include>**   
    
  15. </select>

2.4.5.4 <where>和<if>標簽

<where> : 主要用來替換sql語句中的where字段吝岭,他的作用主要是用來簡化sql語句中where條件判斷的書寫的

<if>:條件判斷標簽三痰,配置屬性test=" 條件字符串 ",判斷是否滿足條件窜管,滿足則執(zhí)行散劫,不滿足則跳過。

如果當id值為空時幕帆,此時打印的sql應(yīng)是:select * from hrmresource where name=“xx” and age=“xx”

where 標簽會自動將其后第一個條件的and或者是or給忽略掉

  1. <select id="selectByParams" parameterType="map" resultType="user">

  2. select * from hrmresource

  3. <where>

  4. <if test="id != null ">id=#{id}</if>

  5. <if test="name != null and name.length()>0" >and name=#{name}</if>

  6. <if test="age != null and age.length()>0">and age = #{age}</if>

  7. </where>

  8. </select>

2.4.5.5 <set>標簽

<set> : 主要用來替換sql語句中的set字段获搏,一般在update中使用。

在下述的代碼片段當中失乾,假如說現(xiàn)在三個字段都有值得話常熙,那么上面打印的SQL語句如下:

update hrmresource set name=‘xxx’ , age=‘xx’ where id=‘x’

在上面age="xx"的后是沒有逗號的,也就是說set標記已經(jīng)自動幫助我們把最后一個逗號給去掉了

set 標記會自動將其后第一個條件后的逗號忽略掉

  1. <update>

  2. update hrmresource

  3. <set>

  4. **<if** test="name != null and name.length()>0"**>**name = #{name},**</if>**  
    
  5. **<if** test="age != null and age .length()>0"**>**age = #{age },**</if>**  
    
  6. </set>

  7. where id = #{id}

  8. </update>

2.4.5.6 <trim>標簽

<trim> : 是一個格式化的標記碱茁,可以完成set或者是where標記的功能裸卫。

示例1:

  1. select * from hrmresource

  2. <trim prefix="WHERE" prefixoverride="AND |OR">

  3. <if test="name != null and name.length()>0"> AND name=#{name}</if>

  4. <if test="age != null and age.length()>0"> AND age=#{age}</if>

  5. </trim>

假如說name和age的值都不為null的話打印的SQL為:select * from hrmresource where name = ‘xx’ and age = ‘xx’

在where的后面是不存在第一個and的,上面兩個屬性的意思如下:

prefix:前綴

prefixoverride:去掉第一個and或者是or

示例2:

  1. update hrmresource

  2. <trim prefix="set" suffixoverride="," suffix=" where id = #{id} ">

  3. <if test="name != null and name.length()>0"> name=#{name} , </if>

  4. <if test="age!= null and age.length()>0"> age=#{age} , </if>

  5. </trim>

假如說name和age的值都不為null的話打印的SQL為:update hrmresource set name=‘xx’ , age=‘xx’ where id=‘x’

在age='xx’的后面不存在逗號纽竣,而且自動加了一個set前綴和where后綴彼城,上面三個屬性的意義如下,其中prefix意義如上:

suffixoverride:去掉最后一個逗號(也可以是其他的標記退个,就像是上面前綴中的and一樣)

suffix:后綴

2.4.5.7 <choose>標簽

<choose> : choose標簽是按順序判斷其內(nèi)部when標簽中的test條件出否成立募壕,如果有一個成立,則 choose 結(jié)束语盈。當 choose 中所有 when 的條件都不滿則時舱馅,則執(zhí)行 otherwise 中的sql。類似于Java 的 switch 語句刀荒,choose 為 switch代嗤,when 為 case棘钞,otherwise 則為 default。

  1. <select id="selectByParams" parameterType="map" resultType="user">

  2. select * from hrmresource where 1 = 1

  3. <choose>

  4.         **<when** test="id !=null "**>**    
    
  5.             AND id = #{id}  
    
  6.         **</when** **>**    
    
  7.         **<when** test="username != null and username != '' "**>**    
    
  8.             AND username = #{username}    
    
  9.         **</when** **>**    
    
  10.         **<when** test="age != null and age !=''"**>**    
    
  11.             AND age = #{age}    
    
  12.         **</when** **>**    
    
  13.         **<otherwise>**    
    
  14.         **</otherwise>**    
    
  15.          **</choose>**  
    
  16. </select>

2.5 SpringBoot整合Nacos(非必要)

2.5.1 下載Nacos

https://github.com/alibaba/nacos/releases

[圖片上傳失敗...(image-8eeae3-1593312061473)]

Linux版本: nacos-server-1.2.1.tar.gz

Windows版本: nacos-server-1.2.1.zip

2.5.2 啟動nacos

解壓后進入nacos/bin目錄干毅,執(zhí)行startup.cmd

jdk必須是1.8以上宜猜,并且是 64位

如果啟動成功,Nacos在8848端口綁定管理端Web應(yīng)用程序硝逢,例如在本機運行則入口是http://localhost:8848/nacos/姨拥,默認用戶名和密碼都是nacos。

閃退情況:

右鍵用編輯器打開startup.cmd

[圖片上傳失敗...(image-92ac45-1593312061473)]

[圖片上傳失敗...(image-ec2f22-1593312061473)]

本地配置的環(huán)境變量JAVA_HOME渠鸽,不能以bin目錄結(jié)尾叫乌。

2.5.3 引入Nacos

本章將描述在nacos中如何注冊服務(wù)、參數(shù)動態(tài)配置

2.5.3.1 Nacos配置中心

開發(fā)payment-service服務(wù)徽缚。

2.5.3.1.1 引入依賴

<properties>

    <java.version>1.8</java.version>

    <spring-cloud.version>Greenwich.SR1</spring-cloud.version>

    <alibaba.version>0.9.0.RELEASE</alibaba.version>

</properties>

<dependencies>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>

        <version>${alibaba.version}</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-test</artifactId>

        <scope>test</scope>

    </dependency>

</dependencies>

<dependencyManagement>

    <dependencies>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-dependencies</artifactId>

            <version>${spring-cloud.version}</version>

            <type>pom</type>

            <scope>import</scope>

        </dependency>

    </dependencies>

</dependencyManagement>
2.5.3.1.2 編寫Controller

@RestController

@RefreshScope

public class PaymentController {

@Value("${sleep:0}")

private int sleep;

final static Map<Integer, Balance> balanceMap = new HashMap() {{

    put(1, new Balance(1, 10, 1000));

    put(2, new Balance(2, 0, 10000));

    put(3, new Balance(3, 100, 0));

}

};

@RequestMapping("/pay/balance")

public Balance getBalance(Integer id) {

    System.out.println("request: /pay/balance?id=" + id + ", sleep: " + sleep);

    if(sleep > 0) {

        try {

            Thread.sleep(sleep);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    }

    if(id != null && balanceMap.containsKey(id)) {

        return balanceMap.get(id);

    }

    return new Balance(0, 0, 0);

}

}

2.5.3.1.3 實體類

public class Balance {

private int id;

private int diamond;

public int getId() {

    return id;

}

public void setId(int id) {

    this.id = id;

}

public int getDiamond() {

    return diamond;

}

public void setDiamond(int diamond) {

    this.diamond = diamond;

}

public int getTicket() {

    return ticket;

}

public void setTicket(int ticket) {

    this.ticket = ticket;

}

public String getMessage() {

    return message;

}

public void setMessage(String message) {

    this.message = message;

}

private int ticket;

private String message;

public Balance() {

}

public Balance(int id, int diamond, int ticket) {

    this(id, diamond, ticket, "OK");

}

public Balance(int id, int diamond, int ticket, String message) {

    this.id = id;

    this.diamond = diamond;

    this.ticket = ticket;

    this.message = message;

}

}

2.5.3.1.4 啟動類

@SpringBootApplication

public class SalaryApplication {

public static void main(String[] args) {

    SpringApplication.run(SalaryApplication.class, args);

}

}

2.5.3.1.5 配置文件

application.yml文件中添加下圖信息:

|

spring:

profiles:

active: dev

server:

port: 8082

sleep: 0

|

port:服務(wù)的端口號

創(chuàng)建bootstrap.yml文件,內(nèi)容如下:

其中 server-addr即Nacos的IP和端口

spring: application: name: payment-service cloud: nacos: config: server-addr: 127.0.0.1:8848

Name:服務(wù)名稱

Server-addr:監(jiān)聽nacos的ip及端口號

2.5.3.1.6 啟動服務(wù)

日志中見如下信息憨奸,代表配置成功

[圖片上傳失敗...(image-cb21a3-1593312061469)]

訪問:http://localhost:8082/pay/balance?id=1

[圖片上傳失敗...(image-59b850-1593312061469)]

2.5.3.1.7 創(chuàng)建nacos配置項動態(tài)修改配置信息

訪問nacos:http://localhost:8848/nacos

[圖片上傳失敗...(image-154fad-1593312061469)]

[圖片上傳失敗...(image-22ca19-1593312061469)]

Data ID命名規(guī)則:

  **application.name**-dev.properties

然后重新調(diào)用接口,查看輸出日志

[圖片上傳失敗...(image-ada85f-1593312061469)]

然后****將配置改為2000發(fā)布后再****調(diào)用接口凿试,查看輸出日志

[圖片上傳失敗...(image-7d5ccd-1593312061469)]

[圖片上傳失敗...(image-7d7c1f-1593312061469)]

[圖片上傳失敗...(image-aca94b-1593312061469)]

[圖片上傳失敗...(image-50215a-1593312061469)]

2.5.3.2 Nacos注冊中心

將payment-service服務(wù)注冊進nacos

2.5.3.2.1 添加依賴

<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

    <version>${alibaba.version}</version>

</dependency>

2.5.3.2.2 修改bootstrap.yml

pring:

application:

name: payment-service

cloud:

nacos:

  config:

    server-addr: 127.0.0.1:8848

  discovery:

    server-addr: 127.0.0.1:8848
2.5.3.2.3 啟動類上添加注解@EnableDiscoveryClient

@SpringBootApplication

@EnableDiscoveryClient

public class SalaryApplication {

public static void main(String[] args) {

    SpringApplication.run(SalaryApplication.class, args);

}

}

2.5.3.2.4 啟動服務(wù)并查看nacos服務(wù)列表

重啟服務(wù)排宰,查看輸出日志:

[圖片上傳失敗...(image-60c2f8-1593312061469)]

[圖片上傳失敗...(image-3b5c77-1593312061469)]

2.5.3.2.5 執(zhí)行mvc clean package把應(yīng)用打成jar包并在8082和8083端口上啟動兩個實例

|

java -jar mynacosdemo-0.0.1-SNAPSHOT.jar --server.port=8082

java -jar mynacosdemo-0.0.1-SNAPSHOT.jar --server.port=8083

|

回到Nacos后臺查看,可以看到兩個實例信息

[圖片上傳失敗...(image-336b81-1593312061469)]

點擊詳情:

[圖片上傳失敗...(image-c1ddc7-1593312061469)]

停止payment-service服務(wù)后那婉,健康實例數(shù)變?yōu)?

[圖片上傳失敗...(image-1caf32-1593312061469)]

[圖片上傳失敗...(image-731295-1593312061469)]

至此额各,服務(wù)Provider的工作完成

2.6 SpringBoot整合Feign(非必要)

本章將結(jié)合具體的應(yīng)用場景描述如何實現(xiàn)服務(wù)之間的相互調(diào)用

場景:

payment-service服務(wù)(參照2.5.3.2):

   此服務(wù)中存儲了每個人對應(yīng)的賬戶余額。

account-service服務(wù):

   此服務(wù)中存儲了人員信息吧恃。

在調(diào)用account-service服務(wù)的接口時,要同時獲取人員信息及每個人對應(yīng)的賬戶余額麻诀。

也就是說痕寓,account-service服務(wù)要調(diào)用payment-service服務(wù)的接口(使用Feign)。

2.6.1 account-service服務(wù)

新建名稱為account-service的SpringBoot應(yīng)用蝇闭,配置文件與payment-service基本相同呻率,僅修改 以下兩項,服務(wù)端口號和服務(wù)名稱:

application.yml

server.port=8081

bootstrap.yml

spring.application.name=account-service

2.6.1.1 添加依賴

<properties>

    <java.version>1.8</java.version>

    <spring-cloud.version>Greenwich.SR1</spring-cloud.version>

    <alibaba.version>0.9.0.RELEASE</alibaba.version>

    <spring-cloud-netflix.version>2.1.1.RELEASE</spring-cloud-netflix.version>

    <spring-cloud-openfeign.version>2.1.1.RELEASE</spring-cloud-openfeign.version>

</properties>

<dependencies>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>

        <version>${alibaba.version}</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

        <version>${alibaba.version}</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-openfeign</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-test</artifactId>

        <scope>test</scope>

    </dependency>

</dependencies>

<dependencyManagement>

    <dependencies>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-dependencies</artifactId>

            <version>${spring-cloud.version}</version>

            <type>pom</type>

            <scope>import</scope>

        </dependency>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-openfeign-dependencies</artifactId>

            <version>${spring-cloud-openfeign.version}</version>

            <type>pom</type>

            <scope>import</scope>

        </dependency>

    </dependencies>

</dependencyManagement>

2.6.1.2 編寫Controller

@RestController

public class AccountController {

final static Map<Integer, User> userMap = new HashMap() {{

    put(1, new User(1, "張三"));

    put(2, new User(2, "李四"));

    put(3, new User(3, "王五"));

}

};

@Autowired

private BalanceService balanceService;

@RequestMapping("/acc/user")

public User getUser(@RequestParam Integer id) {

    if(id != null && userMap.containsKey(id)) {

        User user = userMap.get(id);

        //service中去調(diào)用 另外的服務(wù)接口 獲取余額

        Balance balance = balanceService.getBalance(id);

        user.setBalance(balance);

        return user;

    }

    return new User(0, "");

}

}

2.6.1.3 編寫service

編寫B(tài)alanceService接口及實現(xiàn)類

接口:

@FeignClient(name = "payment-service", fallback = BalanceServiceImpl.class)

public interface BalanceService {

@RequestMapping(value = "/pay/balance", method = RequestMethod.GET)

Balance getBalance(@RequestParam("id") Integer id);

}

FeignClient:

name:調(diào)用服務(wù)的名稱

fallback:指定一個實現(xiàn)Feign接口的實現(xiàn)類

RequestMapping****:

value:被調(diào)用服務(wù)的接口地址

實現(xiàn)類:

@Component

public class BalanceServiceImpl implements BalanceService {

@Override

public Balance getBalance(Integer id) {

    return new Balance(0, 0, 0, "降級");

}

}

2.6.1.4 啟動account-service服務(wù)

瀏覽器訪問:http://localhost:8081/acc/user?id=1

此時在瀏覽器中可以看到余額信息,余額信息是從payment-service中獲取

[圖片上傳失敗...(image-2c96a9-1593312061466)]

查看payment-service服務(wù)的輸出日志:

[圖片上傳失敗...(image-c0b142-1593312061466)]

2.6.1.5 災(zāi)難測試

關(guān)閉一個payment-service服務(wù),然后訪問:http://localhost:8081/acc/user?id=1

發(fā)現(xiàn)服務(wù)仍然可用

[圖片上傳失敗...(image-6553e-1593312061466)]

將兩個payment-service都關(guān)閉呻引,然后訪問:http://localhost:8081/acc/user?id=1

發(fā)現(xiàn)報錯

[圖片上傳失敗...(image-ebc304-1593312061466)]

解決:

在account-service中添加依賴:

<dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>

        <version>${alibaba.version}</version>

</dependency>

在bootstrap.yml中添加

feign:

sentinel:

enabled: true

打開sentinel對Feign的支持

此時重啟account-service服務(wù)

payment-service兩個服務(wù)仍然處于關(guān)閉狀態(tài)

訪問:http://localhost:8081/acc/user?id=1

此時發(fā)現(xiàn)沒有報錯礼仗,而是返回了默認的余額信息

[圖片上傳失敗...(image-dd63af-1593312061466)]

2.7 SpringBoot整合SpringCloudGetWay(非必要)

Nacos僅僅提供了注冊中心實現(xiàn)了單服務(wù)的多實例化,如果想要實現(xiàn)負載均衡逻悠,那么還要依賴GetWay的路由和分流

2.7.1 首先分不同端口啟動兩個微服務(wù)實例元践,見2.5.4.5

2.7.2 路由

2.7.2.1 創(chuàng)建新的Spring boot項目

2.7.2.2 添加依賴

注意: Spring boot 版本 和 Spring cloud gatewaty的版本必須保持一致

<properties>

    <java.version>1.8</java.version>

    <spring-cloud.version>Greenwich.SR1</spring-cloud.version>

    <alibaba.version>0.9.0.RELEASE</alibaba.version>

</properties>

<dependencies>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-gateway</artifactId>

        <version>2.1.3.RELEASE</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-data-redis</artifactId>

        <version>1.4.0.RELEASE</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-data-redis-reactive</artifactId>

    </dependency>

    <dependency>

        <groupId>redis.clients</groupId>

        <artifactId>jedis</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>

        <version>${alibaba.version}</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

        <version>${alibaba.version}</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-test</artifactId>

        <scope>test</scope>

    </dependency>

</dependencies>

<dependencyManagement>

    <dependencies>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-dependencies</artifactId>

            <version>${spring-cloud.version}</version>

            <type>pom</type>

            <scope>import</scope>

        </dependency>

    </dependencies>

</dependencyManagement>

2.7.2.3 修改bootstrap.yml文件

spring:

application:

name: gateway

cloud:

nacos:

  config:

    server-addr: 127.0.0.1:8848

  discovery:

    server-addr: 127.0.0.1:8848

gateway:

  discovery:

    locator:

      enabled: true

  routes:

    - id: payment-router

      uri: lb://payment-service

      predicates:

        - Path=/pay/**

id: payment-router (值隨意,方便記憶并且在所有路由定義中唯一即可)

uri: lb://payment-service

lb://為固定寫法童谒,表示開啟負載均衡单旁;payment-service即服務(wù)在Nacos中注冊的名字

predicates:- Path=/pay/** (使用"Path Route Predicate Factory",規(guī)則為/pay開頭的任意URI)

2.7.2.4 修改application.yml文件

端口號改為8084

spring:

profiles:

active: dev

server:

port: 8084

sleep: 0

2.7.2.5 啟動類添加****@EnableDiscoveryClient****注解

@SpringBootApplication

@EnableDiscoveryClient

public class GetawayApplication {

public static void main(String[] args) {

    SpringApplication.run(GetawayApplication.class, args);

}

}

2.7.2.6 啟動應(yīng)用測試

啟動剛創(chuàng)建的Spring boot項目

瀏覽器訪問http://localhost:8084/pay/balance?id=2

[圖片上傳失敗...(image-19c353-1593312061464)]

請求成功饥伊,可以看出請求被分發(fā)到了 payment-service1和payment-service2中

同時查看兩個payment服務(wù)的輸出日志,并發(fā)起6次請求

可以看出多次請求被平均分配到兩個實例上

[圖片上傳失敗...(image-7a42ab-1593312061464)]

2.7.2.7 Path Route Predicate Factory

除了Path Route Predicate Factory象浑,Gateway還支持多種設(shè)置方式:

|

類型

|

示例:

|
|

After

|

After=2017-01-20T17:42:47.789-07:00[America/Denver]

|
|

Before

|

Before=2017-01-20T17:42:47.789-07:00[America/Denver]

|
|

Between

|

2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

|
|

Cookie

|

Cookie=chocolate, ch.p

|
|

Header

|

Header=X-Request-Id, \d+

|
|

Host

|

Host=**.somehost.org

|
|

Method

|

Method=GET

|
|

Path

|

Path=/foo/{segment}

|
|

Query

|

Query=baz

|
|

RemoteAddr

|

RemoteAddr=192.168.1.1/24

|

2.7.3 GetWay結(jié)合Nacos實現(xiàn)動態(tài)路由

2.7.3.1 創(chuàng)建監(jiān)聽類

Spring Cloud Gateway本身還不支持直接從Nacos動態(tài)加載路由配置表蔫饰,需要自己編寫監(jiān)聽器監(jiān)聽配置變化并刷新路由表。

NacosDynamicRouteService.java

|

package com.example.service;

import com.alibaba.fastjson.JSONObject;

import com.alibaba.nacos.api.NacosFactory;

import com.alibaba.nacos.api.config.ConfigService;

import com.alibaba.nacos.api.config.listener.Listener;

import com.alibaba.nacos.api.exception.NacosException;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.cloud.gateway.event.RefreshRoutesEvent;

import org.springframework.cloud.gateway.route.RouteDefinition;

import org.springframework.cloud.gateway.route.RouteDefinitionWriter;

import org.springframework.context.ApplicationEventPublisher;

import org.springframework.context.ApplicationEventPublisherAware;

import org.springframework.stereotype.Component;

import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.Executor;

@Component

public class NacosDynamicRouteService implements ApplicationEventPublisherAware {

private String dataId = "gateway-router";

private String group = "DEFAULT_GROUP";

@Value("${spring.cloud.nacos.config.server-addr}")

private String serverAddr;

@Autowired

private RouteDefinitionWriter routeDefinitionWriter;

private ApplicationEventPublisher applicationEventPublisher;

private static final List<String> ROUTE_LIST = new ArrayList<>();

@PostConstruct

public void dynamicRouteByNacosListener() {

    try {

        ConfigService configService = NacosFactory.createConfigService(serverAddr);

        configService.getConfig(dataId, group, 5000);

        configService.addListener(dataId, group, new Listener() {

            @Override

            public void receiveConfigInfo(String configInfo) {

                clearRoute();

                try {

                    List<RouteDefinition> gatewayRouteDefinitions = JSONObject.

parseArray(configInfo, RouteDefinition.class);

                    for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {

                        addRoute(routeDefinition);

                    }

                    publish();

                } catch (Exception e) {

                    e.printStackTrace();

                }

            }

            @Override

            public Executor getExecutor() {

                return null;

            }

        });

    } catch (NacosException e) {

        e.printStackTrace();

    }

}

private void clearRoute() {

    for(String id : ROUTE_LIST) {

        this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();

    }

    ROUTE_LIST.clear();

}

private void addRoute(RouteDefinition definition) {

    try {

        routeDefinitionWriter.save(Mono.just(definition)).subscribe();

        ROUTE_LIST.add(definition.getId());

    } catch (Exception e) {

        e.printStackTrace();

    }

}

private void publish() {

    this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));

}

@Override

public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {

    this.applicationEventPublisher = applicationEventPublisher;

}

}

|

2.7.3.2 創(chuàng)建nacos配置

代碼中監(jiān)聽的配置ID為gateway-router愉豺,按此ID在Nacos中創(chuàng)建配置

[圖片上傳失敗...(image-6baa7b-1593312061456)]

2.7.3.3 注釋bootstrap.yml中的路由配置

從bootstrap.yml中刪除路由配置篓吁,即刪除以下內(nèi)容

routes:

  - id: payment-router

    uri: lb://payment-service

    predicates:

    - Path=/pay/**

2.7.3.4 添加動態(tài)路由設(shè)置

動態(tài)路由功能修改完成,啟動gateway測試蚪拦,目前路由表中僅匹配了/acc/**的杖剪,分別測試一下/acc和/pay

[圖片上傳失敗...(image-d7be3b-1593312061464)]

[圖片上傳失敗...(image-36f15f-1593312061464)]

/acc/user請求成功轉(zhuǎn)發(fā)到account-service,而/pay/balance沒有找到匹配的路由信息外盯,與期望行為一致摘盆。

下面來動態(tài)增加/pay的路由,修改Nacos中的gateway-router配置如下:

[{

"id": "account-router",

"order": 0,

"predicates": [{

    "args": {

        "pattern": "/acc/**"

    },

    "name": "Path"

}],

"uri": "[lb://account-service](lb://account-service)"

},{

"id": "payment-router",

"order": 2,

"predicates": [{

    "args": {

        "pattern": "/pay/**"

    },

    "name": "Path"

}],

"uri": "[lb://payment-service](lb://payment-service)"

}]

不重啟gateway再次測試/pay/balance請求 饱苟,已經(jīng)可以達到訪問預(yù)期效果孩擂。

[圖片上傳失敗...(image-78f185-1593312061463)]

2.8 在ecology整合二次開發(fā)微服務(wù)

2.8.1 說明

原則上所有的ecology和微服務(wù)的交互都是通過RestApi

2.8.2 微服務(wù)配置平臺部署

2.8.2.1 部署微服務(wù)配置平臺

  1. 將“微服務(wù)配置平臺后端.zip”解壓覆蓋到ecology目錄(如果已經(jīng)部署過”wn_E9Mybatis.jar”,請使用“微服務(wù)配置平臺(不含Mybatis.jar)”版本)箱熬。

  2. 將\WEB-INF\config\mapper\weavernorth\MicoService\MicoService.xml注冊到WN_MyBatisConfig.xml中

[圖片上傳失敗...(image-996017-1593312061463)]

  1. 重啟服務(wù)器类垦。

  2. 訪問ecology->后端應(yīng)用中心->微服務(wù)配置平臺->微服務(wù)網(wǎng)關(guān)注冊平臺,如果出現(xiàn)以下頁面代表部署成功

[圖片上傳失敗...(image-727e16-1593312061463)]

2.8.2.2 使用微服務(wù)配置平臺

2.8.2.2.1 注冊網(wǎng)關(guān)

在“微服務(wù)網(wǎng)關(guān)注冊平臺”中點擊編輯,設(shè)置ServiceID城须、URL蚤认、是否啟用,URL填寫SpringCloudGetWay網(wǎng)關(guān)地址或springboot單體應(yīng)用地址都可以糕伐,ServiceID保證唯一砰琢。

[圖片上傳失敗...(image-4bde0d-1593312061463)]

2.8.2.2.2 在Action中代碼示例

|

import com.alibaba.fastjson.JSONObject;

import com.weavernorth.Developer.MicoServiceUtil;

import weaver.soa.workflow.request.RequestInfo;

import weaver.workflow.action.BaseAction;

public class SalaryPaymentAction extends BaseAction {

@Override

public String execute(RequestInfo requestInfo) {

    //獲取微服務(wù)網(wǎng)關(guān)地址

    String strMicoServiceURI= MicoServiceUtil.getMicoServiceURI("Salary");

    //獲取Requestid

    String strRequestid=requestInfo.getRequestid();

    //調(diào)用微服務(wù)

    JSONObject returnjson=MicoServiceUtil.httpGet(strMicoServiceURI+"/api/weavernorth/hrm/computeSalary?strRequestid="+strRequestid);

    if(returnjson.get("flag").equals("success")){

        return SUCCESS;

    }else{

        requestInfo.getRequestManager().setMessage(returnjson.get("message").toString());

        return "0";

    }

}

}

|

2.8.2.2.3 在JavaScript中代碼示例

<script type="text/javascript" src="/weavernorth/developer/MicoServiceUtil.js"></script>

<script>

//微服務(wù)地址

var MicoServiceURI="";

$(function(){

MicoServiceURI=getMicoServiceURI("Salary");

})

$.ajax({

        type:"get",

        url:MicoServiceURI+"/api/weavernorth/hrm/getSalaryReissue,

        contentType:"application/json",

        dataType:"json",

        success:function(jsonarray){

            console.log(jsonarray)

        }

    })

<script>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市良瞧,隨后出現(xiàn)的幾起案子陪汽,更是在濱河造成了極大的恐慌,老刑警劉巖褥蚯,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挚冤,死亡現(xiàn)場離奇詭異,居然都是意外死亡赞庶,警方通過查閱死者的電腦和手機训挡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歧强,“玉大人澜薄,你說我怎么就攤上這事√幔” “怎么了表悬?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我樊卓,道長睬关,這世上最難降的妖魔是什么奈应? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任捏肢,我火速辦了婚禮负拟,結(jié)果婚禮上抓歼,老公的妹妹穿的比我還像新娘钞螟。我一直安慰自己舟山,他們只是感情好绸狐,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著累盗,像睡著了一般寒矿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上若债,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天符相,我揣著相機與錄音,去河邊找鬼蠢琳。 笑死啊终,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的傲须。 我是一名探鬼主播蓝牲,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泰讽!你這毒婦竟也來了例衍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤已卸,失蹤者是張志新(化名)和其女友劉穎佛玄,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咬最,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年欠动,在試婚紗的時候發(fā)現(xiàn)自己被綠了永乌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡具伍,死狀恐怖翅雏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情人芽,我是刑警寧澤望几,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站萤厅,受9級特大地震影響橄抹,放射性物質(zhì)發(fā)生泄漏靴迫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一楼誓、第九天 我趴在偏房一處隱蔽的房頂上張望玉锌。 院中可真熱鬧,春花似錦疟羹、人聲如沸主守。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽参淫。三九已至,卻和暖如春愧杯,著一層夾襖步出監(jiān)牢的瞬間涎才,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工民效, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留憔维,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓畏邢,卻偏偏與公主長得像业扒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子舒萎,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345