vue.jsr入门_JSR-308和Checker框架为jOOQ 3.9添加了更多类型安全性

vue.jsr入门

Java 8引入了JSR-308,它为Java语言添加了新的注释功能。 最重要的是:键入注释。 现在可以像下面这样设计怪物了:

该推文中显示的代码确实可以编译。 现在可以注释每种类型,以便以任何自定义方式增强类型系统。 为什么,你可能会问? 这种语言增强功能的主要驱动用例之一是checker框架 ,这是一个开放源代码库,可让您轻松实现任意编译器插件以进行复杂的类型检查。 最无聊和琐碎的例子是可空性。 考虑以下代码:

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

产量:

错误:[dereference.of.nullable]取消引用可能为空的引用nbl:5:9

太棒了! 例如,它的工作方式与在Ceylon或Kotlin中 实现的流敏感类型非常相似,不同之处在于它更为冗长。 但是它也要强大得多,因为可以使用注释处理器直接在Java中实现实现增强和注释的Java类型系统的规则! 通过某种方式使注解图灵变得完整。#55357;�

这对jOOQ有什么帮助?

jOOQ已经提供了两种类型的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后,不再可用。 现在,我们向jOOQ API引入了两个新的注释:

  • org.jooq.Allow –允许在给定范围内使用一组方言(或@PlainSQL批注)
  • org.jooq.Require –在给定范围内要求通过@Support注释支持一组方言

最好通过示例解释。 让我们先来看@PlainSQL

限制对

使用jOOQ API的最大优点之一就是SQL注入已成为过去。 jOOQ是内部特定于域的语言,因此用户确实可以直接在Java代码中直接定义SQL表达式树,而不是像JDBC那样使用声明的字符串化版本。 表达式树是用Java编译的,因此不可能通过用户输入注入任何不需要的或无法预见的表达式。

但是有一个例外。 jOOQ并不支持每个数据库中的所有SQL功能。 这就是jOOQ附带丰富的“普通SQL” API的原因,在该API中,可以将自定义SQL字符串嵌入SQL表达式树中的任何位置。 例如,上面的CONNECT BY子句:

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

上面的jOOQ查询转换为以下SQL查询:

SELECT level
FROM dual
CONNECT BY level < ?

如您所见,完全有可能“做错了”并产生SQL注入风险,就像在JDBC中一样:

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

区别非常细微。 使用jOOQ 3.9和checker框架,现在可以指定以下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);}
}

甚至(但是您可能只是关闭检查器):

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

好处是显而易见的。 如果安全性对您非常重要(应该如此),则只需在每个开发人员版本或至少在CI版本中启用org.jooq.checker.PlainSQLChecker ,并在使用“偶然的” @PlainSQL API时获得编译错误。遇到。

限制对

现在,对于大多数用户而言,更有趣的是能够检查客户端代码中使用的jOOQ API是否确实支持您的数据库。 例如,上面的CONNECT BY子句仅在Oracle中受支持(如果我们忽略不太流行的Cubrid和Informix数据库)。 假设您仅使用Oracle。 您要确保您使用的所有jOOQ API都与Oracle兼容。 现在,您可以将以下注释添加到所有使用jOOQ API的软件包中:

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

现在,只需激活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>

从现在开始,每当您使用任何jOOQ API时,上述检查器都将验证以下三个值是否为true:

  • 正在使用的jOOQ API未使用@Support注释
  • 使用的jOOQ API带有@Support注释,但没有任何显式的SQLDialect (即“可在所有数据库上运行”),例如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;

从现在开始,此程序包中的所有代码都可能引用支持MySQL和/或Oracle的方法。

@Allow批注有助于在全局级别上访问API。 多个@Allow注释(可能具有不同的范围)会创建允许的方言的@Allow取关系,如下所示:

// 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();}
}

从上面可以看出,析取两个方言不能确保给定的语句在两个数据库中都可以使用。 所以…

如果我希望同时支持两个数据库怎么办?

在这种情况下,我们将使用新的@Require注释。 多个@Require批注(范围可能不同)创建所需方言的合集,如下所示:

// 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();}
}

如何使用

假设您的应用程序仅需要与Oracle一起使用。 现在,您可以在软件包上添加以下注释,例如,由于在您的代码中不允许将MySQL作为方言,因此您将无法使用任何仅MySQL的API:

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

