1 二次開發(fā)現(xiàn)狀分析
1.1 目前二次開發(fā)的痛點
過于依賴Ecology的JDK及Jar包吹菱,對于JDK及新版本工具jar包的使用具有局限性楣黍。
模塊耦合度太高,代碼關(guān)聯(lián)性太強田巴,變量修改容易造成全局污染钠糊,class代碼升級需要停ecology服務(wù),正式環(huán)境影響用戶使用壹哺,測試環(huán)境影響項目及開發(fā)的工作效率抄伍。
二次開發(fā)的代碼和標準產(chǎn)品代碼的粘合度太高,無法提取獨立的二次開發(fā)代碼管宵,不利于知識沉淀和后期復(fù)用截珍,之前我們的代碼復(fù)用大部分是類級復(fù)用而非模塊級復(fù)用。
問題排查困難箩朴,由于代碼和標準產(chǎn)品代碼摻雜在一起岗喉,日志無法切割,排查困難炸庞。
對比產(chǎn)品開發(fā)钱床,二次開發(fā)往往未經(jīng)過針對性的壓力或系統(tǒng)測試,二次開發(fā)引發(fā)的宕機往往會波及整個EC服務(wù)埠居。
1.2 微服務(wù)的優(yōu)勢
不依賴于Ecology查牌,JDK、Jar包版本無限制滥壕,利用Maven導(dǎo)入Java依賴纸颜,易于和第三方應(yīng)用集成,支持使用不同的開發(fā)語言绎橘,允許整合最新的技術(shù)胁孙。
微服務(wù)是松耦合的,無論是開發(fā)階段還是部署階段都是獨立的。
能夠快速響應(yīng)涮较,局部修改容易稠鼻,一個服務(wù)出現(xiàn)問題不會影響整個應(yīng)用。
Springboot有成熟的整合方案狂票,對于主流的開發(fā)框架無配置集成枷餐。
內(nèi)嵌Servlet容器,無需單獨安裝容器即可獨立運行項目(默認是使用tomcat苫亦,整體以jar包的形式運行)。
利用SpringBoot整合Mybatis實現(xiàn)Sql統(tǒng)一管理和優(yōu)化怨咪,簡化Dao層代碼編寫屋剑,同時支持SQL熱部署。
微服務(wù)可以使不同的團隊專注于更小范圍的工作職責诗眨、使用獨立的技術(shù)唉匾、更安全更頻繁地部署。
1.3 待解決問題
微服務(wù)代碼版本管理及備案問題
微服務(wù)代碼部署問題(每次都打一個比較大的jar包)
微服務(wù)環(huán)境啟動問題(每次需要啟動很多個應(yīng)用服務(wù)和基礎(chǔ)設(shè)施服務(wù)匠楚,初步考慮單獨寫啟動腳本)
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)整工程目錄
在src目錄下新建包com.weavernorth.模塊名
將IDE生成的SpringbootApplication.java文件放置在模塊包的根目錄下(注:由于Controller層、Dao層要和啟動類有共同的父包奸绷,否則會出現(xiàn)掃描不到的問題,如果啟動類和 controller 沒有共同的父包梗夸,則需要在啟動上增加@ComponentScan注解)
File->Project Structure->Modules將src設(shè)置為”Sources”,刪除src/main下面的java文件夾健盒。
[圖片上傳失敗...(image-7079b8-1593312061480)]
修改application.properties后綴绒瘦,改為application.yml。
在新建的“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)]
- 打包步驟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)]
- 訪問我們剛才發(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”埋嵌。
{user_id}俱恶,如果傳入的值是111,那么解析成sql時的值為order by 111 如果傳入的值是id雹嗦,則解析成的sql為order by id.
{}: 解析為一個 JDBC 預(yù)編譯語句(prepared statement)的參數(shù)標記符,一個 #{ } 被解析為一個參數(shù)占位符 范舀。
2.4.5.3 <sql>標簽
該標簽主要定義復(fù)用的sql語句片段,在執(zhí)行的sql語句標簽直接引用即可捶惜√锩辏可以提高編碼效率、簡化代碼和提高可讀性吱七。
需要配置id熟悉汽久,表示該sql片段的唯一標識。
引用:通過<include refid=" " />標簽引用踊餐,refid的值就是<sql>的id屬性的值景醇。
<sql id="Base_Column_List">
id, question, answer
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
**<include** refid="Base_Column_List" **/>**
from java
where id = #{id,jdbcType=BIGINT}
</select>
在<sql>中也可以include其他的<sql>標簽,例如:
<sql id="sometable">
${prefix}Table
</sql>
<sql id="someinclude">
from
**<include** refid="${include_target}"**/>**
</sql>
<select id="select" resultType="map">
select
field1, field2, field3
**<include** refid="someinclude"**>**
**<property** name="prefix" value="Some"**/>**
**<property** name="include_target" value="sometable"**/>**
**</include>**
</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給忽略掉
<select id="selectByParams" parameterType="map" resultType="user">
select * from hrmresource
<where>
<if test="id != null ">id=#{id}</if>
<if test="name != null and name.length()>0" >and name=#{name}</if>
<if test="age != null and age.length()>0">and age = #{age}</if>
</where>
</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 標記會自動將其后第一個條件后的逗號忽略掉
<update>
update hrmresource
<set>
**<if** test="name != null and name.length()>0"**>**name = #{name},**</if>**
**<if** test="age != null and age .length()>0"**>**age = #{age },**</if>**
</set>
where id = #{id}
</update>
2.4.5.6 <trim>標簽
<trim> : 是一個格式化的標記碱茁,可以完成set或者是where標記的功能裸卫。
示例1:
select * from hrmresource
<trim prefix="WHERE" prefixoverride="AND |OR">
<if test="name != null and name.length()>0"> AND name=#{name}</if>
<if test="age != null and age.length()>0"> AND age=#{age}</if>
</trim>
假如說name和age的值都不為null的話打印的SQL為:select * from hrmresource where name = ‘xx’ and age = ‘xx’
在where的后面是不存在第一個and的,上面兩個屬性的意思如下:
prefix:前綴
prefixoverride:去掉第一個and或者是or
示例2:
update hrmresource
<trim prefix="set" suffixoverride="," suffix=" where id = #{id} ">
<if test="name != null and name.length()>0"> name=#{name} , </if>
<if test="age!= null and age.length()>0"> age=#{age} , </if>
</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。
<select id="selectByParams" parameterType="map" resultType="user">
select * from hrmresource where 1 = 1
<choose>
**<when** test="id !=null "**>**
AND id = #{id}
**</when** **>**
**<when** test="username != null and username != '' "**>**
AND username = #{username}
**</when** **>**
**<when** test="age != null and age !=''"**>**
AND age = #{age}
**</when** **>**
**<otherwise>**
**</otherwise>**
**</choose>**
</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ù)配置平臺
將“微服務(wù)配置平臺后端.zip”解壓覆蓋到ecology目錄(如果已經(jīng)部署過”wn_E9Mybatis.jar”,請使用“微服務(wù)配置平臺(不含Mybatis.jar)”版本)箱熬。
將\WEB-INF\config\mapper\weavernorth\MicoService\MicoService.xml注冊到WN_MyBatisConfig.xml中
[圖片上傳失敗...(image-996017-1593312061463)]
重啟服務(wù)器类垦。
訪問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>