日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JSR-308和Checker框架为jOOQ 3.9添加了更多类型安全性

發(fā)布時(shí)間:2023/12/3 javascript 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JSR-308和Checker框架为jOOQ 3.9添加了更多类型安全性 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Java 8引入了JSR-308,它為Java語言添加了新的注釋功能。 最重要的是:鍵入注釋。 現(xiàn)在可以像下面這樣設(shè)計(jì)怪物了:

比注解更瘋狂的是類型注解。 在數(shù)組上。 誰認(rèn)為這是有效的Java代碼? pic.twitter.com/M9fSRRerAD

— Lukas Eder(@lukaseder) 2016年3月20日

該推文中顯示的代碼確實(shí)可以編譯。 現(xiàn)在可以注釋每種類型,以便以任何自定義方式增強(qiáng)類型系統(tǒng)。 為什么,你可能會(huì)問? 這種語言增強(qiáng)的主要驅(qū)動(dòng)用例之一是checker框架 ,這是一個(gè)開放源代碼庫,可讓您輕松實(shí)現(xiàn)任意編譯器插件以進(jìn)行復(fù)雜的類型檢查。 最無聊和瑣碎的例子是可空性。 考慮以下代碼:

import org.checkerframework.checker.nullness.qual.Nullable;class YourClassNameHere {void foo(Object nn, @Nullable Object nbl) {nn.toString(); // OKnbl.toString(); // Failif (nbl != null)nbl.toString(); // OK again} }

上面的示例可以直接在checker框架實(shí)時(shí)演示控制臺(tái)中運(yùn)行 。 使用以下注釋處理器編譯以上代碼:

javac -processor org.checkerframework.checker.nullness.NullnessChecker afile.java

產(chǎn)量:

錯(cuò)誤:[dereference.of.nullable]取消引用可能為空的引用nbl:5:9

太棒了! 例如,它的工作方式與在Ceylon或Kotlin中 實(shí)現(xiàn)的流敏感類型非常相似,不同之處在于它更為冗長。 但是它也要強(qiáng)大得多,因?yàn)榭梢允褂米⑨屘幚砥髦苯釉贘ava中實(shí)現(xiàn)實(shí)現(xiàn)增強(qiáng)的和帶注釋的Java類型系統(tǒng)的規(guī)則! 通過某種方式使注解圖靈完整。��

這對(duì)jOOQ有什么幫助?

jOOQ已經(jīng)提供了兩種類型的API文檔注釋。 這些注釋是:

  • @PlainSQL –表示DSL方法接受“純SQL”字符串,這可能會(huì)帶來SQL注入風(fēng)險(xiǎn)
  • @Support –表示DSL方法可以本機(jī)工作,或者可以針對(duì)給定的SQLDialect集進(jìn)行仿真

這種方法的一個(gè)示例是CONNECT BY子句 ,該子句得到Cubrid,Informix和Oracle的支持,為了方便起見,它也被重載為也接受“普通SQL”謂詞:

@Support({ CUBRID, INFORMIX, ORACLE }) @PlainSQL SelectConnectByConditionStep<R> connectBy(String sql);

到目前為止,這些注釋僅用于文檔目的。 使用jOOQ 3.9后,不再可用。 現(xiàn)在,我們向jOOQ API引入了兩個(gè)新的注釋:

  • org.jooq.Allow –允許在給定范圍內(nèi)使用一組方言(或@PlainSQL批注)
  • org.jooq.Require –在給定范圍內(nèi)要求通過@Support注釋支持一組方言

最好通過示例來解釋。 讓我們先看看@PlainSQL

限制對(duì)

使用jOOQ API的最大優(yōu)點(diǎn)之一就是SQL注入已經(jīng)成為過去。 由于jOOQ是內(nèi)部特定于域的語言,因此用戶確實(shí)可以直接在Java代碼中直接定義SQL表達(dá)式樹,而不是像JDBC那樣使用聲明的字符串化版本。 表達(dá)式樹是用Java編譯的,因此不可能通過用戶輸入注入任何不需要的或無法預(yù)見的表達(dá)式。

但是有一個(gè)例外。 jOOQ并不支持每個(gè)數(shù)據(jù)庫中的所有SQL功能。 這就是jOOQ附帶豐富的“普通SQL” API的原因,在該API中,可以將自定義SQL字符串嵌入SQL表達(dá)式樹中的任何位置。 例如,上面的CONNECT BY子句:

DSL.using(configuration).select(level()).connectBy("level < ?", bindValue).fetch();

上面的jOOQ查詢轉(zhuǎn)換為以下SQL查詢:

SELECT level FROM dual CONNECT BY level < ?

如您所見,完全有可能“做錯(cuò)”并產(chǎn)生SQL注入風(fēng)險(xiǎn),就像在JDBC中一樣:

DSL.using(configuration).select(level()).connectBy("level < " + bindValue).fetch();

區(qū)別非常細(xì)微。 使用jOOQ 3.9和checker框架,現(xiàn)在可以指定以下Maven編譯器配置:

<plugin><artifactId>maven-compiler-plugin</artifactId><version>3.3</version><configuration><source>1.8</source><target>1.8</target><fork>true</fork><annotationProcessors><annotationProcessor>org.jooq.checker.PlainSQLChecker</annotationProcessor></annotationProcessors><compilerArgs><arg>-Xbootclasspath/p:1.8</arg></compilerArgs></configuration> </plugin>

org.jooq.checker.PlainSQLChecker將確保不會(huì)編譯使用帶有@PlainSQL注釋的API的客戶端代碼。 我們收到的錯(cuò)誤消息是這樣的:

C:\ Users \ lukas \ workspace \ jOOQ \ jOOQ-examples \ jOOQ-checker-framework-example \ src \ main \ java \ org \ jooq \ example \ checker \ PlainSQLCheckerTests.java:[17,17]錯(cuò)誤:[普通]當(dāng)前范圍不允許使用SQL。 使用@ Allow.PlainSQL。]

