转到正文

宁静海

发现,理解,提升

存档

分类: Java开发笔记
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
long curPos = startPos;
int bytesRead = -1;
byte[] buffer = new byte[BUFFER_SIZE];
while ((bytesRead = bis.read(buffer)) != -1) {
    fos.write(buffer, 0, bytesRead);
}

 

起因:

公司因为设置了外网的proxy,eclipse必须设置Proxy来访问一些plug-in的update site或者marketplace,但总是不稳定,常常刚开始能访问,但是突然又不能,也不是被端口禁用或者别的原因,因为报错的那些站点浏览器都能正常访问。 今天花了整整半天时间来想要彻底解决这个问题。

结果:

这是一个长达4年的Bug,从未被修复。但有work around的方法能解决。

Reference:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=364992#c5

https://bugs.eclipse.org/bugs/show_bug.cgi?id=281472

解决方法:

ht

-Djavax.net.ssl.trustStore 
-Dhttps.protocols=SSLv3 
-Djsse.enableSNIExtension=false //This is for JDK 7 SNI support, but need to be disabled.
-Djavax.net.debug=ssl
-Dweblogic.security.SSL.protocolVersion=SSL3
-Dweblogic.security.SSL.ignoreHostnameVerification=true

 

Reference

http://stackoverflow.com/questions/5507878/ssl-connection-reset

http://stackoverflow.com/questions/10188568/sslexception-during-handshake-while-resuming-cached-session

http://stackoverflow.com/questions/7615645/ssl-handshake-alert-unrecognized-name-error-since-upgrade-to-java-1-7-0

 

一句话概括,JDK升级到1.7后对于SSL的支持各种坑。

 

static static <K, V extends Comparable<? super V>> SortedSet<Map.Entry<K, V>> entriesSortedByValues(Map<K, V> map) {
    SortedSet<Map.Entry<K, V>> sortedEntries = new TreeSet<Map.Entry<K, V>>(new Comparator<Map.Entry<K, V>>() {
        @Override
        public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) {
            return e1.getValue().compareTo(e2.getValue());
        }
    });
    sortedEntries.addAll(map.entrySet());
    return sortedEntries;
}

 

Java获得环境变量有两个方法。

 

System.getProperties();
System.getenv();

 

根据JDK 7中的描述

System.getenv()
Returns an unmodifiable string map view of the current system environment.

 

public static Map<String,String> getenv()

Returns an unmodifiable string map view of the current system environment. The environment is a system-dependent mapping from names to values which is passed from parent to child processes.

If the system does not support environment variables, an empty map is returned.

The returned map will never contain null keys or values. Attempting to query the presence of a null key or value will throw a NullPointerException. Attempting to query the presence of a key or value which is not of type String will throw a ClassCastException.

The returned map and its collection views may not obey the general contract of the Object.equals(java.lang.Object) and Object.hashCode() methods.

The returned map is typically case-sensitive on all platforms.

If a security manager exists, its checkPermission method is called with a RuntimePermission("getenv.*") permission. This may result in a SecurityException being thrown.

When passing information to a Java subprocess, system properties are generally preferred over environment variables.

Returns:
    the environment as a map of variable names to values
Throws:
    SecurityException - if a security manager exists and its checkPermission method doesn't allow access to the process environment
Since:
    1.5
See Also:
    getenv(String), ProcessBuilder.environment()

 

getProperties()
Determines the current system properties.

 

public static Properties getProperties()

Determines the current system properties.

First, if there is a security manager, its checkPropertiesAccess method is called with no arguments. This may result in a security exception.

The current set of system properties for use by the getProperty(String) method is returned as a Properties object. If there is no current set of system properties, a set of system properties is first created and initialized. This set of system properties always includes values for the following keys:
Key 	Description of Associated Value
java.version 	Java Runtime Environment version
java.vendor 	Java Runtime Environment vendor
java.vendor.url 	Java vendor URL
java.home 	Java installation directory
java.vm.specification.version 	Java Virtual Machine specification version
java.vm.specification.vendor 	Java Virtual Machine specification vendor
java.vm.specification.name 	Java Virtual Machine specification name
java.vm.version 	Java Virtual Machine implementation version
java.vm.vendor 	Java Virtual Machine implementation vendor
java.vm.name 	Java Virtual Machine implementation name
java.specification.version 	Java Runtime Environment specification version
java.specification.vendor 	Java Runtime Environment specification vendor
java.specification.name 	Java Runtime Environment specification name
java.class.version 	Java class format version number
java.class.path 	Java class path
java.library.path 	List of paths to search when loading libraries
java.io.tmpdir 	Default temp file path
java.compiler 	Name of JIT compiler to use
java.ext.dirs 	Path of extension directory or directories
os.name 	Operating system name
os.arch 	Operating system architecture
os.version 	Operating system version
file.separator 	File separator ("/" on UNIX)
path.separator 	Path separator (":" on UNIX)
line.separator 	Line separator ("\n" on UNIX)
user.name 	User's account name
user.home 	User's home directory
user.dir 	User's current working directory

Multiple paths in a system property value are separated by the path separator character of the platform.

Note that even if the security manager does not permit the getProperties operation, it may choose to permit the getProperty(String) operation.

