vue.jsr入门_JSR-308和Checker框架为jOOQ 3.9添加了更多类型安全性
vue.jsr入門
Java 8引入了JSR-308,它為Java語言添加了新的注釋功能。 最重要的是:鍵入注釋。 現(xiàn)在可以像下面這樣設(shè)計怪物了:
比注解更瘋狂的是類型注解。 在數(shù)組上。 誰認為這是有效的Java代碼? pic.twitter.com/M9fSRRerAD
— Lukas Eder(@lukaseder) 2016年3月20日
該推文中顯示的代碼確實可以編譯。 現(xiàn)在可以注釋每種類型,以便以任何自定義方式增強類型系統(tǒng)。 為什么,你可能會問? 這種語言增強功能的主要驅(qū)動用例之一是checker框架 ,這是一個開放源代碼庫,可讓您輕松實現(xià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框架實時演示控制臺中運行 。 使用以下注釋處理器編譯以上代碼:
javac -processor org.checkerframework.checker.nullness.NullnessChecker afile.java
產(chǎn)量:
錯誤:[dereference.of.nullable]取消引用可能為空的引用nbl:5:9
太棒了! 例如,它的工作方式與在Ceylon或Kotlin中 實現(xiàn)的流敏感類型非常相似,不同之處在于它更為冗長。 但是它也要強大得多,因為可以使用注釋處理器直接在Java中實現(xiàn)實現(xiàn)增強和注釋的Java類型系統(tǒng)的規(guī)則! 通過某種方式使注解圖靈變得完整。#55357;�
這對jOOQ有什么幫助?
jOOQ已經(jīng)提供了兩種類型的API文檔注釋。 這些注釋是:
- @PlainSQL –表示DSL方法接受“純SQL”字符串,這可能會帶來SQL注入風險
- @Support –表示DSL方法可以本機工作,或者可以針對給定的SQLDialect集進行仿真
這種方法的一個示例是CONNECT BY子句 ,Cubrid,Informix和Oracle支持該子句 ,為方便起見,它也被重載為也接受“普通SQL”謂詞:
@Support({ CUBRID, INFORMIX, ORACLE }) @PlainSQL SelectConnectByConditionStep<R> connectBy(String sql);到目前為止,這些注釋僅用于文檔目的。 使用jOOQ 3.9后,不再可用。 現(xiàn)在,我們向jOOQ API引入了兩個新的注釋:
- org.jooq.Allow –允許在給定范圍內(nèi)使用一組方言(或@PlainSQL批注)
- org.jooq.Require –在給定范圍內(nèi)要求通過@Support注釋支持一組方言
最好通過示例解釋。 讓我們先來看@PlainSQL
限制對
使用jOOQ API的最大優(yōu)點之一就是SQL注入已成為過去。 jOOQ是內(nèi)部特定于域的語言,因此用戶確實可以直接在Java代碼中直接定義SQL表達式樹,而不是像JDBC那樣使用聲明的字符串化版本。 表達式樹是用Java編譯的,因此不可能通過用戶輸入注入任何不需要的或無法預(yù)見的表達式。
但是有一個例外。 jOOQ并不支持每個數(shù)據(jù)庫中的所有SQL功能。 這就是jOOQ附帶豐富的“普通SQL” API的原因,在該API中,可以將自定義SQL字符串嵌入SQL表達式樹中的任何位置。 例如,上面的CONNECT BY子句:
DSL.using(configuration).select(level()).connectBy("level < ?", bindValue).fetch();上面的jOOQ查詢轉(zhuǎn)換為以下SQL查詢:
SELECT level FROM dual CONNECT BY level < ?如您所見,完全有可能“做錯了”并產(chǎn)生SQL注入風險,就像在JDBC中一樣:
DSL.using(configuration).select(level()).connectBy("level < " + bindValue).fetch();區(qū)別非常細微。 使用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將確保不會編譯使用帶有@PlainSQL注釋的API的客戶端代碼。 我們收到的錯誤消息是這樣的:
C:\ Users \ lukas \ workspace \ jOOQ \ jOOQ-examples \ jOOQ-checker-framework-example \ src \ main \ java \ org \ jooq \ example \ checker \ PlainSQLCheckerTests.java:[17,17]錯誤:[普通]當前范圍不允許使用SQL。 使用@ Allow.PlainSQL。]
如果您知道自己在做什么,并且絕對必須在非常特定的位置(范圍)使用jOOQ的@PlainSQL API,則可以使用@Allow.PlainSQL注釋該位置(范圍),并且代碼可以再次正常編譯:
// 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;好處是顯而易見的。 如果安全性對您非常重要(應(yīng)該如此),則只需在每個開發(fā)人員版本或至少在CI版本中啟用org.jooq.checker.PlainSQLChecker ,并在使用“偶然的” @PlainSQL API時獲得編譯錯誤。遇到。
限制對
現(xiàn)在,對于大多數(shù)用戶而言,更有趣的是能夠檢查客戶端代碼中使用的jOOQ API是否確實支持您的數(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)在開始,每當您使用任何jOOQ API時,上述檢查器都將驗證以下三個值是否為true:
- 正在使用的jOOQ API未使用@Support注釋
- 使用的jOOQ API帶有@Support注釋,但沒有任何顯式的SQLDialect (即“可在所有數(shù)據(jù)庫上運行”),例如DSLContext.select()
- 使用的jOOQ API帶有@Support注釋,并且至少具有SQLDialects引用的@Allow
因此,在這樣標注的包裝中……
// 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批注有助于在全局級別上訪問API。 多個@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();} }從上面可以看出,析取兩個方言不能確保給定的語句在兩個數(shù)據(jù)庫中都可以使用。 所以…
如果我希望同時支持兩個數(shù)據(jù)庫怎么辦?
在這種情況下,我們將使用新的@Require注釋。 多個@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使用中的所有編譯錯誤。
// 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;默認值
默認情況下,對于任何范圍, org.jooq.checker.SQLDialectChecker都采用以下注釋:
- 什么都不允許。 每個@Allow批注都會添加到允許的方言集中。
- 一切都是必需的。 每個@Require批注都將從必需的方言集中刪除。
實際觀看
這些功能將是jOOQ 3.9的組成部分。 只需添加以下依賴項即可使用它們:
<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>…,然后為您的編譯器插件選擇適當?shù)淖⑨屘幚砥鳌?
不能等到j(luò)OOQ 3.9嗎? 不用了 只需從GitHub上檢查3.9.0-SNAPSHOT版本,然后按照此處提供的示例項目進行操作:
- https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-checker-framework-example
做完了! 從現(xiàn)在開始,使用jOOQ時,您可以確保編寫的任何代碼都可以在計劃支持的所有數(shù)據(jù)庫上使用!
我認為,今年的Annotatiomaniac冠軍頭銜應(yīng)該交給檢查框架的制定者:
有關(guān)檢查器框架的更多信息:
- http://types.cs.washington.edu/checker-framework/
- http://eisop.uwaterloo.ca/live#mode=display(實時演示)
翻譯自: https://www.javacodegeeks.com/2016/05/jsr-308-checker-framework-add-even-typesafety-jooq-3-9.html
vue.jsr入門
總結(jié)
以上是生活随笔為你收集整理的vue.jsr入门_JSR-308和Checker框架为jOOQ 3.9添加了更多类型安全性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑怎么玩唱吧(电脑上怎么玩唱吧)
- 下一篇: html5倒计时秒杀怎么做,vue 设