假设我有一个使用Maven 3和junit的Java项目.有src/main/java和src/test/java目录分别包含主要来源和测试来源(一切都是标准的).
现在我想将项目迁移到Java 9. src/main/java内容代表Java 9模块; 有com/acme/project/module-info.java看大约是这样的:
module com.acme.project {
require module1;
require module2;
...
}
Run Code Online (Sandbox Code Playgroud)
如果测试代码需要module-info.java自己怎么办?例如,添加对某些模块的依赖性,该模块仅用于测试,而不是生产代码.在这种情况下,我必须把module-info.java以src/test/java/com/acme/project/给模块不同的名称.这样Maven似乎将主要源和测试源视为不同的模块,因此我必须将包从主模块导出到测试模块,并且需要测试模块中的包,如下所示:
主模块(in src/main/java/com/acme/project):
module prod.module {
exports com.acme.project to test.module;
}
Run Code Online (Sandbox Code Playgroud)
测试模块(in src/test/java/com/acme/project):
module test.module {
requires junit;
requires prod.module;
}
Run Code Online (Sandbox Code Playgroud)
这产生了
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:testCompile (default-testCompile) on project test-java9-modules-junit: Compilation failure: Compilation failure:
[ERROR] /home/rpuch/git/my/test-java9-modules-junit/src/test/java/com/acme/project/GreeterTest.java:[1,1] package exists in another module: prod.module
Run Code Online (Sandbox Code Playgroud)
因为一个包在两个模块中定义.所以现在我必须在主模块和测试模块中有不同的项目,这是不方便的.
我觉得我走错了道路,一切都开始看起来非常难看.如何module-info.java在测试代码中拥有自己的代码,或者如何在没有测试代码的情况下实现相同的效果(require …
我有一个测试:
public class ResourceTest {
@Test
public void test() throws ClassNotFoundException {
Class.forName("javax.annotation.Resource");
}
}
Run Code Online (Sandbox Code Playgroud)
它试图访问javax.annotation.Resource.在java 8中它可以工作,但是在java 9中(我使用的是Oracle JDK 9)它失败了ClassNotFoundException.正如本文所解释的那样:@Resource注入在JDK9下停止工作,javax.annotation.ResourceJDK在Java 9中默认不可用.
我正在尝试使用模块描述符访问它:
module test {
requires java.xml.ws.annotation;
requires junit;
}
Run Code Online (Sandbox Code Playgroud)
在这里,我特意请求访问java.xml.ws.annotation模块(包含javax.annotation.Resource).但测试仍然失败.
当我删除该requires子句并添加包含的依赖项(作为库)时javax.annotations.Resource,它可以工作:
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.1</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
当我同时添加它们(Maven依赖于pom.xml和requires java.xml.ws.annotation)时,IDEA中的编译失败,并显示以下消息:
the unnamed module reads package javax.annotation from both java.xml.ws.annotation and java.annotation
Run Code Online (Sandbox Code Playgroud)
但Maven构建仍然成功!
如果我java.xml.ws.annotation通过命令行添加模块,它可以工作(没有Maven依赖和with requires子句):
mvn clean test …Run Code Online (Sandbox Code Playgroud) 在我的@Configuration课堂上,我有如下的家属:
@Configuration
public class MyConfig {
@Resource(name = "firstDataSource")
private DataSource firstDataSource;
// more code
}
Run Code Online (Sandbox Code Playgroud)
在Oracle JDK 8:firstDataSource字段中工作的依赖项注入已成功注入非null值.
现在我尝试在JDK 9中运行应用程序(没有修改).结果是@Resource不再触发依赖注入:使用此注释注释的所有内容仍然存在null.
什么可能是@Resource停止工作的原因?
在项目中使用Spring 4.0.9.
这是一个测试项目,展示了这个问题:https://github.com/rpuch/test-spring-injection-jdk9
它包含一个测试:MainTest我从IDE运行.当我使用JDK 8时,它会输出
??? 29, 2017 10:45:13 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5f8ed237: startup date [Fri Sep 29 22:45:13 SAMT 2017]; root of context hierarchy
OK
Run Code Online (Sandbox Code Playgroud)
但是在JDK 9下,它会在启动期间抛出异常,这是由以下原因造成的:
Caused by: java.lang.IllegalStateException: bean1 is not injected
at Bean2.<init>(Bean2.java:7)
at Config2.bean2(Config2.java:16)
Run Code Online (Sandbox Code Playgroud)
当没有注入依赖时会发生这种情况.
在org.springframework.core.SerializableTypeWrapper(5.2.3版)中,第112行有如下代码:
if (GraalDetector.inImageCode() || !Serializable.class.isAssignableFrom(Class.class)) {
// Let's skip any wrapping attempts if types are generally not serializable in
// the current runtime environment (even java.lang.Class itself, e.g. on Graal)
return providedType;
}
Run Code Online (Sandbox Code Playgroud)
我对第二个检查 ( !Serializable.class.isAssignableFrom(Class.class))很好奇:它是否可以评估为true(即,Serialazable.class不可从 分配Class.class)?
这是Class#isAssignableFrom()javadoc 所说的:
确定此 Class 对象表示的类或接口是否与指定的 Class 参数表示的类或接口相同,或者是其超类或超接口。
查看 的代码Class,我看到以下内容:
public final class Class<T> implements java.io.Serializable
Run Code Online (Sandbox Code Playgroud)
Serializable的超级接口也是如此,Class并且应该始终可以从Class. 但是 Spring 代码中的检查表明有时并非如此。
怎么来的?在什么情况下会发生这种情况,为什么它们不违反 Java 语言规范?
我有一个使用 Micronaut 2.0.0 实现 RESTful API 的小 Java 应用程序。在幕后,它使用 Redisson 3.13.1 转到 Redis。Redisson 反过来使用 Netty (4.1.49)。
该应用程序在“经典”java(在 HotSpot 上,Java 8 和 11)中运行良好。
我正在尝试使用 GraalVM 从此应用程序构建本机映像。
命令大概是这样的:
native-image --no-server --no-fallback -H:+TraceClassInitialization -H:+PrintClassInitialization --report-unsupported-elements-at-runtime --initialize-at-build-time=reactor.core.publisher.Flux,reactor.core.publisher.Mono -H:ConfigurationFileDirectories=target/config -cp target/app-1.0.0-SNAPSHOT.jar com.app.AppApplication target/app
Run Code Online (Sandbox Code Playgroud)
这是我得到的:
Error: Unsupported features in 4 methods
Detailed message:
Error: No instances of java.net.Inet4Address are allowed in the image heap as this class should be initialized at image runtime. Object has been initialized without the native-image initialization instrumentation and the …Run Code Online (Sandbox Code Playgroud) 我得到了一个自签名的客户端证书工具包,该工具包将用于通过HTTPS访问服务器。该套件包含以下PEM文件:
解决任务的一种方法是生成Java密钥库:
...然后使用类似以下的代码来构建SSLSocketFactory实例:
InputStream stream = new ByteArrayInputStream(pksData);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(stream, password);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(
KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, password.toCharArray());
KeyManager[] keyManagers = kmf.getKeyManagers();
TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmfactory.init(keyStore);
TrustManager[] trustManagers = tmfactory.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);
sslSocketFactory = sslContext.getSocketFactory();
Run Code Online (Sandbox Code Playgroud)
...以后用于初始化http库。
因此,我们获得了一个KeyStore,然后在其帮助下初始化KeyManagers和TrustManagers,最后我们用它们构建SSLSocketFactory实例。
问题是:是否有一种方法可以避免创建密钥库文件,并以某种方式从PublicKey和Certificate实例开始构建SSLSocketFactory(例如,可以使用bouncycastle的PemReader从PEM文件中获取)?
我有以下代码:
final TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
Run Code Online (Sandbox Code Playgroud)
第二行在带有默认值的现代JDK(我尝试过1.8)中运行良好TransformerFactory。但是,当我xalan向类路径添加(最新的版本2.7.2)时,在第二行得到以下内容:
Exception in thread "main" java.lang.IllegalArgumentException: Not supported: http://javax.xml.XMLConstants/property/accessExternalDTD
at org.apache.xalan.processor.TransformerFactoryImpl.setAttribute(TransformerFactoryImpl.java:571)
at Main.main(Main.java:11)
Run Code Online (Sandbox Code Playgroud)
我猜这是因为xalan's TransformerFactory不支持此属性。Xalan的实现通过以下ServiceLoader机制获得:services/javax.xml.transform.TransfomerFactory在xalan jar中指定。
可以TransformerFactory使用javax.xml.transform.TransformerFactory系统属性或$JRE/lib/jaxp.properties文件覆盖实现,也可以直接在代码中传递类名称。但是要做到这一点,我必须提供一个具体的类名。现在是com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl,但是在系统属性中对其进行硬编码有点吓人,因为在JDK升级中,它们可以轻松更改类名,而我们只会遇到运行时错误。
有什么方法可以指示TransformerFactory.newInstance()忽略Xalan提供的实现吗?或告诉它“仅使用系统默认值”。
PS我不能仅仅xalan从类路径中删除,因为我们使用的许多其他库都依赖于它。
有一个服务类需要PublicKey从X.509编码的公钥表示形式生成实例。此类的一个实例将服务多个线程。这样做是正确的吗?
public class MyService {
private final KeyFactory rsaKeyFactory;
public MyService() throws NoSuchAlgorithmException {
rsaKeyFactory = KeyFactory.getInstance("RSA");
}
public PublicKey generatePublicKey(byte[] publicKeyBytes) throws GeneralSecurityException {
return rsaKeyFactory.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
}
}
Run Code Online (Sandbox Code Playgroud)
即KeyFactory这里使用的实例是线程安全的吗?generatePublicKey()方法可以由不同的线程同时调用。
Javadocs似乎没有提到线程安全性。
如果我没有理解错的话,AuthenticationProvider用于UserDetailsService检索用户的属性以验证Authentication对象。
问题是在下一个代码中没有配置 aAuthenticationProvider和 a UserDetailsService。
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("pass").roles("ADMIN").and().withUser("user1")
.password("pass").roles("USER");
}
Run Code Online (Sandbox Code Playgroud)
但认证服务已经设置。
我的问题是,是否有一个实现AuthenticationProvider和另一个实现UserDetailsService被添加到内部的 spring 上下文中?在这种情况下,使用的实现是什么(在内存身份验证的情况下)。
*.withUser("user").password("pass").roles("ADMIN")*配置部分是否代表UserDetailsService实现?
我的任务是使用nginx实现微缓存策略,即缓存一些POST端点的响应几秒钟。
在http部分nginx.conf我有以下内容:
proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inactive=600s max_size=100m;
Run Code Online (Sandbox Code Playgroud)
然后我location有server:
location /my-url/ {
root dir;
client_max_body_size 50k;
proxy_cache cache;
proxy_cache_valid 10s;
proxy_cache_methods POST;
proxy_cache_key "$request_uri|$request_body";
proxy_ignore_headers Vary;
add_header X-Cached $upstream_cache_status;
proxy_pass http://my-upstream;
}
Run Code Online (Sandbox Code Playgroud)
该应用程序位于输出处,如果我理解正确的my-upstream话Cache-Control: max-age=10,应该使响应可缓存。
但是当我在短时间内(不到10秒)使用curl发出重复请求时
curl -v --data "a=b&c=d" https://my-host/my-url/1573
Run Code Online (Sandbox Code Playgroud)
它们全部到达后端(根据后端日志)。还有,X-Cached总是MISS。
请求和响应如下:
> POST /my-url/1573 HTTP/1.1
> Host: my-host
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Length: 113
> Content-Type: application/x-www-form-urlencoded
>
* upload …Run Code Online (Sandbox Code Playgroud)