Spring+zookeeper+dubbo構建微服務項目框架

整個項目源碼我已經(jīng)提交到Github上面了精绎,大家可以去看一下項目源碼地址

1鄙早、首先上搭建好的項目結構:

分層多模塊web項目(微服務架構)
SpringMVC+Spring+mybatis-plus 集成redis

  • commons-parent是父級項目管理子項目的maven jar包的版本信息酗昼。

  • commons-util是項目中一些公共類型的存放模塊冲秽。

  • commons-config是項目中通用配置文件的存放模塊

  • commons-manaeger是微服務內(nèi)聚項目

    • commons-mananger-dao dao層代碼(持久層代碼在這里只洒,mybatis-plus的Mapper也是放在這里)
    • commons-manager-interface 接口類的存放模塊
    • commons-manager-model model和pojo類型的存放路徑
    • commons-manager-service 服務提供者
    • commons-manager-web 服務消費者

    整體的項目目錄樹如上圖纵苛。
    項目創(chuàng)建的具體過程就不在這里貼出來了夜惭,使用idea構建這種多模塊內(nèi)聚項目還是很簡單姻灶。

    201801.png

2、啟動相應的前置中間件服務

啟動順序:
因為該項目已經(jīng)整合了redis诈茧,所以在啟動服務提供者和服務訂閱者之前最好先把redis服務給先啟動了


201802.png

redis服務啟動后产喉,還需要把zookeeper注冊中心給開啟,zookeeper的配置我是使用默認的端口


201803.png

以上的兩個服務啟動完成敢会,我們就可以分別啟動服務提供者項目和服務訂閱者項目了曾沈。

3、啟動服務提供者和訂閱者

服務提供者項目其實就是commons-manager-service鸥昏,該項目主要就是把項目的服務接口注冊到zookeeper上面塞俱,所以我這里就使用了main方法的方式來啟動。其實也可以使用其他的方式來啟動吏垮,不過這里為了簡單演示障涯,所以就使用了main方法;
我們打開commons-manager-service目錄下面test文件下面的dubbo.test.DubboProviderTest類:


2018-10-19 10-55-52 的屏幕截圖.png

啟動該類的main方法就可以了膳汪。


2018-10-19 10-57-18 的屏幕截圖.png

如果控制臺唯蝶,沒有報錯就說明項目啟動正常1,服務也已經(jīng)成功注冊到了zookeeper上面遗嗽。

為了驗證我們可以使用dubbo-admin項目來查看一下粘我,服務是否已經(jīng)真的成功注冊了。使用tomcat啟動dubbo-admin項目痹换。


201804.png

訪問dubbo-admin項目征字,我們可以看到有服務注冊了。


2018-10-19 11-01-30 的屏幕截圖.png

到這里服務提供者就已經(jīng)啟動成功了娇豫。

接著我們來啟動服務訂閱者來訪問注冊到zookeeper的服務匙姜。其實所說的服務訂閱者也就是項目commons-manager-web,這是一個web項目來的冯痢,我們使用tomcat來啟動就行了氮昧。


2018-10-19 11-04-39 的屏幕截圖.png

2018-10-19 11-05-18 的屏幕截圖.png

同樣的或详,如果控制臺沒有報錯,就說明啟動完成了郭计。我們接著看一下dubbo-admin的消費者信息。


2018-10-19 11-06-24 的屏幕截圖.png

可看到已經(jīng)有消費者訂閱到服務了椒振。

到這里我們就已經(jīng)把項目完全啟動了昭伸。并且項目里面已經(jīng)有通過mybatis-plus的代碼生成器根據(jù)數(shù)據(jù)庫的一些表生成了代碼了。所以我們可以通過在commons-manager-web的controller調(diào)用一個服務來驗證一下服務是否能夠正常通訊并且訪問數(shù)據(jù)庫返回數(shù)據(jù)澎迎。
我們以ResourceController這個類庐杨,來寫一個請求方法來做校驗:


2018-10-19 11-10-41 的屏幕截圖.png

重啟項目的服務,通過瀏覽器請求:http://localhost:8080/resource/testResource

2018-10-19 11-11-54 的屏幕截圖.png

可以看到夹供,接口成功的返回了數(shù)據(jù)庫查詢到的數(shù)據(jù)了灵份。

PS:mybatis-plus的代碼生成器,我已經(jīng)放到了項目commons-manager-dao的項目中了哮洽,這個代碼生成器填渠,我是根據(jù)官網(wǎng)給出的代碼,做了一下相關的調(diào)整的鸟辅,使得該生成器可以根據(jù)多模塊項目的目錄來對應生成相關的文件氛什,除了xml文件生成后我們需要手動移動到對應的文件夾,其他的文件mapper匪凉,model枪眉,service,controller這些再层,我們度可以通過在代碼生成器的那個類里面設贸铜,這樣我們在生成代碼后就不用再一個個的手動的移動了。具體的代碼大家可以去看一下那個類:

