1. 程式人生 > >vue-codemirror + Java Compiler實現Java Web IDE

vue-codemirror + Java Compiler實現Java Web IDE

# 背景 >最近同事告訴我一個很有趣的需求:讓使用者(應用場景中,一般為其他開發者)自己填入**Java程式碼片段**,程式碼片段的內容為已經規定好的模板類的**繼承類**,實現模板類定義的方法。我們的專案要實現動態編譯程式碼片段,儲存程式碼片段和使用者操作記錄的對映關係,並能夠在業務中載入程式碼片段執行。 這有點像我們提供一個模板模式的架構,只不過模板類的實現類由外部介面填入程式碼片段動態實現。相較讓其他開發者直接參與專案開發,無疑: 1. 降低了侵入風險 2. 向其他開發者隱藏了大部分實現 3. 降低操作難度和開發門檻 4. 便於管理 …… 這相當於要實現一個簡單的線上Java開發環境,提供基礎的程式碼填寫、編譯和儲存的功能。 # 效果演示 ![切換主題](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy82ODEwNjIwLTAzMWUyOTZkYWMyNWQ1YzQuZ2lm) ![聯動填寫類名](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy82ODEwNjIwLTMwNGZkZjM2NGQ4NzEzYTIuZ2lm) ![測試編譯](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy82ODEwNjIwLWZkNDI3Y2ZlMTg3MjMxZTkuZ2lm) 基於`vue-codemirror`和`Java Compiler`的動態編譯,實現了上述需求,目前完成的Web端IDE主要功能點包括: - 頁面展示Java程式碼塊(程式碼高亮,有行號、可自動補全括號等) - 從服務端獲取模板類程式碼,並提供示例 - 實時動態編譯並獲取編譯結果(通過/失敗 todo:返回編譯錯誤資訊) - 將輸入字串載入成Java Class 以及小的功能點:自動縮排、補全括號、切換主題、聯動填寫類名等等。 下面給出涉及到的技術和實現方法。 --- # CodeMirror CodeMirror是一個JS庫,可以支援實現有豐富的附加功能和多種語言支援。我們專案的前端使用Vue框架,可以很方便地整合並使用CodeMirror提供的外掛,實現我們的線上IDE多種特性。 參考:[CodeMirror官網](https://codemirror.net/) ## 引入 安裝依賴:` "vue-codemirror": "^4.0.6"` 在`src`目錄下的`main.js`中引入: ```javascript import VueCodeMirror from 'vue-codemirror' import 'codemirror/lib/codemirror.css' Vue.use(VueCodeMirror) ``` ## 使用 新建元件`JavaIDE.vue` ```vue ``` 元件化地使用它,我們可以方便地操作它繫結的值(code)和其他附加選項(cmOption)。 在元件建立時為code賦值,即可實現載入模板程式碼。 > 根據官網,我們可以直接使用CodeMirror的預設建構函式,也可以提供一個`textarea DOM`元素作為構造CodeMirror物件的引數。 可以使用`readOnly`引數將程式碼塊設定為只讀。 ### 聯動填寫類名功能 希望實現:在上面頂欄中填寫類名,在程式碼中聯動填寫。 實現方式: 使用正則匹配替換程式碼片段,再進行替換 使用相同的方法,也可以實現動態補全類名等功能 >參考更多[JavaScript的正則表示式](https://www.runoob.com/js/js-regexp.html) 為輸入框加上監聽函式`@input="changeClassName"` ```javascript changeClassName(className) { var reg = new RegExp(/public class .*? extends ActionParamBuilder/); this.code = this.code.replace(reg, "public class " + className + " extends ActionParamBuilder" ); } ``` ### 切換主題 引入主題`css`樣式檔案 ``` import "codemirror/theme/eclipse.css"; import "codemirror/theme/darcula.css"; import "codemirror/theme/blackboard.css"; ``` 使用String陣列定義支援的主題,並使用 `Element-UI`提供的`Select`元件支援主題切換: ``` ``` * 使用`slot`實現在選擇器中嵌入圖示,並支援`tooltip`功能,使工具欄更加緊湊。 `slot`意為插槽,是封裝好的元件預留的可以自定義的空間,我們可以使用`slot = ""`把DOM元素置入到元件內部,非常靈活。 ### 樣式覆寫 使用`!important`關鍵字覆蓋原有CodeMirror樣式。注意,將該樣式放在全域性而不是區域性`scoped`樣式表中。 ``` .CodeMirror { height: 500px !important; } ``` # JavaCompiler 不用將傳入的程式碼儲存成`.java`檔案寫入磁碟,直接就可以使用`JavaCompiler`工具對字串進行編譯。 > 為了實現實時動態編譯功能,我搜索了關於如何將字串編譯成class的方法,還看了一些動態代理的實現思路。後來看到這一篇:[ Java執行時動態生成class的方法](https://www.liaoxuefeng.com/article/1080190250181920),發現這就是我想要的! 使用Java SDK(since 1.6)提供的JavaCompiler工具。該工具提供編譯方法: ```java CompilationTask getTask(Writer out, JavaFileManager fileManager, DiagnosticListener diagnosticListener,