编写脚本电脑怎么编写界面_在任何无法理解的情况下,请编写脚本
編寫腳本電腦怎么編寫界面
腳本編寫是使您的應用程序在運行時就可根據客戶需求進行調整的最流行的方法之一。 與往常一樣,此方法不僅帶來好處,例如,在靈活性和可管理性之間存在眾所周知的折衷方案。 本文不是從理論上討論優缺點的文章之一,它實際上展示了如何采用腳本的不同方式,并介紹了一個Spring庫,該庫提供了方便的腳本基礎結構和有用的功能。
介紹
腳本(又稱插件架構)是使應用程序在運行時可自定義的最直接方法。 通常,腳本不是偶然進入設計的,而是偶然進入應用程序的。 說,您在功能規范中有一個非常不清楚的部分,因此為了避免浪費一天來進行額外的業務分析,我們決定創建一個擴展點并調用一個實現存根的腳本,這將闡明以后的工作方式。
使用這種方法有很多眾所周知的利弊:例如,在運行時定義業務邏輯的靈活性非常高,并且可以節省大量的重新部署時間,而無法進行全面的測試,因此,安全性,性能問題是無法預測的問題等等。
對于已經決定在其Java應用程序中堅持使用腳本插件的人,或者只是考慮將其添加到其代碼中的人,進一步討論的腳本編寫方法可能會有所幫助。
沒什么特別的,只是腳本
使用Java的JSR-233 API,用Java評估腳本是一項簡單的任務。 為此API實現了許多生產級評估引擎(Nashorn,JRuby,Jython等),因此向Java代碼中添加一些腳本魔術不是問題,如下所示:
Map parameters = createParametersMap();ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine scriptEngine = manager.getEngineByName("groovy");Object result = scriptEngine.eval(script.getScriptAsString("discount.groovy"), new SimpleBindings(parameters));顯然,當代碼庫中有多個腳本文件和一個調用時,將這樣的代碼分散在整個應用程序中并不是一個好主意,因此您可以將此代碼段提取到放置到實用程序類的單獨方法中。 有時,您甚至可以走得更遠:您可以創建一個特殊的類(或類集),以基于業務域將腳本化的業務邏輯分組,例如PricingScriptService類。 這將使我們將對validateGroovy ()的調用包裝到一個不錯的強類型方法中,但是仍然有一些樣板代碼,所有方法都將包含參數映射,腳本文本加載邏輯和腳本評估引擎調用,類似于以下內容:
public BigDecimal applyCustomerDiscount(Customer customer, BigDecimal orderAmount) {Map params = new HashMap<>();params.put("cust", customer);params.put("amount", orderAmount);return (BigDecimal)scripting.evalGroovy(getScriptSrc("discount.groovy"), params); }這種方法在了解參數類型和返回值類型方面帶來了更大的透明度。 并且不要忘了在編碼標準文檔中添加禁止“未包裝”腳本引擎調用的規則!
類固醇腳本
盡管使用腳本引擎非常簡單,但是如果代碼庫中有很多腳本,您可能會遇到一些性能問題。 舉個例子–您使用Groovy模板進行報告并同時運行許多報告。 遲早您會發現“簡單”腳本正在成為性能瓶頸。
這就是為什么某些框架在現有API上構建自己的腳本引擎的原因,并添加了一些不錯的功能以實現更好的性能,執行監視,多語言腳本等。
例如,在CUBA框架中,有一個相當復雜的腳本引擎,該引擎實現了一些功能來改善腳本的實現和執行,例如:
所有這些都提高了性能和可用性,但是它們仍然是用于創建參數映射,獲取腳本文本等的低級API,因此,我們仍然需要將它們分組為高階模塊,以在應用程序中有效地使用腳本。
更何況是不提及新的實驗性GraalVM引擎及其允許使用其他語言擴展Java應用程序的多語言API。 因此,也許我們會看到Nashorn早晚退休,并且能夠在相同的源文件中使用不同的編程語言進行編寫,但是將來仍然如此。
Spring框架:很難拒絕的提議?
在Spring Framework中,我們對JDK的API提供了內置的腳本支持,您可以在org.springframework.scripting。*包中找到很多有用的類。 這里有評估人員,工廠等。所有構建您自己的腳本支持所需的工具。
除了底層API之外,Spring Framework的實現還應簡化應用程序中腳本的處理-您可以按照文檔中的描述定義以動態語言實現的bean。
您需要做的就是使用動態語言(例如Groovy)實現一個類,并在配置XML中描述一個bean,如下所示:
<lang:groovy id="messenger" script-source="classpath:Messenger.groovy"><lang:property name="message" value="I Can Do The Frug" /> </lang:groovy>之后,您可以使用XML config將Messenger Bean注入到您的應用程序類中。 可以在基礎腳本更改的情況下自動“刷新”該bean,并與AOP等一起使用。
這種方法看起來不錯,但是作為開發人員,如果您想利用動態語言支持的所有功能,則應該為您的bean實現成熟的類。 在現實生活中,腳本可能只是純函數,因此您需要向腳本中添加一些額外的代碼,以使其與Spring兼容。 如今也有一些開發人員認為XML配置與注釋相比是“過時的”,并試圖避免使用它,因為Bean定義和注入在Java代碼和XML代碼之間進行了劃分。 盡管它更多是一個品味問題,而不是性能/兼容性/可讀性等問題,但我們可以考慮到它。
腳本:挑戰和想法
因此,一切都有其代價,當您向應用程序中添加腳本時,您可能會遇到一些挑戰:
似乎在常規Java方法下隱藏腳本化方法調用可以解決大多數這些挑戰。 首選方式–注入“腳本化” bean并使用有意義的名稱調用其方法,而不是僅從實用工具類中調用另一個“ eval”方法。 因此,我們的代碼正變得自我記錄,開發人員無需查看文件“ disc_10_cl.groovy”即可確定參數名稱,類型等。
另一個優勢–如果所有腳本都有與之關聯的唯一Java方法,則可以使用IDE中的“查找用法”功能輕松找到應用程序中的所有擴展點,以及了解該腳本的參數及其含義。返回。
這種執行腳本的方式也使測試變得更加簡單–我們不僅能夠“照常”測試這些類,而且還可以在需要時使用模擬框架。
所有這些都使我們想起了本文開頭提到的方法–腳本方法的“特殊”類。 而且,如果我們更進一步,并隱藏開發人員對腳本引擎,參數創建等的所有調用,該怎么辦?
腳本存儲庫概念
這個想法非常簡單,并且所有使用Spring Framework的開發人員都應該熟悉。 我們只是創建一個Java接口并將其方法以某種方式鏈接到腳本。 例如,Spring Data JPA使用類似的方法,其中接口方法根據方法名稱轉換為SQL查詢,然后由ORM引擎執行。
我們可能需要執行什么概念?
可能是一個類級別的注釋,它將幫助我們檢測腳本存儲庫接口并為其構造一個特殊的Spring bean。
方法級別的注釋將幫助我們將方法鏈接到其腳本實現。
最好為該方法提供一個默認實現,它不是簡單的存根,而是業務邏輯的有效部分。 在我們實現由業務分析師開發的算法之前,該方法將一直有效。 或者我們可以讓他/她編寫此腳本:-)
假設您需要創建一個服務來根據用戶個人資料計算折扣。 而且業務分析師說,我們可以放心地假設默認情況下可以為所有注冊客戶提供10%的折扣。 對于這種情況,我們可能會考慮以下代碼概念:
@ScriptRepository public interface PricingRepository {@ScriptMethoddefault BigDecimal applyCustomerDiscount(Customer customer,BigDecimal orderAmount) {return orderAmount.multiply(new BigDecimal("0.9"));} }當涉及適當的折扣算法實現時,groovy腳本將如下所示:
-------- file discount.groovy -------- def age = 50 if ((Calendar.YEAR - cust.birthday.year) >= age) {return amount.multiply(0.75) } --------所有這些的最終目標–讓開發人員僅實現唯一的接口和折扣算法腳本,并且不要迷失所有這些“ getEngine”和“ eval”調用。 腳本解決方案應該發揮所有魔力:當方法被調用時,攔截調用,查找并加載腳本文本,對其進行評估并返回結果(或者,如果找不到腳本文本,則執行默認方法)。 理想用法應與此類似:
@Service public class CustomerServiceBean implements CustomerService {@Injectprivate PricingRepository pricingRepository;//Other injected beans here@Overridepublic BigDecimal applyCustomerDiscount(Customer cust, BigDecimal orderAmnt) {if (customer.isRegistered()) {return pricingRepository.applyCustomerDiscount(cust, orderAmnt);} else {return orderAmnt;}//Other service methods here}腳本調用是可讀的,我猜想任何Java開發人員都熟悉腳本的調用方式。
這些就是想法,它們被用來為使用Spring Framework實現腳本存儲庫創建一個庫。 該庫具有用于從不同來源加載和評估腳本文本的功能,以及一些API,允許開發人員在需要時實現庫的擴展。
這個怎么運作
該庫引入了一些注釋(以及那些喜歡它的人的XML配置),這些注釋在上下文初始化期間為所有標記有@ScriptRepository注釋的存儲庫接口啟動動態代理構建。 這些代理以實現存儲庫接口的單例bean的形式發布,這意味著您可以使用@Autowired或@Inject將這些代理完全注入到您的bean中,如上一節中的代碼片段所示。
在應用程序配置類之一上使用@EnableSpringRepositories批注可激活腳本存儲庫。 這種方法類似于其他熟悉的Spring注釋,例如@EnableJpaRepositories或@EnableMongoRepositories。 并且對于此批注,您需要指定應類似于JPA存儲庫進行掃描的軟件包名稱數組。
@Configuration @EnableScriptRepositories(basePackages = {"com.example", "com.sample"}) public class CoreConfig { //More configuration here. }如前所示,我們需要使用@ScriptMethod標記腳本存儲庫中的每個方法(庫還提供@GroovyScript和@JavaScript ),以將元數據添加到這些調用中并指示這些方法已編寫腳本。 當然,還支持腳本方法的默認實現。 解決方案的所有組件都顯示在下圖中。 藍色形狀與應用程序代碼相關,白色形狀與庫相關。 Spring Bean標記有春天徽標。
調用接口的腳本化方法時,該代理類將攔截該代理類,該代理類將對兩個bean執行查找-提供程序以實現腳本文本,以及評估程序以獲取結果。 腳本評估后,結果將返回到調用服務。 提供程序和評估程序都可以在@ScriptMethod批注屬性以及執行超時中指定(盡管庫提供了這些屬性的默認值):
@ScriptRepository public interface PricingRepository {@ScriptMethod (providerBeanName = "resourceProvider",evaluatorBeanName = "groovyEvaluator",timeout = 100) default BigDecimal applyCustomerDiscount(@ScriptParam("cust") Customer customer,@ScriptParam("amount") BigDecimal orderAmount) {return orderAmount.multiply(new BigDecimal("0.9")); } }您可能會注意到@ScriptParam批注–我們需要它們為方法的參數提供名稱。 這些名稱應在腳本中使用,因為Java編譯器會在編譯時刪除實際的參數名稱。 您可以省略這些注釋,在這種情況下,您需要將腳本的參數命名為“ arg0”,“ arg1”等,這會影響代碼的可讀性。
默認情況下,該庫具有可從兩種腳本語言的文件系統和基于JSR-233的評估程序讀取groovy和javascript文件的提供程序。 但是,您可以為不同的腳本存儲和執行引擎創建自定義提供程序和評估程序。 所有這些功能都基于Spring框架接口( org.springframework.scripting.ScriptSource和org.springframework.scripting.ScriptEvaluator ),因此您可以重用所有基于Spring的類,例如StandardScriptEvaluator而不是默認類。
提供程序(以及評估程序)以Spring Bean的形式發布,因為腳本存儲庫代理為了靈活性而按名稱解析它們-您可以用新的executor代替默認的執行程序,而無需更改應用程序代碼,而是在應用程序上下文中替換一個Bean。
測試和版本控制
由于可以輕松更改腳本,因此我們需要確保在更改腳本時不會破壞生產服務器。 該庫與JUnit測試框架兼容,沒有什么特別的。 由于您在基于Spring的應用程序中使用腳本,因此可以將單元測試和集成測試作為應用程序的一部分來測試腳本,然后再將其上傳到生產環境,因此還支持模擬。
另外,您可以創建一個腳本提供程序,以從數據庫甚至從Git或其他源代碼控制系統讀取不同的腳本文本版本。 在這種情況下,如果生產中出現問題,則很容易切換到較新的腳本版本或回滾到以前的腳本版本。
結論
該庫將幫助您在代碼中安排腳本,提供以下內容:
在此Spring Boot的基礎上,還支持自動配置,您還可以使用熟悉的單元測試和模擬技術,在將腳本部署到生產之前測試腳本。
該庫具有用于在運行時獲取腳本元數據(方法名稱,參數等)的API,如果您希望避免編寫try..catch塊來處理腳本拋出的異常,則可以獲取包裝的執行結果,它還支持XML配置,如果您希望以這種格式存儲配置。
另外,可以通過注釋中的超時參數來限制腳本執行時間。
可以在https://github.com/cuba-rnd/spring-script-repositories找到庫資源。
翻譯自: https://www.javacodegeeks.com/2018/11/incomprehensible-situation-scripting.html
編寫腳本電腦怎么編寫界面
總結
以上是生活随笔為你收集整理的编写脚本电脑怎么编写界面_在任何无法理解的情况下,请编写脚本的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html 强制返回404 怎么设置(网页
- 下一篇: 线程同步临界区(线程同步linux)