如果您知道自己在做什么,并且絕對(duì)必須在非常特定的位置(范圍)使用jOOQ的@PlainSQL API,則可以使用@Allow.PlainSQL對(duì)該位置(范圍)進(jìn)行注釋,并且代碼可以再次正常編譯:

// Scope: Single method. @Allow.PlainSQL public List<Integer> iKnowWhatImDoing() {return DSL.using(configuration).select(level()).connectBy("level < ?", bindValue).fetch(0, int.class); }

甚至:

// Scope: Entire class. @Allow.PlainSQL public class IKnowWhatImDoing {public List<Integer> iKnowWhatImDoing() {return DSL.using(configuration).select(level()).connectBy("level < ?", bindValue).fetch(0, int.class);} }

甚至(但是您可能只是關(guān)閉檢查器):

// Scope: entire package (put in package-info.java) @Allow.PlainSQL package org.jooq.example.checker;

好處是顯而易見的。 如果安全性對(duì)您非常重要(應(yīng)該如此),則只需在每個(gè)開發(fā)人員版本或至少在CI版本中啟用org.jooq.checker.PlainSQLChecker ,并在“偶然”使用@PlainSQL API時(shí)獲得編譯錯(cuò)誤遇到。

限制對(duì)

現(xiàn)在,對(duì)于大多數(shù)用戶而言,更有趣的是能夠檢查客戶端代碼中使用的jOOQ API是否確實(shí)支持您的數(shù)據(jù)庫。 例如,上面的CONNECT BY子句僅在Oracle中受支持(如果我們忽略不太流行的Cubrid和Informix數(shù)據(jù)庫)。 假設(shè)您僅使用Oracle。 您要確保您使用的所有jOOQ API都與Oracle兼容。 現(xiàn)在,您可以將以下注釋添加到所有使用jOOQ API的軟件包中:

// Scope: entire package (put in package-info.java) @Allow(ORACLE) package org.jooq.example.checker;

現(xiàn)在,只需激活org.jooq.checker.SQLDialectChecker來鍵入代碼以檢查@Allow符合性,即可完成:

<plugin><artifactId>maven-compiler-plugin</artifactId><version>3.3</version><configuration><source>1.8</source><target>1.8</target><fork>true</fork><annotationProcessors><annotationProcessor>org.jooq.checker.SQLDialectChecker</annotationProcessor></annotationProcessors><compilerArgs><arg>-Xbootclasspath/p:1.8</arg></compilerArgs></configuration> </plugin>

從現(xiàn)在開始,每當(dāng)您使用任何jOOQ API時(shí),上述檢查器都將驗(yàn)證以下三個(gè)值是否為true:

  • 正在使用的jOOQ API未使用@Support注釋
  • 使用的jOOQ API帶有@Support注釋,但沒有任何顯式的SQLDialect (即“可在所有數(shù)據(jù)庫上工作”),例如DSLContext.select()
  • 使用的jOOQ API帶有@Support注釋,并帶有SQLDialects引用的至少一個(gè)@Allow

因此,在這樣標(biāo)注的包裝中……

// Scope: entire package (put in package-info.java) @Allow(ORACLE) package org.jooq.example.checker;

……使用這樣注釋的方法就可以了:

