OSGi案例研究:模塊化vert.x

OSGi使Java代碼可以清晰地劃分為多個模塊,這些模塊稱為捆綁軟件 ,可以訪問由每個捆綁軟件的類加載器控制的代碼和資源。 OSGi 服務提供了一種附加的分離機制:接口的用戶不需要依賴于實現類,工廠等。

以下案例研究旨在使OSGi捆綁包和服務的上述優勢具體化。 它采用了一個有趣的Java項目vert.x,并展示了如何將其嵌入OSGi并利用OSGi的功能。

免責聲明:我不建議更換vert.x容器或其模塊系統。 這主要是在OSGi的使用中進行的案例研究,盡管某些發現應該促使對vert.x進行改進,尤其是將其嵌入具有自定義類加載器的應用程序中時。

版本號

vert.x開源項目提供了node.js的JVM替代方案:異步,事件驅動的編程模型,用于以多種語言(包括Java,Groovy,JavaScript和Ruby)編寫Web應用程序。

vert.x支持HTTP以及現代協議,例如WebSockets和sockjs (與WebSockets 相比 ,它們在更多的瀏覽器中工作,并且可以更輕松地穿越防火墻)。
vert.x具有分布式事件總線,允許已知為verticles并稱為busmods共享代碼庫vert.x應用程序之間進行傳播JSON消息。 busmod是一種特殊的Verticle,它處理事件總線中的事件。 vert.x艦艇一些busmods,如MongoDB的 “persistor”,用戶可以寫自己的。

vert.x的線程模型很有趣,因為每個頂點(或busmod)在其生命周期內都綁定到特定線程,因此,頂點代碼無需關注線程安全性。 線程池用于在頂點上分派工作,并且每個頂點必須避免阻塞或長時間運行的操作,以免影響服務器吞吐量(vert.x提供了有效地實現長時間運行的操作的單獨機制)。 這類似于CICS事務處理器中的準可重入線程模型。 1個

這里特別受關注的是vert.x模塊系統,該系統在每個頂點上都有一個類加載器和稱為模塊的代碼庫,它們被加載到使用它們的每個頂點的類加載器中。 因此,除了通過事件總線之外,沒有其他方法可以在各個頂點之間共享代碼。

vert.x具有出色的文檔,包括主要手冊 , java手冊 (以及其他語言的手冊), 教程和可運行的代碼示例 。

OSGi

如果您還不熟悉OSGi,請閱讀我的OSGi簡介文章,但現在不要再理會該文章中的鏈接-您可以隨時返回并稍后再做。

將vert.x嵌入OSGi

我通過幾個小步驟完成了此操作,下面依次介紹了這些步驟:將vert.x JAR轉換為OSGi捆綁包,然后模塊化verticle,busmod和事件總線客戶端。

將vert.x JAR轉換為OSGi捆綁軟件

vert.x手冊鼓勵用戶使用vert.x核心JAR將vert.x嵌入其自己的應用程序中,因此將vert.x嵌入OSGi的第一步是將vert.x核心JAR轉換為OSGi捆綁包,因此可以將其加載到OSGi運行時中。

我使用了Bundlor工具,盡管其他工具(例如bnd)也可以很好地工作。 Bundlor接受一個模板,然后分析JAR的字節碼以生成帶有適當OSGi清單標頭的新JAR。 請立即參閱SpringSource Bundlor文檔以獲取有關Bundlor的更多信息,因為在撰寫本文時Eclipse Virgo Bundlor文檔尚未發布,即使Bundlor項目已轉移到Eclipse.org。

vert.x核心JAR的模板如下:

Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.vertx.core
Bundle-Version: 1.0.0.final
Bundle-Name: vert.x Core
Import-Template:org.jboss.netty.*;version="[3.4.2.Final,4.0)",org.codehaus.jackson.*;version="[1.9.4,2.0)",com.hazelcast.*;version="[2.0.2,3.0)";resolution:=optional,groovy.*;resolution:=optional;version=0,org.codehaus.groovy.*;resolution:=optional;version=0,javax.net.ssl;resolution:=optional;version=0,org.apache.log4j;resolution:=optional;version=0,org.slf4j;resolution:=optional;version=0
Export-Template: *;version="1.0.0.final"