8120601-dfd04f9a000e788d.png
public class MybatisPlusUtils {

    public static void main(String[] args) {
        String[] models = {"commons-manager/commons-manager-dao", "commons-manager/commons-manager-pojo", "commons-manager/commons-manager-service",
                "commons-manager/commons-manager-interface", "commons-manager/commons-manager-web"};
        for (String model : models) {
            shell(model);
        }
    }

    private static void shell(String model) {
        File file = new File(model);
        String path = file.getAbsolutePath();
        System.out.println(path);
        //path = path.substring(0, path.lastIndexOf(File.separator));
        AutoGenerator mpg = new AutoGenerator();
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        gc.setOutputDir(path + "/src/main/java");
        gc.setFileOverride(true);
        gc.setActiveRecord(true);
        gc.setEnableCache(false);// XML 二級緩存
        gc.setBaseResultMap(true);// XML ResultMap
        gc.setBaseColumnList(false);// XML columList
        gc.setAuthor("ChinPangLung");

        // 自定義文件命名聂受,注意 %s 會自動填充表實體屬性蒿秦!
        gc.setMapperName("%sMapper");
        gc.setXmlName("%sMapper");
        gc.setServiceName("I%sService");
        gc.setServiceImplName("I%sServiceImpl");
        gc.setControllerName("%sController");
        mpg.setGlobalConfig(gc);

        // 數(shù)據(jù)源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDbType(DbType.MYSQL);
        dsc.setTypeConvert(new MySqlTypeConvert() {
            // 自定義數(shù)據(jù)庫表字段類型轉(zhuǎn)換【可選】
            @Override
            public DbColumnType processTypeConvert(String fieldType) {
                System.out.println("轉(zhuǎn)換類型:" + fieldType);
                // 注意!饺饭!processTypeConvert 存在默認類型轉(zhuǎn)換渤早,如果不是你要的效果請自定義返回、非如下直接返回瘫俊。
                return super.processTypeConvert(fieldType);
            }
        });
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        dsc.setUrl("jdbc:mysql:///managerDB?characterEncoding=utf8");
        mpg.setDataSource(dsc);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        // strategy.setCapitalMode(true);// 全局大寫命名 ORACLE 注意
//        strategy.setTablePrefix(new String[]{"tlog_", "tsys_"});// 此處可以修改為您的表前綴
        strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
        strategy.setInclude(new String[]{"resource"}); // 需要生成的表
        // strategy.setExclude(new String[]{"test"}); // 排除生成的表
        // 自定義實體父類
        //strategy.setSuperEntityClass("com.spf.model.Entity");
        // 自定義實體鹊杖,公共字段
        //strategy.setSuperEntityColumns(new String[] { "test_id", "age" });
        // 自定義 mapper 父類
        // strategy.setSuperMapperClass("com.baomidou.demo.TestMapper");
        // 自定義 service 父類
        //strategy.setSuperServiceClass("com.baomidou.demo.TestService");
        // 自定義 service 實現(xiàn)類父類
        //strategy.setSuperServiceImplClass("com.baomidou.demo.TestServiceImpl");
        // 自定義 controller 父類
        strategy.setSuperControllerClass("com.lung.common.controller.SuperController");
        // 【實體】是否生成字段常量(默認 false)
        // public static final String ID = "test_id";
        // strategy.setEntityColumnConstant(true);
        // 【實體】是否為構建者模型(默認 false)
        // public User setName(String name) {this.name = name; return this;}
        // strategy.setEntityBuliderModel(true);
        mpg.setStrategy(strategy);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent("com.lung.application.test");
        pc.setController("controller");
        pc.setEntity("entity");
        pc.setMapper("mapper");
        pc.setService("api");
        pc.setServiceImpl("service");
        //pc.setModuleName("test");
        mpg.setPackageInfo(pc);

        // 注入自定義配置,可以在 VM 中使用 cfg.abc 【可無】
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
                this.setMap(map);
            }
        };

        // 自定義 xxList.jsp 生成
        List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
//    focList.add(new FileOutConfig("/template/list.jsp.vm") {
//       @Override
//       public String outputFile(TableInfo tableInfo) {
//          // 自定義輸入文件名稱
//          return "D://my_" + tableInfo.getEntityName() + ".jsp";
//       }
//    });
//    cfg.setFileOutConfigList(focList);
//    mpg.setCfg(cfg);

        // 調(diào)整 xml 生成目錄演示