现在,随着需求的变化,您希望从应用程序中也开始支持MySQL。 只需将软件包规格更改为以下内容,然后开始修复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>

…,然后为您的编译器插件选择适当的注释处理器。

不能等到jOOQ 3.9吗? 不用了 只需从GitHub上检查3.9.0-SNAPSHOT版本,然后按照此处提供的示例项目进行操作:

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

做完了! 从现在开始,使用jOOQ时,您可以确保编写的任何代码都可以在计划支持的所有数据库上使用!

我认为,今年的Annotatiomaniac冠军头衔应该交给检查框架的制定者:

有关检查器框架的更多信息:

  • 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入门

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336117.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数组索引必须为正整数或逻辑值_Office 365函数新世界——动态数组

革新一个旧的函数体系&#xff0c;无外乎从这么几个方面入手&#xff0c;函数的运行效率、函数的编写方式以及扩展新的函数功能。今天咱们就学习一下&#xff0c;看看365新函数是如何通过这三个方面打破旧函数条条框框的。365函数系列推出了一个新的概念&#xff0c;叫做动态数…

【Android OpenGL ES 开发 (零)】创建一个新的工程

创建符合要求的AndroidApp 使用Android Studio开发&#xff0c;Android Studio下载地址 1.先创建Native C 2.项目相关添加 3.使用C11标准 学习使用JNI为Java提供API 1.在cpp中定义相关接口&#xff0c;格式如下 2.外部调用这个API 把so改成自己想要的名字 1.需要在cmake文件…

java方法参数类型不确定_一个Java方法能有多少个参数类型?这个好奇coder做了个实验...

选自 justinblank机器之心编译参与&#xff1a;李志伟、张倩在 JVM 中&#xff0c;一个 Java 方法&#xff0c;最多能定义多少参数呢&#xff1f;这是一个很无聊的问题&#xff0c;即使能定义一万个&#xff0c;十万个&#xff0c;谁又会真的去这么做呢。但是作为一个 coder&am…

lagom的微服务框架_您的第一个Lagom服务– Java Microservices入门

lagom的微服务框架在撰写我的下一份OReilly报告时&#xff0c;我一直很沮丧&#xff0c;并且一段时间内没有足够的时间来撰写博客。 是时候赶快来这里&#xff0c;让您真正快速地开始使用名为Lagom的新微服务框架。 它与您从Java EE或其他应用程序框架中可能了解到的有所不同。…

【Android OpenGL ES 开发 (一)】使用c++开发opengles 与 日志功能 及 加载assets

创建OpenGLES视口 1.App窗口改成OpenGL窗口,是通过java调用C&#xff0c;在以下位置修改如下内容 package com.example.learnogles;import androidx.appcompat.app.AppCompatActivity;import android.content.Context; import android.opengl.GLSurfaceView; import android.o…

水印相机定位不准确怎么办_禄来的广角双反相机(2020版)

点击上方胶卷迷俱乐部快速关注&#xff0c;胶卷迷们坚实的阵地内容主要原创&#xff0c;配图来自群友和网络&#xff0c;所有水印保留最下方为微信自带广告&#xff0c;支持请点击(本号可获微量收入)4.0德国禄来公司以双反相机名震天下&#xff0c;其中的2.8&#xff0c;3.5两个…

【Android OpenGL ES 开发 (二)】渲染管线与Shader