(此案例研究的模板和所有其他部分可在github上找到 。)

這是為JAR所依賴的軟件包定義有效的版本范圍(范圍“ 0”表示0或更大的版本范圍),這些軟件包是可選的還是強制的,以及JAR自己的軟件包應為哪個版本出口處。 它還為捆綁軟件提供了符號名稱 (用于標識捆綁軟件),版本和(描述性)名稱。 有了這些信息,OSGi然后通過委派包類加載器之間的類加載和資源查找,將包的依賴關系連接在一起。

值得慶幸的網狀網絡JAR和杰克遜 JSON JAR文件將vert.x核心JAR取決于附帶有效的OSGi清單。

為了驗證清單是否有效,我嘗試在處女座內核中部署vert.x核心軟件包。 只需將vert.x核心捆綁包放置在Pickup目錄中,并將其依賴項放置在repository / usr目錄中,然后啟動內核即可。 以下控制臺消息顯示vert.x核心捆綁包已安裝并成功解決:

<hd0001i> Hot deployer processing 'INITIAL' event for file 'vert.x-core-1.0.0.final.jar'.
<de0000i> Installing bundle 'org.vertx.core' version '1.0.0.final'.
<de0001i> Installed bundle 'org.vertx.core' version '1.0.0.final'.
<de0004i> Starting bundle 'org.vertx.core' version '1.0.0.final'.
<de0005i> Started bundle 'org.vertx.core' version '1.0.0.final'.

然后使用處女座外殼,檢查線束的接線:

osgi> ss
"Framework is launched."id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.7.1.R37x_v20110808-1106
...
89      ACTIVE      org.vertx.core_1.0.0.final
90      ACTIVE      jackson-core-asl_1.9.4
91      ACTIVE      jackson-mapper-asl_1.9.4
92      ACTIVE      org.jboss.netty_3.4.2.Finalosgi> bundle 89
org.vertx.core_1.0.0.final [89]...Exported packages...org.vertx.java.core; version="1.0.0.final"[exported]org.vertx.java.core.buffer; version="1.0.0.final"[exported]...Imported packagesorg.jboss.netty.util; version="3.4.2.Final"<org.jboss.netty_3.4.2.final [92]>...org.codehaus.jackson.map; version="1.9.4"<jackson-mapper-asl_1.9.4 [91]>...

我還按照以后需要的類似方式將vert.x平臺JAR轉換為OSGi捆綁軟件。

模塊化頂點

一個典型的頂點如下所示:

public class ServerExample extends Verticle {public void start() {vertx.createHttpServer().requestHandler(new Handler<httpserverrequest>() {public void handle(HttpServerRequest req) {...}}).listen(8080);}
}

調用start方法時,它將創建一個HTTP服務器,并向該服務器注冊一個處理程序,并設置服務器在端口上偵聽。 除了處理程序的主體之外,該代碼的其余部分都是樣板。 因此,我決定將樣板分解為一個通用的OSGi捆綁包(org.vertx.osgi),并用包含處理程序和一些等同于樣板的聲明性元數據的模塊化頂包替換該頂標。 常見的OSGi捆綁包使用白板模式來偵聽OSGi服務注冊表中的特定種類的服務,基于元數據創建樣板,并向生成的HTTP服務器注冊處理程序。

讓我們看一下模塊化的vertical bundle。 它的代碼包含一個HttpServerRequestHandler類: 2

public final class HttpServerRequestHandler implements Handler<httpserverrequest> {public void handle(HttpServerRequest req) {...}}

