參加工作的第一個月,我開始寫下第一篇博客

来源:https://www.cnblogs.com/LeeMouRen/archive/2018/05/06/8992509.html
-Advertisement-
Play Games

參加工作 關於從學生到職場的轉變與心態起伏,已然有許多文筆好的朋友感嘆過,我想自己作為一個平凡的人,相較他人也不會有更為特別的感受,自然也就不值當多說。只簡單聊聊自身的情況,1月份畢業於非電腦專業,3月底檔案上的職業欄從 變成了 手動滑稽,編程功底相比電腦專業的各位前輩有較大差距,但這就是我職業 ...


參加工作

關於從學生到職場的轉變與心態起伏,已然有許多文筆好的朋友感嘆過,我想自己作為一個平凡的人,相較他人也不會有更為特別的感受,自然也就不值當多說。只簡單聊聊自身的情況,1月份畢業於非電腦專業,3月底檔案上的職業欄從學生變成了軟體開發高級工程師手動滑稽,編程功底相比電腦專業的各位前輩有較大差距,但這就是我職業生涯的起點。
進入部門一個月,接觸的東西大多都是在學校聽過但沒有用過的,考慮到腦容量的問題,防止以後持續的東忘西,終於決定將一部分通用的技術或理念或心得記錄下來,就從現在開始。

程式整體框架概述

我所接觸的是數據採集方面的任務,整個數據採集模塊主框架被封裝在一個a.jar包之中,程式入口common通過啟動命令指定,使用nohuo與&指令將服務運行在後臺:

 nohup java -cp 'pwd'/a.jar main.common [args]>>nohup.out &

進入common繼續往下看:
首先關註啟動命令中所指定的args參數,此參數指定配置文件路徑,(程式啟動後,a.jar文件所在目錄即為根目錄,指定路徑以此為基礎)。通過jar包sysconfig類中定義的靜態方法,讀取cfg配置文件內容,依次賦值給sysconfig類中的靜態變數,作後續使用。
之後利用jar包Server類中的ServerRun靜態方法,通過讀取上述sysconfig類中的port靜態變數,使用mina框架提供的socket通信方法,監聽本機埠。

public static void ServerRun(int PORT) throws Exception {

        SocketAcceptor acceptor = new NioSocketAcceptor();
        acceptor.setReuseAddress(true);

        DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
        chain.addLast("threadPool", new ExecutorFilter(Executors.newFixedThreadPool(sysconfig.socket_poolsize)));

        acceptor.setHandler(new Server());
        acceptor.getSessionConfig().setUseReadOperation(true);
        acceptor.getSessionConfig().setReadBufferSize(30000);
        acceptor.bind(new InetSocketAddress(PORT));
        
        System.out.println("Listening on port " + PORT);
        for (;;) {
            Thread.sleep(1000);
        }
    }

如此一來,通過telnet連接至指定埠,就可以做到與程式進行交互。Server類繼承mina框架的IoHandAdapter類,便於管理連接,[mian Iohander事件觸發機制可以參考該博文]
(https://blog.csdn.net/boonya/article/details/51583823)
當消息被接收到時,messageReceived事件被觸發,這是應用程式需要處理輸入信息的地方。這裡將首次與外部js文件產生調用,(關於java與js的相互調用,大家可自行查閱相關資料)而後續大量的操作均需要通過外部js代碼進行完成,如此重要的操作自然需要一個專門的類進行封裝。js類概要功能如下:

import javax.script.*;
public class js {
    public ScriptEngine engine = null;
    public static ScriptEngineManager manager = new ScriptEngineManager();
    public js(String args) throws Exception {
        m_args = args;
        engine = manager.getEngineByName("JavaScript");
        engine.put("engine", engine);
        engine.put("core", this);
        engine.put("args", args);
        ...
        m_files.add(sysconfig.js_run_path + sysconfig.entry_js);
    }
    public Object runfile(String filename) throws Exception {
        java.io.FileReader reader = null;
        try { 
            reader = new java.io.FileReader(filename); 
            return engine.eval(reader);
        } finally {
            try{ reader.close(); } catch(Exception e){}
        }
    }
    public Object include(String filename) throws Exception{
        return this.runfile(sysconfig.js_run_path + filename);
    }
}

簡單地說,就是通過getEngineByName初始化一個ScriptEngine,然後通過put()對變數賦值,通過eval執行js程式。
瞭解了js類的主要方法,回過頭繼續看messageReceived方法中所作的處理。

public class Server extends IoHandlerAdapter {
    @Override
    public void messageReceived(IoSession session, Object message) throws UnsupportedEncodingException {
        String buf = new String(((IoBuffer) message).array(), sysconfig.socket_recv_encode);
        buf = buf.trim();
        if (buf.length() > 0) {
            try {
                    js jengine = new js(buf);
                    jengine.engine.put("client", new Requ(session));
                    jengine.include(sysconfig.entry_js);
                }
                jengine.engine.put("input_0_0_0", buf);
                jengine.engine.eval("main(input_0_0_0)");
            } catch (Exception ex) {
                ex.printStackTrace();
                Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
                session.closeOnFlush();
            }
        }
    }
}

