线程使用的System.setProperty会影响与外部网络元素通信的其他线程。 怎么解决?

在我的应用程序中,我有两个线程。 每个线程与不同的外部实体通信。

让我们说T1 – > N1和T2 – > N2(T1和T2是两个线程.N1和N2是外部实体。通信是基于HTTPS的SOAP。)

N1的供应商请求使用密钥存储文件UPCC_client.store进行身份validation,同样我们使用了以下代码,

 System.setProperty("javax.net.ssl.keyStore", ""); System.setProperty("javax.net.ssl.keyStorePassword", ""); System.setProperty("javax.net.ssl.trustStore",""); System.setProperty("javax.net.ssl.trustStorePassword", ""); 

已重新启动应用程序,并在T1线程中设置了上述属性,没有任何问题。 T2开始陷入困境,因为T1设置的属性正被T2使用。 这背后的主要原因是System.setProperty是JVM范围。 如何解决这个问题?

我怀疑你有一个设计问题,但有这个要求。

解决这个问题的唯一方法是我能想到的是使你的属性成为ThreadLocal。

 public class ThreadLocalProperties extends Properties { private final ThreadLocal localProperties = new ThreadLocal() { @Override protected Properties initialValue() { return new Properties(); } }; public ThreadLocalProperties(Properties properties) { super(properties); } @Override public String getProperty(String key) { String localValue = localProperties.get().getProperty(key); return localValue == null ? super.getProperty(key) : localValue; } @Override public Object setProperty(String key, String value) { return localProperties.get().setProperty(key, value); } } // Make the properties thread local from here. This to be done globally once. System.setProperties(new ThreadLocalProperties(System.getProperties())); // in each thread. System.setProperty("javax.net.ssl.keyStore", "my-key-store"); 

除非有任何混淆,否则System.setProperties()不仅会设置属性,而是替换集合及其实现。

 // From java.lang.System * The argument becomes the current set of system properties for use * by the {@link #getProperty(String)} method. public static void setProperties(Properties props) { SecurityManager sm = getSecurityManager(); if (sm != null) { sm.checkPropertiesAccess(); } if (props == null) { props = new Properties(); initProperties(props); } System.props = props; } 

通过使用此方法,系统属性的行为将更改为调用setProperty()和getProperty()的线程本地

我到这里寻找一个解决方案来设置每个线程的系统属性。 我使用了@Peter Lawrey上面的优秀示例,这正是我需要的一个例外 – 我的代码需要在servlet容器(Tomcat)中运行,因此我有义务成为一个好公民并且不会改变预期的行为setProperty()用于在同一JVM实例中运行的任何其他webapp。 为了解决这个问题,我将Peter的setProperty()方法重命名为setLocalProperty()

  public Object setThreadLocalProperty(String key, String value) { return localProperties.get().setProperty(key, value); } 

通过这一次更改,结果是对setProperty()的调用将全局更改属性 – 这将是JVM中其他线程的所需行为。 要仅改变本地线程的属性,则调用setThreadLocalProperty()

总而言之,如果您完全控制您的应用程序实例,那么Peter的代码应该对您有用。 但是,如果您的应用程序位于共享JVM中 – 或者如果您需要将系统属性“分层”为全局和线程本地,则上面的一个修改应该适合您。

有一些编程方法可以设置密钥库和信任库,请参阅JSSE参考指南 ,但为什么您认为您需要不同的密钥库和信任库呢? 信任库是您信任的每个CA的列表:在不同的上下文中真的不同:密钥库是您的身份:在不同的上下文中是否真的不同? 如果是这样,为什么?