它還具有服務屬性形式的聲明性元數據,該聲明性元數據與OSGi服務注冊表中的處理程序一起注冊。 我可以使用OSGi藍圖服務來執行此操作,盡管我可以使用OSGi聲明性服務,甚至可以使用OSGi API以編程方式注冊該服務。 藍圖元數據是捆綁軟件中的文件blueprint.xml ,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"><service interface="org.vertx.java.core.Handler" ref="handler"><service-properties><entry key="type" value="HttpServerRequestHandler"><entry key="port" value="8090"></service-properties></service><bean class="org.vertx.osgi.sample.basic.HttpServerRequestHandler"id="handler"/></blueprint>

此元數據聲明應創建HTTP服務器(通過類型服務屬性),向其注冊的處理程序以及偵聽端口8090的服務器集(通過端口服務屬性)。 當org.vertx.osgi捆綁包運行時,這一切都是通過白板模式完成的,如下所示。

請注意,模塊化Verticle僅依賴于Handler和HttpServerRequest類,而原始Verticle也依賴于Vertx,HttpServer和Verticle類。 對于那些喜歡單元測試(除了容器內測試)的人來說,這也使事情變得簡單得多,因為所需的模擬或存根數量更少。

那么我們現在有什么呢? 將兩個包添加到我們先前安裝的包中:一個org.vertx.osgi包,它封裝了樣板代碼;一個應用程序包,它代表一個模塊化的verticle。 我們還需要一個Blueprint服務實現-從Virgo 3.5開始,Virgo內核內置了一個Blueprint實現。 以下交互圖顯示了一種可能的事件序列:

在OSGi中,每個捆綁軟件都有其自己的生命周期,并且通常設計捆綁軟件時,無論它們相對于其他捆綁軟件啟動的順序如何,它們都將正確運行。 在上面的示例中,假定的開始順序為:藍圖服務,org.vertx.osgi包,模塊化verticle包。 但是,org.vertx.osgi捆綁包可以在模塊化Verticle捆綁包之后開始,并且最終結果將是相同的:將創建服務器,并且在服務器上注冊模塊化Verticle捆綁包的處理程序,并且服務器設置監聽。 如果藍圖服務是在org.vertx.osgi和模塊化Verticle捆綁包之后啟動的,那么直到藍圖服務啟動后,org.vertx.osgi捆綁包才會檢測到模塊化注冊表包的處理程序服務出現在服務注冊表中,但是最終結果將再次相同。

github項目包含一些示例模塊verticle的源代碼: 基本的HTTP垂直版本 (在8090端口上運行)和sockjs verticle (在8091端口上運行)。 org.vertx.osgi捆綁軟件需要更多的代碼來支持sockjs,而模塊化的sockjs verticle除了提供HTTP處理程序外,還需要提供sockjs處理程序。

模塊化BusMods

MongoDB持久程序是處理事件總線消息的busmod的典型示例:

public class MongoPersistor extends BusModBase implements Handler<message<jsonobject>> {private String address;private String host;private int port;private String dbName;private Mongo mongo;private DB db;public void start() {super.start();address = getOptionalStringConfig("address", "vertx.mongopersistor");host = getOptionalStringConfig("host", "localhost");port = getOptionalIntConfig("port", 27017);dbName = getOptionalStringConfig("db_name", "default_db");try {mongo = new Mongo(host, port);db = mongo.getDB(dbName);eb.registerHandler(address, this);} catch (UnknownHostException e) {logger.error("Failed to connect to mongo server", e);}}public void stop() {mongo.close();}public void handle(Message<jsonobject> message) {...}}

再次,混合了樣板代碼(用于注冊事件總線處理程序),啟動/停止邏輯,配置處理以及事件總線處理程序本身。 我對其他豎版應用了類似的方法,并將樣板代碼分離到org.vertx.osgi包中,將處理程序和元數據(包括配置)保留在模塊化busmod中。 持久性對MongoDB客戶端JAR(mongo.jar)的依賴很方便,因為此JAR附帶了有效的OSGi清單。