這裡首先生成一個js對象,之後通過put方法將一個Requ對象與client字元串綁定,Requ對象即為負責與telnet進行通信的實現對象,包括send和recv方法。(在後續程式中通過client.send(“msg”)即可往控制台輸出內容,方便瞭解程式交互運行的過程)。
緊接著調用include方法調用執行一個外部js文件(sysconfig.entry_js在配置文件中的值為main.js,通過include方法拼湊出文件路徑,進一步調用runfile方法執行main.js)。而事實上,mian.js裡面僅僅定義了一個main(args)函數,因此在jengine.engine.put("input_0", buf);jengine.engine.eval("main(input_0)");這兩句代碼的作用僅僅是將接收到的buf數據傳輸給main(args)執行,其中由telnet傳輸的args[0]此處一般為js文件名,args[1]為後續參數。通過main(args)函數繼續調用args[0]執行各類操作。(這麼做顯得main.js多此一舉,完全可以在Server類中做同樣處理,但我想既然存在,自然是有一定的道理,畢竟架構師的經驗要豐富的多)。
到此處,基本的架構邏輯捋順,接下來就是在此基礎上各種具體應用,如果有人願意看,下一篇就選取一個常用的資料庫指標採集進行詳細的陳述。

所思所得

java與js文件的互相調用配合,架構師的作用

在java程式中通過js類封裝了ScriptEngine,並將core與當前js對象綁定。之後在執行的各js文件中,通過core.include("*.js"),就可以繼續調用執行其他js程式。js類中還有一個重要的方法newobject(String classname),這個方法實現在js腳本程式中初始化jar包中封裝的類。

    public Object newobject(String classname) throws Exception {
        return Class.forName(classname).newInstance();
    }

這樣在js腳本程式中通過Object_classname= core.newobject(classname);就可以得到classname的實例對象。
如此一來,將主要功能模塊封裝在jar包中,具體使用時則通過js程式來調用,這種設計使得程式的靈活性大大提高,程式後期的擴展性也得到了保障。(ps:在學校也曾讀過一兩本關於設計模式的書,淺嘗輒止,只能在以後的工作中多花功夫了)

java與telnet之間的命令傳輸

在java程式中通過Server類啟動並監聽PORT埠,當有一個遠程埠接入,就生成一個Requ對象負責通信,而根據約定,遠程埠發送的命令格式為js文件名+" "+參數列表,解析命令字元串,通過core.include與runfile方法就可以實現執行js程式並傳參的功能預期。

js奇妙體驗

以前對js沒怎麼研究過,只是初步知道是解釋型語言,原生支持json,語法簡單瞭解過。在這一個月的"使用"過程中,深深體會到它的便捷與易用性,最簡單的如編寫一個js文件,代碼僅僅是一個方法,甚至只是幾個變數的初始化,而當被eval()執行過後,該方法就被載入到了記憶體中,之後就可以在其它地方直接調用執行,產生一種C#擴展方法的錯覺。

所遇到的一個問題

問題描述

在添加對postgresql資料庫指標的採集功能時,發現無法採集數據,經排查發現原因在於無法連接至postgresql資料庫。

解決問題過程中的所見所得