计算出每一帧耗费的时间 1.在头文件中加入time.h,cpp中实现如下计算时间接口 float GetFrameTime(){static unsigned long long lastTime0,currentTime0;timeval current;gettimeofday(&current, nullptr);//取当前时间currentTime current.tv_sec * 1000 current.tv…

【Android OpenGL ES 开发 (三)】Shader 扩展

编译Shader代码 1.封装一个编译shader的接口 GLuint CompileShader(GLenum shaderType,const char *shaderCode){GLuint shaderglCreateShader(shaderType);glShaderSource(shader,1,&shaderCode,NULL);glCompileShader(shader);GLint compileResultGL_TRUE;glGetShaderi…

css阴影属性_第三场阴影场与属性访问器接口

css阴影属性这是“ 影子字段与属性访问器”界面的 第3轮 。 如果您是新手&#xff0c;但不确定要怎么做&#xff0c;请查看我以前的文章或关于开发JavaFX应用程序时节省内存的第一篇文章 。 作为Java开发人员&#xff0c;我主要关心的是在开发JavaFX域模型时在性能 &#xff0c…

js if判断多个条件_JS条件判断小技巧(一)

经常code review&#xff0c;我发现JS newbie很容易写出一堆冗长的代码。今天就列几个比较常见的“解决之道”&#xff0c;看看如何减少JS里的条件判断。提前返回&#xff0c;少用if...else“if...else是编程语言的精华。——鲁迅”但是过多的嵌套&#xff0c;还是挺令人抓狂的…

【Android OpenGL ES 开发 (四)】纹理相关(一)

纹理贴图的原理 1.作用&#xff1a;可以用来渲染视频。 2.纹理坐标 生成OpenGL中的纹理对象 1.像素数据想要绘制出来需要先变成纹理 2.创建纹理放在GPU上 GLuint CreateTexture2D(unsigned char *pixelData,int width,int height,GLenum type) {GLuint texture;glGenTextu…

jmx 替代_使用JMX作为Ganglia的现代替代品进行CLDB监视

jmx 替代有许多选项可用于监视MapR集群的性能和运行状况。 在本文中&#xff0c;我将介绍使用Java管理扩展&#xff08;JMX&#xff09;监视CLDB的鲜为人知的方法。 据最受尊敬的MapR数据工程师之一&#xff0c;Akihiko Kusanagi称&#xff0c;与使用Ganglia相比&#xff0c;使…

red hat安装宝塔_如何在几分钟内安装Red Hat Container Development Kit(CDK)

red hat安装宝塔作为负责开发容器化应用程序提供的可能性的应用程序开发人员或架构师&#xff0c;将所有工具组合在一起以帮助您入门时几乎没有帮助。 到现在。 红帽容器开发套件&#xff08;CDK&#xff09; 安装变得简单&#xff01; 红帽提供了一个容器开发套件&#xf…

threejs 影子属性_影子场vs.属性访问器接口第2轮

threejs 影子属性如果你们还没有注意到Dirk Lemmerman和我之间的&#xff08;轻松&#xff09; 摊牌 &#xff0c;那么让我快速提及一下我们是如何做到这一点的。 首先&#xff0c;Dirk创建了JavaFX技巧23&#xff1a;“ 为属性保存内存阴影字段 ”&#xff0c;以帮助应用程序开…

【OpenGL从入门到精通】Shader专题

详解GPU的工作流程 1.shader通常称为着色器&#xff0c;作用是把CPU上的点渲染出来。 2.shader是并行的。 3.流程&#xff1a;数据data (顶点数据) ----->VS(输入&#xff1a;data的顶点数据&#xff0c;输出&#xff1a;gl_Position的 vec4 顶点数据)----->光栅化处理…

【OpenGL从入门到精通(六)】纹理对象与纹理坐标

1.在OpenGL想要显示一张图片&#xff0c;需要先绘制一个自定义的几何体。 2.把图片加载到纹理对象中 3.当进行纹理贴图时候&#xff0c;使用纹理坐标来设置纹理对象。 2.

yeoman_具有Spring Boot和Yeoman的单页Angularjs应用程序

yeoman我非常感谢yeoman之类的工具&#xff0c;这些工具提供了一种非常快速的方法来将不同的javascript库组合在一起成为一个一致的应用程序。 Yeoman提供了UI层&#xff0c;如果您需要开发服务层和静态资产的Web层&#xff0c;则打包的一种好方法是使用Spring Boot 。 我知道有…

双向链表删除节点时间复杂度_「十分钟学算法」删除链表的倒数第N个节点

给定一个链表&#xff0c;删除链表的倒数第 n 个节点&#xff0c;并且返回链表的头结点。示例&#xff1a;给定一个链表: 1->2->3->4->5, 和 n 2.当删除了倒数第二个节点后&#xff0c;链表变为 1->2->3->5.说明&#xff1a;给定的 n 保证是有效的。题解…

netbeans连接数据库_NetBeans Java EE技巧3:数据库中的RESTful Web服务

netbeans连接数据库许多现代的Web应用程序正朝着使用HTTP使用无状态通信的方向发展。 REST&#xff08;表示状态转移&#xff09;体系结构样式通常用于设计网络应用程序&#xff0c;而使用Java EE 7&#xff0c;很容易开发用于数据库通信的RESTful后端。 使用简单的POJO&#x…