0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Spring 應(yīng)用合并之路(一):摸石頭過(guò)河

京東云 ? 來(lái)源:京東科技 李君 ? 作者:京東科技 李君 ? 2024-10-28 11:11 ? 次閱讀

作者:京東科技 李君

公司最近一年在推進(jìn)降本增效,在用盡各種手段之后,發(fā)現(xiàn)應(yīng)用太多,每個(gè)應(yīng)用都做跨機(jī)房容災(zāi)部署,則最少需要 4 臺(tái)機(jī)器(稱為容器更合適)。那么,將相近應(yīng)用做一個(gè)合并,減少維護(hù)項(xiàng)目,提高機(jī)器利用率就是一個(gè)可選方案。

?

經(jīng)過(guò)前后三次不同的折騰,最后探索出來(lái)一個(gè)可行方案。記錄一下,分享出來(lái),希望對(duì)有相關(guān)需求的研發(fā)童鞋有所幫助。下面按照四種可能的方案,分別做介紹。另外,為了方便做演示,專門整了兩個(gè)演示項(xiàng)目:

?

??diguage/merge-demo-boot — 合并項(xiàng)目,下面簡(jiǎn)稱為 boot。

??diguage/merge-demo-web — 被合并項(xiàng)目,下面簡(jiǎn)稱為 web。

?

一、Jar 包引用

?

這個(gè)方式,可能是給人印象最容易的方式。仔細(xì)思考一下,從維護(hù)性的角度來(lái)看,這個(gè)方式反而是最麻煩的方式,理由如下:

?

1.web 項(xiàng)目每次更新,都需要重新打包發(fā)布新版; boot 項(xiàng)目也需要跟著更新發(fā)布。拉一次屎,脫兩次褲子。屬實(shí)麻煩。

2.還需要考慮 web 項(xiàng)目的加載問(wèn)題,類似下面要描述的,是否共用容器:共用容器 — 這是最容器想到的方式。但是這種方式,需要解決 Bean 沖突的問(wèn)題。不共用容器 — 這種方式需要處理 web 容器如何加載的問(wèn)題。默認(rèn)應(yīng)該是無(wú)法識(shí)別。

3.?

基于這些考慮,這種方式直接被拋棄了。

?

二、倉(cāng)庫(kù)合并,公用一套容器

?

這是第一次嘗試使用的方案。也是遇到問(wèn)題最多的方案。

?

1.將兩個(gè)倉(cāng)庫(kù)做合并。

1.將 web 倉(cāng)庫(kù)的地址配置到 boot 項(xiàng)目里: git remote add web git@github.com:diguage/merge-demo-web.git;

2.在 boot 項(xiàng)目里,切出來(lái)一個(gè)分支: git switch -c web;

3.將 web 分支的提交清空: git update-ref -d HEAD,然后做一次提交;

4.將 web 項(xiàng)目的代碼克隆到 web 分支上: git pull --rebase --allow-unrelated-histories web master;注意,這里需要加 --allow-unrelated-histories 參數(shù),以允許不相干的倉(cāng)庫(kù)進(jìn)行合并。

5.從 boot 項(xiàng)目的 master 分支上,切出來(lái)一個(gè)合并分支: git switch -c merge;

6.將 web 項(xiàng)目向 boot 項(xiàng)目合并: git merge --allow-unrelated-histories web;注意,這里需要加 --allow-unrelated-histories 參數(shù),以允許不相干的倉(cāng)庫(kù)進(jìn)行合并。

7.處理代碼沖突,完成合并即可。

2.配置文件的合并于歸整。為了防止同名配置文件沖突,需要把 web 項(xiàng)目的配置文件調(diào)整到一個(gè)文件夾下,這里設(shè)定為 web 目錄。然后,需要把 web 項(xiàng)目的配置文件,讓 boot 可以加載到。這個(gè)調(diào)整相對(duì)簡(jiǎn)單,只需要一個(gè)注解即可 @ImportResource({"classpath:web/spring-cfg.xml"})。

3.調(diào)整完配置文件,接著遇到的問(wèn)題就是上面提到的 Bean 沖突的問(wèn)題。由于兩個(gè)項(xiàng)目都訪問(wèn)相同的數(shù)據(jù)庫(kù), Dao 及 Service 層很多很多類都是同名的。另外,在 web 項(xiàng)目里,Dao 是基于 iBATIS 開發(fā)的,而在 boot 項(xiàng)目里,DAO 是基于 MyBATIS 開發(fā)的。所以,只能給 web 項(xiàng)目的相關(guān)代碼做重命名(嚴(yán)謹(jǐn)一點(diǎn)是給 Spring Bean 的 beanName 做重命名操作)。這又帶來(lái)了新問(wèn)題:原來(lái)的項(xiàng)目里,注入方式是根據(jù)名稱注入的,就需要改動(dòng)大量的代碼,給相關(guān)的 Bean 變量做重命名操作。這無(wú)形中增加了很多的復(fù)雜度和不確定性。