為什麼無法連接postgresql資料庫?明明代碼什麼的都沒問題,自己編寫的資料庫連接測試的小程式也可以成功連接,不得不請教技術專家來解決。問題描述清楚後,老師鍵指如飛,我一個初出茅廬的小兵是眼花繚亂,再也插不上一句話。幾分鐘後老師排查出問題所在,原因很簡單,jar包沒有自動引用postgresql資料庫驅動包。事後通過查看歷史命令,將大致排查過程簡單還原如下:

starce 命令跟蹤---查到資料庫連接不通
ps -ef | grep *.jar---得到程式pid
cd /proc/pid/fd ---進入程式文件描述符文件夾
ll -h | grep *.jar---查看引用的所有jar包---發現沒有引用postgresql驅動jar包

解決方案

為了進一步確認驅動包是否可用,在測試環境下進行了一次破壞性試驗。

cd /'home'/lib/
for name in `ls | grep *.jar$`;do `jar -xvf $name`;done
rm -rf *.jar
jar -cvf ojdbc14.jar *

由於ojdbc14.jar是一定會被引用,所以將所有的jar包解包後全部壓入ojdbc14.jar中。重新運行程式,發現已經可以正常連接至postgresql資料庫。技術與經驗的差距,僅僅不到10分鐘,不僅排查了問題,還給出一個臨時的試驗解決方案,當然最終的解決是重新編譯打包程式。
事後嘗試直接改寫jar包中的META-INF/MANIFEST.MF文件,在其Class-Path後加上postgresql的包地址,但並不起作用(格式沒問題),所以請讀到此文的各位博友不吝賜教。

目前水平較低,難免對各種各樣的問題理解不夠深徹,還是希望各位博友多多留言交流。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 項目開發中,大家都會使用日誌框架(LogBack, log4j , java.util.logging 等)。下麵來簡單的瞭解一下日誌框架的大體設計思路。 類圖: ...
  • Spring介紹 Spring的核心是一個輕量級(Lightweight)的容器(Container),它是實現IoC(Inversion of Control)容器和非入侵性(No intrusive)的框架,並提供AOP(Aspect-oriented programming)概念的實現方式;提 ...
  • 技巧提示:mysql讀寫分離搭建好之後,配合nginx的負載均衡,可以高效的mysql的集群性能,同時免去麻煩的query分流。比如,sever1收到的請求就專門鏈接slave1從mysql讀取數據,配合nginx的反向代理實現的分流,就可以優雅的把mysql的query請求分壓到不同的mysql- ...
  • 1.服務註冊與發現基礎架構 註冊中心: 接受服務提供者的註冊、存儲服務提供者的服務信息 ,比如ip 埠號 服務名這些信息; 並且與微服務保持心跳,如果心跳不能保持則註銷該實例。 所以註冊中心主要提供服務提供者信息的存儲,另外與服務提供者保持心跳以監控服務提供者的存活。 服務提供者: 向註冊中心提供 ...
  • 1.微服務技術選型圖如下圖所示: 2.如何進行微服務架構設計: 深入業務功能, 滿足功能性需求 非功能性需求關註擴展性,穩定性。可維護性,伸縮性,高可用,高性能 堅持kiss原則,防止簡單問題複雜化 註: 可伸縮性是指系統通過增加或減少硬體水平從而提升或降低系統性能的難易程度。可伸縮性分為scale ...
  • 責任鏈模式 一.什麼是責任鏈模式? 責任鏈模式為請求創建一個接受者對象的鏈,這種模式給予請求的類型,對請求的發送者和接收者進行解耦.(將接受者對象連成一條鏈,並且在該鏈上傳遞請求,直到有一個接受者對象處理它,通過讓更多對象有機會處理請求,避免了發送者和接受者之間的耦合度)這種類型的設計模式屬於行為型 ...
  • 單例模式 一.什麼是單例模式? 單例模式是java中最簡單的設計模式之一,屬於創建型設計模式,這種模式涉及到一個的單一的類,該類負責創建自己的對象,這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。(1.單例類只能有一個實例,2.單例類必須自己創建自己唯一實例,2.單例類 ...
  • 模板模式和鉤子函數 一.什麼是模板模式? 定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中,模板方法使得子類可以不改變一個演算法的結構就能重新定義該演算法的某些特定步驟,模板模式屬於設計模式中的行為模式。 二.如何實現模板模式? 三.模板模式的實現要素? 準備一個抽象基類,將部分邏輯以具體方法的形式 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...