這是blueprint.xml :

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"><service ref="handler" interface="org.vertx.java.core.Handler"><service-properties><entry key="type" value="EventBusHandler"/><entry key="address" value="vertx.mongopersistor"/></service-properties></service><bean id="handler" class="org.vertx.osgi.mod.mongo.MongoPersistor"destroy-method="stop"><argument type="java.lang.String"><value>localhost</value></argument><argument type="int"><value>27017</value></argument><argument type="java.lang.String"><value>default_db</value></argument></bean></blueprint>

請注意,樣板配置由處理程序類型和事件總線地址組成。 其他配置(主機,端口和數據庫名稱)特定于MongoDB持久程序。

這是模塊化的MongoDB busmod代碼 :

public class MongoPersistor extends BusModBaseimplements Handler<Message<JsonObject>> {private final String host;private final int port;private final String dbName;private final Mongo mongo;private final DB db;public MongoPersistor(String host, int port, String dbName)throws UnknownHostException, MongoException {this.host = host;this.port = port;this.dbName = dbName;this.mongo = new Mongo(host, port);this.db = this.mongo.getDB(dbName);}public void stop() {mongo.close();}public void handle(Message<JsonObject> message) {...}}

該代碼仍然擴展了BusModBase,僅僅是因為BusModBase提供了幾種方便的輔助方法。 同樣,與非模塊化等效代碼相比,生成的代碼更簡單,更易于單元測試。

模塊化事件總線客戶端

最后,我需要一個模塊化的Verticle來測試模塊化的MongoDB持久性。 這些verticle需要做的就是將適當的消息發布到事件總線。 普通的vert.x垂直版本使用Vertx類獲取事件總線,但是我再次使用了Blueprint服務,這一次是在服務注冊表中查找事件總線服務,并將其注入到模塊化垂直版本中。 我還擴展了org.vertx.osgi捆綁包,以便在服務注冊表中發布事件總線服務。

模塊化事件總線客戶端的blueprint.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"><reference id="eventBus" interface="org.vertx.java.core.eventbus.EventBus"/><bean class="org.vertx.osgi.sample.mongo.MongoClient"><argument ref="eventBus"/><argument type="java.lang.String"><value>vertx.mongopersistor</value></argument></bean></blueprint>

然后, 模塊化事件總線客戶端代碼非常簡單:

public final class MongoClient {public MongoClient(EventBus eventBus, String address) {JsonObject msg = ...eventBus.send(address, msg,new Handler<Message<JsonObject>>(){...});}}

旋轉一下

1.我已經在git的bundles目錄中提供了所有必需的OSGi捆綁包 。 您可以通過克隆git存儲庫來獲取它們:

git clone git://github.com/glyn/vert.x.osgi.git

或通過下載git repo的zip文件 。

2. vert.x需要Java 7 ,因此請設置終端外殼以使用Java7 。確保正確設置了JAVA_HOME環境變量。 (如果現在無法獲取Java 7,則將捆綁軟件部署到OSGi時會看到一些錯誤,并且您將無法在步驟8和9中運行示例。)

3.如果您是OSGi用戶,只需在您喜歡的OSGi框架或容器中安裝并啟動捆綁軟件,然后跳至步驟8。否則,請按以下方式使用git存儲庫中的Virgo內核副本。

4.將目錄更改為git repo本地副本中的virgo-kernel-…目錄。

5.在UNIX上,發出:

bin/startup.sh -clean

或在Windows上,發出:

bin\startup.bat -clean