?

經(jīng)過(guò)不斷折騰,這種方式被迫放棄。

?

三、倉(cāng)庫(kù)合并,Spring Boot 父子容器

?

在經(jīng)過(guò)上述方式折騰后,就想到了另外一個(gè)方案:可以考慮使用父子容器的方式來(lái)搞。接著就查到了這篇文章: Context Hierarchy with the Spring Boot Fluent Builder API。感覺(jué)這種方式挺不錯(cuò),就嘗試了一下。

?

1.代碼合并及文件調(diào)整,跟上述步驟類似,這個(gè)后面就不再贅述。

2.按照文章中的介紹,使用父子容器的方式來(lái)加載兩個(gè)項(xiàng)目。代碼如下:

3.原以為,這種方式屬于父子兩個(gè)容器,即使有同名的 Bean 應(yīng)該也沒(méi)有影響。但是,經(jīng)過(guò)實(shí)踐才發(fā)現(xiàn),上面這個(gè)猜測(cè)是錯(cuò)誤的。Spring Boot 在啟動(dòng)的時(shí)候,它背后做了檢查,如果兩個(gè)容器有同名的 Bean,它也會(huì)報(bào)錯(cuò)。也會(huì)帶來(lái)像上述方式那樣的大量重命名。折騰一兩天,最后還是放棄了這種寄予厚望的方式。

package com.diguage.demo.boot;

import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

/**
 * @author D瓜哥 · https://www.diguage.com
 */
public class DemoBootApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder()
                .parent(BootConfig.class).web(WebApplicationType.NONE)
                .child(WebConfig.class)
                // 如果有第三個(gè)項(xiàng)目,可以作為子容器的兄弟容器加載。
                // .sibling(SiblingConfig.class)
                .run(args);
    }

    @Configuration
    @ImportResource({"classpath:spring-cfg.xml"})
    @ComponentScan(basePackages = "com.diguage.demo.boot")
    public static class BootConfig {
    }

    @Configuration
    @ImportResource({"classpath:web/spring-cfg.xml"})
    public static class WebConfig {
    }
}

?
Spring Boot 背后是否做了檢查,這個(gè)是根據(jù)報(bào)錯(cuò)信息的猜測(cè),沒(méi)有翻看代碼,所以這個(gè)猜測(cè)有一定的不確定性。有機(jī)會(huì)翻一下代碼,查看一下具體原因。

革命尚未成功,且聽下回分解……