Returns:
    the system properties
Throws:
    SecurityException - if a security manager exists and its checkPropertiesAccess method doesn't allow access to the system properties.
See Also:
    setProperties(java.util.Properties), SecurityException, SecurityManager.checkPropertiesAccess(), Properties

 

网上很多使用的是getProperties。说获得系统变量,但是其实不正确。getProperties中所谓的"system properties"其实是指"java system",而非"operation system",概念完全不同,使用getProperties获得的其实是虚拟机的变量形如: -Djavaxxxx。

 

getenv方法才是真正的获得系统环境变量,比如Path之类。其方法命名方式有违Sun命名规范其实。

还有就是在JDK 1.4中该方法其实是Deprecated的,1.3也是。我认为Sun的当初设计思路是想让其屏蔽,或者可控Java对系统变量的访问能力。以下为JavaDoc 1.3, 1.4中对getenv方法的描述

 

 getenv

public static String getenv(String name)

    Deprecated. The preferred way to extract system-dependent information is the system properties of the java.lang.System.getProperty methods and the corresponding getTypeName methods of the Boolean, Integer, and Long primitive types. For example:

             String classPath = System.getProperty("java.class.path",".");
         

             if (Boolean.getBoolean("myapp.exper.mode"))
                 enableExpertCommands();
         

    Gets an environment variable. An environment variable is a system-dependent external variable that has a string value.

    Parameters:
        name - of the environment variable
    Returns:
        the value of the variable, or null if the variable is not defined.
    See Also:
        Boolean.getBoolean(java.lang.String), Integer.getInteger(java.lang.String), Integer.getInteger(java.lang.String, int), Integer.getInteger(java.lang.String, java.lang.Integer), Long.getLong(java.lang.String), Long.getLong(java.lang.String, long), Long.getLong(java.lang.String, java.lang.Long), getProperties(), getProperty(java.lang.String), getProperty(java.lang.String, java.lang.String)

 

意思就是说:希望使用Java的系统变量替代操作系统的变量获取,如果你想访问某个系统的环境变量(operation system properti

在项目中碰到个问题,想要建立一个反向的键值对关系,什么叫反向的键值对关系类?先看如下的需求。

旧项目中有很多很多表,每个表的机构类似,但是字段的类型不同,有可能是varchar2,有可能是Number,也有可能是Char或者Int,但是我们需要在一个Config表中来描述这些表,有个data_type的字段,在系统中只定义了Number,String,Date等广泛意义的类型定义,从字典表中可查询到字段类型,但是哪几种字段类型算是String,哪几种算是Number呢?这就构成一种多对1的关系。问题也就产生了,传统意义上的Map都是一个键对应多个值,比如:

 

Map<String, List<String>> map

在我们这个Map中,按照我们的需求,就是根据List中的value获得Key,当然,我们假设List中的值全部都是唯一的,更精确的描述应该是一个Set<String>,当然这只是为了方便,使用的List。

 

 

搜索了一圈google,本以为有现成的反向map实现,但似乎没有。看来只能自己实现下了。代码如下。

 

 

package com.catpaw.utils.collection;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MapUtil<K, V> {

public K getKeyFromValue(Map<K, V> sourceMap, String value) {
if (value == null) {
return null;
}
Set<Entry<K, V>> mapEntries = sourceMap.entrySet();
for (Entry<K, V> mapEntry : mapEntries) {
if (value.equals(mapEntry.getValue())) {
return mapEntry.getKey();
}
}
return null;
}

public K getKeyFromListValue(Map<K, List<V>> sourceMap, String value) {
if (value == null) {
return null;
}
Set<Entry<K, List<V>>> mapEntries = sourceMap.entrySet();
for (Entry<K, List<V>> mapEntry : mapEntries) {
List<V> values = mapEntry.getValue();
for (V val : values) {

Spring是常用的开发框架,曾经以为只有2种主要的IOC容器初始化方式

1、显式的实例化ApplicationContext

2、通过web.xml配置

 

以下内容参考自Spring-Reference PDF

显式实例化:

ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
//MessengerService.class用来确定2个XML文件的路径
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}, MessengerService.class);
ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml");
ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");

 

web.xml配置

原理基本就是Servlet,摘自Reference PDF

To support the scoping of beans at the request, session, and global session levels
(web-scoped beans), some minor initial configuration is required before you define your beans. (This
initial setup is not required for the standard scopes, singleton and prototype.)
How you accomplish this initial setup depends on your particular Servlet environment..

对于Servlet2.4以上容器且使用了第三方的工具来控制跳转,比如Struts,则必须添加listener

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

 

这个添加是为了scope考量,摘自PDF

If you access scoped beans within Spring Web MVC, in effect, within a request that is processed by the
Spring DispatcherServlet, or DispatcherPortlet, then no special setup is necessary:
DispatcherServlet and DispatcherPortlet already expose all relevant state.

可以看到如果使用MVC,或者纯粹的DispatcherServlet应用等,可无须配置该listener。
If you use a Servlet 2.4+ web container, with requests processed outside of Spring’s DispatcherServlet
(for example, when using JSF or Struts), you need to add the following
javax.servlet.ServletRequestListener to the declarations in your web applications

如果request的处理过程在Dis