6.處女座內核應在其拾取目錄中啟動并部署各種捆綁軟件:

  • org.vertx.osgi捆綁包( org.vertx.osgi-0.0.1.jar
  • HTTP示例模塊化org.vertx.osgi.sample.basic-1.0.0.jarorg.vertx.osgi.sample.basic-1.0.0.jar
  • SockJS示例模塊化verticle( org.vertx.osgi.sample.sockjs-1.0.0.jar
  • MongoDB持久性示例模塊化busmod( org.vertx.osgi.mods.mongo-1.0.0.jar

7.如果要查看現在正在運行的捆綁軟件,請從另一個終端啟動Virgo Shell:

telnet localhost 2501

并使用sslb命令匯總已安裝的捆綁軟件。 help命令將列出其他可用命令,而disconnect將使您脫離Virgo Shell。 這是ss命令的典型輸出:

...
89      ACTIVE      org.vertx.osgi_0.0.1
90      ACTIVE      jackson-core-asl_1.9.4
91      ACTIVE      jackson-mapper-asl_1.9.4
92      ACTIVE      org.jboss.netty_3.4.2.Final
93      ACTIVE      org.vertx.core_1.0.0.final
94      ACTIVE      org.vertx.osgi.mods.mongo_1.0.0
95      ACTIVE      com.mongodb_2.7.2
96      ACTIVE      org.vertx.platform_1.0.0.final
97      ACTIVE      org.vertx.osgi.sample.basic_1.0.0
98      ACTIVE      org.vertx.osgi.sample.sockjs_1.0.0

lb命令(包括更具描述性的Bundle-Name標頭):

...89|Active     |    4|vert.x OSGi Integration (0.0.1)90|Active     |    4|Jackson JSON processor (1.9.4)91|Active     |    4|Data mapper for Jackson JSON processor (1.9.4)92|Active     |    4|The Netty Project (3.4.2.Final)93|Active     |    4|vert.x Core (1.0.0.final)94|Active     |    4|MongoDB BusMod (1.0.0)95|Active     |    4|MongoDB (2.7.2)96|Active     |    4|vert.x Platform (1.0.0.final)97|Active     |    4|Sample Basic HTTP Verticle (1.0.0)98|Active     |    4|Sample SockJS Verticle (1.0.0)

8.現在,您可以使用Web瀏覽器在localhost:8090嘗試基本的HTTP示例,該示例應響應“ hello”,或在http:// localhost:8091的SockJS示例應顯示一個框,您可以在其中鍵入一些文本和一個按鈕,單擊該按鈕會彈出一個窗口:

9.如果要嘗試(無頭的)MongoDB事件總線客戶端,請下載MondoDB并在其默認端口上本地啟動 ,然后將org.vertx.osgi.sample.mongo-1.0.0.jarbundles目錄復制到Virgo的提取目錄。 此捆綁包啟動后,它將立即向事件總線發送一條消息,并驅動MongoDB持久程序更新數據庫。 如果您不想使用MongoDB來檢查是否進行了更新,請查看處女座的日志(在serviceability/logs/log.log )以查看一些System.out行,例如以下內容,該行確認發生了某些情況:

System.out Sending message: {action=save, document={x=y}, collection=vertx.osgi} 
... 
System.out Message sent 
...
System.out Message response {_id=95..., status=ok}

OSGi和vert.x模塊化

在本案例研究中,各種示例OSGi捆綁包都依賴于并共享vert.x核心捆綁包。 每個捆綁包都加載在其自己的類加載器中,并且OSGi根據OSGi捆綁包的連接方式控制類加載和資源查找的委派。 以相同的方式,寫為OSGi包的頂點可以自由地依賴和共享其他OSGi包。

這與vert.x模塊系統大不相同,在vert.x模塊系統中,一個verticle依賴的任何模塊(除了busmod之外)都被加載到與verticle相同的類加載器中。

OSGi模塊系統的優點是,每個模塊的單個副本安裝在系統中,并且對于諸如Virgo shell之類的工具可見并且可以由其管理。 它還使占地面積最小。

vert.x模塊系統的優點是,在各個頂點之間不存在模塊共享,因此,編寫不當的模塊不會無意或有意地泄漏獨立頂點之間的信息。 此外,每個使用它的垂直模塊都有每個(非busmod)模塊的單獨副本,因此可以編寫模塊而不必擔心線程安全,因為每個副本僅在其垂直線程上執行。 但是,OSGi用戶可能很高興要求可重用的模塊具有線程安全性,并謹慎地管理任何可變的靜態數據,以避免線程之間的泄漏。 ?

更換容器?

當我提出將vert.x嵌入OSGi的話題時, vert.x的負責人蒂姆·福克斯(Tim Fox)問我是否正在編寫當前容器的替代品,對此我回答“不是真的”。 我之所以這樣說,是因為我喜歡vert.x的事件驅動編程模型及其線程模型,它們似乎是“容器”的一部分。 但想更換一對夫婦的vert.x容器方面:模塊系統和verticles登記處理的方式。

后來讓我吃驚的是,在模塊化系統中,“容器”作為整體實體的概念可能有點奇怪,最好考慮多個單獨的容器概念,然后以不同的方式組合以適應不同的容器用戶。 但是,上面看到的類加載和線程模型之間的微妙交互表明,包含的不同概念可以相互依賴。 我想知道其他人如何看待“容器”的概念嗎?

結論

由于OSGi框架是一個相當嚴格的應用程序,因此vert.x聲稱它可以嵌入其他應用程序中的說法已得到驗證。

vert.x模塊系統盡管未在模塊之間提供隔離,但確實在應用程序之間(包括垂直模塊及其模塊)提供了隔離,并且使模塊的編寫無需關注線程安全。

提出了一個vert.x問題2 ,這應該使vert.x易于使用自定義類加載器嵌入其他環境。

vert.x可以遵循netty,jackson和MongoDB JAR的示例,并在其核心JAR和平臺JAR中包含OSGi清單,以避免OSGi用戶不得不將這些JAR轉換為OSGi捆綁包。 我將這個問題留給其他人提出,因為我無法評估在OSGi中使用vert.x的需求。

在OSGi中運行vert.x可以滿足一些出色的vert.x要求,例如如何自動化容器內測試(OSGi有許多解決方案,包括Pax Exam,而Virgo有集成測試框架)以及如何開發verticles并將它們部署到vert .x在IDE的控制下(請參閱Virgo IDE工具指南 )。 處女座還提供了許多附帶的好處,包括用于檢查和管理束和頂點的管理外殼,復雜的診斷程序以及更多其他功能(有關詳細信息,請參閱處女座白皮書 )。

該練習還為處女座帶來了一些不錯的收益。 修復了370253錯誤 ,這是在Java 7下運行Virgo的唯一已知問題。Virgo3.5依賴于在此環境中中斷的Gemini藍圖,因此引發并修復了錯誤379384 。 我使用了新的基于Eclipse的Virgo工具來開發各種捆綁軟件并在Virgo中運行它們。 結果,我在工具中發現了一些小問題,這些問題將適時解決。

最后,在Virgo內核上運行vert.x是對內核是否適合構建自定義服務器運行時的進一步驗證,因為現在除了Tomcat,Jetty以及在內核上運行的一兩個自定義服務器之外,我們還具有vert.x。

腳注:

  1. 在IBM的日子里,我曾在CICS開發團隊中工作。 SpringSource的一位同事給了我“ CICS做到了!” 我們開始合作后不久就穿了T恤。 舊習難改。
  2. 模塊化垂直模塊當前需要攔截vert.x的資源查找邏輯,以便可以輕松提供捆綁中的文件。 將此通用代碼移至org.vertx.osgi捆綁包會更好,但這需要首先實現vert.x問題161 。

參考: OSGi案例研究:來自Mind the Gap博客的JCG合作伙伴 Glyn Normington 的模塊化vert.x。


翻譯自: https://www.javacodegeeks.com/2012/07/osgi-case-study-modular-vertx.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371783.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371783.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371783.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql一些常用操作_表的一些常用操作_MySQL

bitsCN.com-創建表(也就是創建表結構)&#xff1a;create table tbl_name(列結構&#xff0c;即有哪些屬性)[表選項]; 如&#xff1a;班級的信息&#xff1a;(班級編號&#xff0c;開班日期)create table java_class(class_num varchar(10),date_start date);注&#xff1a;該表…

網站appache的ab命令壓力測試性能

①&#xff1a;相關不錯的博文鏈接&#xff1a;http://johnnyhg.iteye.com/blog/523818 ②&#xff1a;首先配置好對應的環境上去&#xff0c;有對應的命令 ③&#xff1a;壓力測試的指令如下&#xff1a; 1. 最基本的關心兩個選項 -c -n例&#xff1a; ./ab -c 100 -n 10000 &…

如何調整自定義標簽樣式

用chromeF12&#xff0c;查看網頁代碼在自定義標簽上加class&#xff0c;寫樣式&#xff1a;例如&#xff1a;JSP文件&#xff1a;來自為知筆記(Wiz)轉載于:https://www.cnblogs.com/anobugworld/p/7112116.html

無需部署即可測試JPQL / HQL

您是否曾經想在不完全部署應用程序的情況下測試JPQL / HQL&#xff1f; 我們今天在這里看到的是適用于任何JPA實現的簡單解決方案&#xff1a;Hibernate&#xff0c;OpenJPA&#xff0c;EclipseLink等。 這篇文章中找到的基本源代碼來自于本書&#xff1a;“ Pro JPA 2&#xf…

freemarker頁面中文亂碼

一、前言 簡單的記錄freemarker遇到的錯誤問題&#xff1a;ftl頁面中文亂碼 由于freemarker整合在ssm框架中&#xff0c;所以筆者直接貼配置代碼 <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-ins…

了解ThreadLocal背后的概念

介紹 我知道本地線程&#xff0c;但直到最近才真正使用過它。 因此&#xff0c;我開始深入研究該主題&#xff0c;因為我需要一種傳播某些用戶信息的簡便方法 通過Web應用程序的不同層&#xff0c;而無需更改每個調用方法的簽名。 小前提信息 線程是具有自己的調用棧的單個…

python加密模塊教程_Python加密模塊的hashlib,hmac模塊使用解析

這篇文章主要介紹了Python加密模塊的hashlib,hmac模塊使用解析,文中通過示例代碼介紹的非常詳細&#xff0c;對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下在寫搬磚腳本中&#xff0c;碰到一個加密的信號標簽文件無法運行。import hashlibimport timem ha…

DAO層–救援通用

泛型可以是使用編譯時驗證&#xff08;類型安全性&#xff09;的功能來創建可重用代碼的強大工具。 不幸的是&#xff0c;我感到主流開發人員仍然對此感到恐懼。 但是&#xff0c;比喻海格的蜘蛛&#xff0c;我會說泛型是被嚴重誤解的生物……:-) 我希望以下示例可以證明它們…

ThreadLocal詳解(實現多線程同步訪問變量)

ThreadLocal翻譯成中文比較準確的叫法應該是&#xff1a;線程局部變量。 這個玩意有什么用處&#xff0c;或者說為什么要有這么一個東東&#xff1f;先解釋一下&#xff0c;在并發編程的時候&#xff0c;成員變量如果不做任何處理其實是線程不安全的&#xff0c;各個線程都 在操…

SCREEN屏幕編程時候必須保證SCREN中詞典的字段格式必須和數據表中字段的類型長度一致!...

此時任意操作都會出現如下問題 /h調試 回車調試被激活任意操作 執行到第23行時候報錯“請輸入一個數值”&#xff0c;檢查數據表中字段參考數據元素以及對應的域均是char類型&#xff0c;此時檢查screen屏幕設置字段類型&#xff0c;/n退出程序 重新進入程序 單擊 點擊屏幕9000…

mysql 阿里云 版本_關于阿里云centos版本,mysql5.7的一些注意事項

1.阿里云進去mysql是默認已經安裝好了的&#xff0c;只需要修改root用戶的密碼。關于修改密碼&#xff1a;1)登陸阿里云&#xff0c;進入root目錄&#xff0c;會有mysql的.sh文件&#xff0c;可以通過運行該文件得到初始密碼。此時用初始密碼登陸mysql&#xff0c;use mysql 切…

JAXB –不需要注釋

似乎存在一個誤解&#xff0c;認為在模型上需要使用批注才能使用JAXB&#xff08;JSR-222&#xff09;實現。 事實是&#xff0c;JAXB是例外配置&#xff0c;因此僅當您要覆蓋默認行為時才需要注釋。 在此示例中&#xff0c;我將演示如何在不提供任何元數據的情況下使用JAXB。 …

zabbix 3.0.3 (nginx)安裝過程中的問題排錯記錄

特殊注明&#xff1a;安裝zabbix 2.4.8和2.4.6遇到2個問題&#xff0c;如下&#xff1a;找了很多解決辦法&#xff0c;實在無解&#xff0c;只能換版本&#xff0c;嘗試換&#xff08;2.2.2正常 | 3.0.3正常&#xff09;都正常&#xff0c;最后決定換3.0.31、Error connecting …

安裝mysql5.7.24rpm_centos7安裝mysql-5.7.24(rpm安裝)

關于mysql的4個rpm包node[rootelk-200 ~]# ls mysql/ -lhtotal 192M-rw-r--r-- 1 root root 25M Aug 26 12:38 mysql-community-client-5.7.24-1.el7.x86_64.rpm-rw-r--r-- 1 root root 275K Aug 26 12:38 mysql-community-common-5.7.24-1.el7.x86_64.rpm-rw-r--r-- 1 root ro…

Java鎖實現

我們都使用第三方庫作為開發的正常部分。 通常&#xff0c;我們無法控制其內部。 JDK隨附的庫是一個典型示例。 這些庫中的許多庫都使用鎖來管理競爭。 JDK鎖具有兩種實現。 人們使用原子CAS樣式指令來管理索賠過程。 CAS指令往往是最昂貴的CPU指令類型&#xff0c;并且在x86上…

一鍵生成APP官網

只需要輸入蘋果下載地址&#xff0c;安卓市場下載地址&#xff0c;或者內測下載地址&#xff0c;就能一鍵生成APP的官網&#xff0c;方便在網上推廣。 好推APP官網 www.hotapp.cn/app 轉載于:https://www.cnblogs.com/likwo/p/6223889.html

python 字符ab+字符c 2_“ab”+”c”*2 結果是: (1.3分)_學小易找答案

【判斷題】藥物效應動力學簡稱藥效學,是研究藥物對機體的作用?【單選題】以下關于Python語言中“縮進”說法正確的是:?????????????????????????????????????????????????????????????????????????…

數據結構及算法 -- 目錄

排序算法 -- 目錄 啦啦啦轉載于:https://www.cnblogs.com/ClassNotFoundException/p/7122848.html

Spring MVC集成測試

在Spring MVC中對控制器進行集成測試的一種方法是使用Spring提供的集成測試支持。 對于Junit4&#xff0c;此支持包括一個名為SpringJunit4ClassRunner的自定義Junit Runner和一個用于加載相關Spring配置的自定義批注。 樣本集成測試將遵循以下原則&#xff1a; RunWith(Spri…

spark 快速入門 java API

Spark的核心就是RDD&#xff0c;對SPARK的使用入門也就是對RDD的使用&#xff0c;包括action和transformation 對于Java的開發者&#xff0c;單單看文檔根本是沒有辦法理解每個API的作用的&#xff0c;所以每個SPARK的新手&#xff0c;最好按部就班直接學習scale, 那才是一個高…