下文:Spring 應(yīng)用合并之路(二):峰回路轉(zhuǎn),柳暗花明?

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    337

    瀏覽量

    14290
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    java spring教程

    java spring教程理解Spring 實(shí)現(xiàn)原理掌握Spring IOC,AOP掌握Spring的基礎(chǔ)配置和用法熟練使用SSH開發(fā)項(xiàng)目Sprin
    發(fā)表于 09-11 11:09

    什么是java spring

    什么是java springSpring是個(gè)開源框架,它由Rod Johnson創(chuàng)建。它是為了解決企業(yè)應(yīng)用開發(fā)的復(fù)雜性而創(chuàng)建的。Spring使用基本的JavaBean來(lái)完成以前只可能由EJB完成
    發(fā)表于 09-11 11:16

    Spring工作原理

    2.AOP的主要原理:動(dòng)態(tài)代理Spring工作原理Spring 已經(jīng)用過(guò)段時(shí)間了,感覺(jué)Spring是個(gè)很不錯(cuò)的框架。內(nèi)部最核心的就是IOC了,動(dòng)態(tài)注入,讓
    發(fā)表于 07-10 07:41

    Spring框架的設(shè)計(jì)理念

    Spring作為現(xiàn)在最優(yōu)秀的框架之,已被廣泛的使用,51CTO也曾經(jīng)針對(duì)Spring框架中的hqC應(yīng)用做過(guò)報(bào)道。本文將從另外個(gè)視角試圖剖析出Sp
    發(fā)表于 07-15 08:17

    Spring筆記分享

    框架:高度抽取,可重用代碼的種設(shè)計(jì)高度的通用性多個(gè)可重用模塊的集合,形成某個(gè)領(lǐng)域的整體解決方案Spring => 容器框架包含并管理應(yīng)用對(duì)象的生命周期IOC和SOP容器框架容器 =>
    發(fā)表于 11-04 07:51

    Spring認(rèn)證」Spring Hello World 項(xiàng)目示例

    讓我們開始使用 Spring Framework 進(jìn)行實(shí)際編程。在開始使用 Spring 框架編寫第個(gè)示例之前,您必須確保已按照Spring - 環(huán)境設(shè)置章節(jié)中的說(shuō)明正確設(shè)置了
    發(fā)表于 08-17 13:49

    如何通過(guò)指針將字符串存放到高128字節(jié)?keil該怎樣設(shè)置?

    ;,str);結(jié)果沒(méi)有顯示。在keil里設(shè)置了存儲(chǔ)模式為large:varabes in PDATA也沒(méi)用。應(yīng)該是那里沒(méi)設(shè)置好,以前直用匯編編程沒(méi)碰到這些事情,現(xiàn)在嘗試學(xué)習(xí)用C51編寫,好多地方都在石頭
    發(fā)表于 10-23 20:30

    spring教程ppt

    主要內(nèi)容Spring 概述Spring 整體結(jié)構(gòu)Spring實(shí)例Spring核心概念介紹控制反轉(zhuǎn)(IOC)依賴注入(DI)
    發(fā)表于 09-11 11:00 ?138次下載
    <b class='flag-5'>spring</b>教程ppt

    Skyworks逆襲靠什么?

    而在2002年由Alpha Industries和Conexant的無(wú)線通信部門合并而成的Skyworks則更像個(gè)摸著石頭過(guò)河的無(wú)名小輩,直到2009年Skyworks才決定集中精力發(fā)展射頻前端市場(chǎng)。
    的頭像 發(fā)表于 05-17 09:19 ?5301次閱讀
    Skyworks逆襲靠什么?

    Spring認(rèn)證_什么是Spring GraphQL

    GraphQL 支持通過(guò) HTTP 和 WebSocket 的 GraphQL 請(qǐng)求。 HTTP GraphQlHttpHandler 通過(guò) HTTP 請(qǐng)求處理 GraphQL,并委托給 Web 攔截執(zhí)行請(qǐng)求。有兩種變體,種用于 Spring MVC,
    的頭像 發(fā)表于 08-06 14:30 ?675次閱讀
    <b class='flag-5'>Spring</b>認(rèn)證_什么是<b class='flag-5'>Spring</b> GraphQL

    Spring認(rèn)證」什么是Spring GraphQL?

    這個(gè)項(xiàng)目建立在 Boot 2.x 上,但它應(yīng)該與最新的 Boot2.4.x5 相關(guān)。 要?jiǎng)?chuàng)建項(xiàng)目,請(qǐng)轉(zhuǎn)到start.spring.io并為要使用的GraphQL傳輸選擇啟動(dòng)器: 啟動(dòng)機(jī) 運(yùn)輸 執(zhí)行
    的頭像 發(fā)表于 08-10 14:08 ?784次閱讀
    「<b class='flag-5'>Spring</b>認(rèn)證」什么是<b class='flag-5'>Spring</b> GraphQL?

    為什么要學(xué)習(xí)Spring?Spring核心基礎(chǔ)教程詳解?

    為什么要學(xué)習(xí)SpringSpring 框架是個(gè)開源的 Java 平臺(tái)。它最初由 Rod Johnson 編寫,并于 2003 年 6 月在 Apache 2.0 許可下首次發(fā)布。 Spr
    的頭像 發(fā)表于 08-11 16:00 ?580次閱讀
    為什么要學(xué)習(xí)<b class='flag-5'>Spring</b>?<b class='flag-5'>Spring</b>核心基礎(chǔ)教程詳解?

    Spring認(rèn)證」Spring IoC 容器

    ,我們將在下章中討論。 容器通過(guò)讀取提供的配置元數(shù)據(jù)來(lái)獲取有關(guān)要實(shí)例化、配置和配置哪些對(duì)象的指令。數(shù)據(jù)可以由XML、Java注釋或Java代碼表示。下圖展示了Spring如何工作的高級(jí)視圖。 IoC
    的頭像 發(fā)表于 06-28 13:27 ?719次閱讀
    「<b class='flag-5'>Spring</b>認(rèn)證」<b class='flag-5'>Spring</b> IoC 容器

    Spring認(rèn)證是什么?

    Spring?Certified?Professional?2022 Spring Professional認(rèn)證旨在測(cè)試和驗(yàn)證學(xué)生對(duì) SpringSpring Boot核心方面的
    的頭像 發(fā)表于 07-04 10:19 ?1261次閱讀
    <b class='flag-5'>Spring</b>認(rèn)證是什么?

    Spring Boot 的設(shè)計(jì)目標(biāo)

    什么是Spring Boot Spring Boot 是 Spring 開源組織下的個(gè)子項(xiàng)目,也是 Spring 組件
    的頭像 發(fā)表于 10-13 14:56 ?539次閱讀
    <b class='flag-5'>Spring</b> Boot 的設(shè)計(jì)目標(biāo)