//        focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
//            @Override
//            public String outputFile(TableInfo tableInfo) {
//                return "/develop/code/xml/" + tableInfo.getEntityName() + ".xml";
//            }
//        });
//        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 關閉默認 xml 生成扛芽,調(diào)整生成 至 根目錄
        TemplateConfig tc = new TemplateConfig();
        if ("commons-manager/commons-manager-dao".equals(model)) {
            tc.setController(null);
            tc.setEntity(null);
            tc.setService(null);
            tc.setServiceImpl(null);
//            tc.setXml(null);
        }
        /*else if ("commons-manager/commons-manager-service/src/main/resources/mapper".equals(model)) {
            PackageConfig packageInfo = mpg.getPackageInfo();
            packageInfo.setParent(null);
            packageInfo.setXml("xml");
            tc.setController(null);
            tc.setEntity(null);
            tc.setService(null);
            tc.setServiceImpl(null);
            tc.setMapper(null);
        }*/
        else if ("commons-manager/commons-manager-pojo".equals(model)) {
            tc.setController(null);
            tc.setService(null);
            tc.setServiceImpl(null);
            tc.setMapper(null);
            tc.setXml(null);
        } else if ("commons-manager/commons-manager-service".equals(model)) {
            tc.setController(null);
            tc.setMapper(null);
            tc.setService(null);
            tc.setXml(null);
            tc.setEntity(null);
        } else if ("commons-manager/commons-manager-interface".equals(model)) {
            tc.setController(null);
            tc.setMapper(null);
            tc.setServiceImpl(null);
            tc.setXml(null);
            tc.setEntity(null);
        } else if ("commons-manager/commons-manager-web".equals(model)) {
            tc.setMapper(null);
            tc.setXml(null);
            tc.setService(null);
            tc.setServiceImpl(null);
            tc.setEntity(null);
        }
        mpg.setTemplate(tc);

        // 自定義模板配置骂蓖,可以 copy 源碼 mybatis-plus/src/main/resources/template 下面內(nèi)容修改,
        // 放置自己項目的 src/main/resources/template 目錄下, 默認名稱一下可以不配置川尖,也可以自定義模板名稱
        // TemplateConfig tc = new TemplateConfig();
        // tc.setController("...");
        // tc.setEntity("...");
        // tc.setMapper("...");
        // tc.setXml("...");
        // tc.setService("...");
        // tc.setServiceImpl("...");
        // 如上任何一個模塊如果設置 空 OR Null 將不生成該模塊登下。
        // mpg.setTemplate(tc);

        // 執(zhí)行生成
        mpg.execute();

        // 打印注入設置【可無】
        System.err.println(mpg.getCfg().getMap().get("abc"));
    }
}
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子被芳,更是在濱河造成了極大的恐慌缰贝,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畔濒,死亡現(xiàn)場離奇詭異剩晴,居然都是意外死亡,警方通過查閱死者的電腦和手機侵状,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門赞弥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人趣兄,你說我怎么就攤上這事绽左。” “怎么了艇潭?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵拼窥,是天一觀的道長。 經(jīng)常有香客問我蹋凝,道長闯团,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任仙粱,我火速辦了婚禮房交,結果婚禮上,老公的妹妹穿的比我還像新娘伐割。我一直安慰自己候味,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布隔心。 她就那樣靜靜地躺著白群,像睡著了一般。 火紅的嫁衣襯著肌膚如雪硬霍。 梳的紋絲不亂的頭發(fā)上帜慢,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音唯卖,去河邊找鬼粱玲。 笑死,一個胖子當著我的面吹牛拜轨,可吹牛的內(nèi)容都是我干的抽减。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼橄碾,長吁一口氣:“原來是場噩夢啊……” “哼卵沉!你這毒婦竟也來了颠锉?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤史汗,失蹤者是張志新(化名)和其女友劉穎琼掠,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體停撞,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡眉枕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了怜森。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡谤牡,死狀恐怖副硅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情翅萤,我是刑警寧澤恐疲,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站套么,受9級特大地震影響培己,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胚泌,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一省咨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧玷室,春花似錦零蓉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至津肛,卻和暖如春章喉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背身坐。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工秸脱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人部蛇。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓撞反,卻偏偏與公主長得像,于是被迫代替她去往敵國和親搪花。 傳聞我的和親對象是個殘疾皇子遏片,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理嘹害,服務發(fā)現(xiàn),斷路器吮便,智...
    卡卡羅2017閱讀 134,665評論 18 139
  • 1笔呀、準備 在分析探索Dubbo架構原理之前,我們需要準備一下環(huán)境髓需,用于后面我們來分析dubbo的架構许师。 1.1 Z...
    墨淵丶閱讀 2,603評論 1 20
  • 本文將以原理+實戰(zhàn)的方式,首先對“微服務”相關的概念進行知識點掃盲僚匆,然后開始手把手教你搭建這一整套的微服務系統(tǒng)微渠。 ...
    傳奇內(nèi)服號閱讀 2,071評論 1 48
  • 2017-10-25 星期三 別用自己的眼界框住孩子的未來 春秋戰(zhàn)國時代楚國一位將軍名叫子發(fā),他帶兵攻秦咧擂,途中糧餉...
    心智教育麥子閱讀 328評論 0 0
  • 整體性學習在我理解就是知識的互聯(lián)逞盆,去中心化,一個知識與另一個知識相互關聯(lián)松申,知識沒有主體云芦,任何知識之間都可以有關系。...
    BertFu閱讀 511評論 0 1