@Support({ CUBRID, INFORMIX, ORACLE }) @PlainSQL SelectConnectByConditionStep<R> connectBy(String sql);

…但是使用這樣注釋的方法不是:

@Support({ MARIADB, MYSQL, POSTGRES }) SelectOptionStep<R> forShare();

為了允許使用此方法,例如,客戶端代碼除了可以使用ORACLE語言外,還可以使用MYSQL語言:

// Scope: entire package (put in package-info.java) @Allow({ MYSQL, ORACLE }) package org.jooq.example.checker;

從現(xiàn)在開始,此程序包中的所有代碼都可能引用支持MySQL和/或Oracle的方法。

@Allow批注有助于在全局級(jí)別上訪問API。 多個(gè)@Allow注釋(范圍可能不同)創(chuàng)建了允許的方言的@Allow取關(guān)系,如下所示:

// Scope: class @Allow(MYSQL) class MySQLAllowed {@Allow(ORACLE)void mySQLAndOracleAllowed() {DSL.using(configuration).select()// Works, because Oracle is allowed.connectBy("...")// Works, because MySQL is allowed.forShare();} }

從上面可以看出,析取兩個(gè)方言不能確保給定的語句在兩個(gè)數(shù)據(jù)庫中都可以使用。 所以…

如果我希望同時(shí)支持兩個(gè)數(shù)據(jù)庫怎么辦?

在這種情況下,我們將使用新的@Require注釋。 多個(gè)@Require注釋(范圍可能不同)創(chuàng)建所需方言的合集,如下所示:

// Scope: class @Allow @Require({ MYSQL, ORACLE }) class MySQLAndOracleRequired {@Require(ORACLE)void onlyOracleRequired() {DSL.using(configuration).select()// Works, because only Oracle is required.connectBy("...")// Doesn't work because Oracle is required.forShare();} }

如何使用

假設(shè)您的應(yīng)用程序僅需要與Oracle一起使用。 現(xiàn)在,您可以在軟件包上添加以下注釋,例如,由于在您的代碼中不允許將MySQL作為方言,因此您將無法使用任何僅MySQL的API:

@Allow(ORACLE) package org.jooq.example.checker;

現(xiàn)在,隨著需求的變化,您還希望從應(yīng)用程序中也開始支持MySQL。 只需將軟件包規(guī)格更改為以下內(nèi)容,然后開始修復(fù)jOOQ使用中的所有編譯錯(cuò)誤。

// Both dialects are allowed, no others are @Allow({ MYSQL, ORACLE })// Both dialects are also required on each clause @Require({ MYSQL, ORACLE }) package org.jooq.example.checker;

默認(rèn)值

默認(rèn)情況下,對(duì)于任何范圍, org.jooq.checker.SQLDialectChecker都采用以下注釋:

  • 什么都不允許。 每個(gè)@Allow批注都會(huì)添加到允許的方言集中。
  • 一切都是必需的。 每個(gè)@Require批注將從必填方言集中刪除。

實(shí)際觀看

這些功能將是jOOQ 3.9的組成部分。 只需添加以下依賴項(xiàng)即可使用它們:

<dependency><!-- Use org.jooq for the Open Source editionorg.jooq.pro for commercial editions, org.jooq.pro-java-6 for commercial editions with Java 6 support,org.jooq.trial for the free trial edition --><groupId>org.jooq</groupId><artifactId>jooq-checker</artifactId><version>${org.jooq.version}</version> </dependency>

…,然后為您的編譯器插件選擇適當(dāng)?shù)淖⑨屘幚砥鳌?

不能等到j(luò)OOQ 3.9嗎? 不用了 只需從GitHub上檢查3.9.0-SNAPSHOT版本,然后按照此處給出的示例項(xiàng)目進(jìn)行操作:

  • https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-checker-framework-example

做完了! 從現(xiàn)在開始,使用jOOQ時(shí),您可以確保編寫的任何代碼都可以在計(jì)劃支持的所有數(shù)據(jù)庫上運(yùn)行!

我認(rèn)為,今年的Annotatiomaniac冠軍頭銜應(yīng)該交給檢查框架的制定者:

有關(guān)檢查器框架的更多信息:

  • http://types.cs.washington.edu/checker-framework/
  • http://eisop.uwaterloo.ca/live#mode=display(實(shí)時(shí)演示)

翻譯自: https://www.javacodegeeks.com/2016/05/jsr-308-checker-framework-add-even-typesafety-jooq-3-9.html

總結(jié)

以上是生活随笔為你收集整理的JSR-308和Checker框架为jOOQ 3.9添加了更多类型安全性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。