Java堂  


给Spring Security中的j_spring_security_check等改名

Filed under: JavaPlateform — Jet @ 11:43 上午
原文出处: http://www.javatang.com/archives/2010/09/02/4325457.html
作者: Jet Mah from Java堂
声明: 可以非商业性任意转载, 转载时请务必以超链接形式标明文章原始出处、作者信息及此声明!

默认情况下,Spring Security(SS)的登录验证提交的Servlet默认名称为j_spring_security_check,但是很多情况下想将这个名称修改掉,后来终于在Spring的官方论坛上找到了一个哥们儿提出的类似的问题(见参考资料),原来只要修改<form-login>节点login-processing-url属性就可以了,其他的一些设置可以参考官方的文档:B.1.5 The <form-login> Element

对于SS的使用及配置文件的含义可以参考这篇文章:spring-security3 配置和使用,总结的非常到位了。

参考资料:
Rename j_spring_security_check to j_security_check

SimpleJdbcInsert使用executeAndReturnKeyHolder方法返回主键时需要注意的一个地方

Filed under: JavaPlateform — Jet @ 1:32 下午
Tags:
原文出处: http://www.javatang.com/archives/2010/08/09/3212438.html
作者: Jet Mah from Java堂
声明: 可以非商业性任意转载, 转载时请务必以超链接形式标明文章原始出处、作者信息及此声明!

Spring的SimpleJdbcInsert发挥了Simple风格,与SimpleJdbcTemplate同属于Simple体系。该类为向数据库中插入数据提供了一个非常快捷的方式,另外它还提供了一套用于返回插入数据的主键的方法:executeAndReturnKeyHolder、executeAndReturnKey。

查看API的时候可以看到executeAndReturnKey这个方法的返回类型是Number类型,当时我就再想如果主键的类型是String类型呢,比如UUID。后来看到还有一个executeAndReturnKeyHolder方法,返回的是一个KeyHolder对象,可以通过keyHolder#getKeys()获取主键的值,另外还有一个getKeyList()方法用于复合主键的情况,这里先撇开不说。

看完API之后那就可以动手了,代码如下:

  1. // jdbcInsert是SimpleJdbcInsert对象
  2. Map<String, Object> data = Maps.newHashMap();
  3. data.put("id", "t0001");
  4. data.put("name", "Tom");
  5. data.put("age", 24);
  6. KeyHolder keyHolder = jdbcInsert.withTableName("t_tablename")
  7.         .usingColumns("id", "name", "age")
  8.         .usingGeneratedKeyColumns("id")
  9.         .executeAndReturnKeyHolder(data);
  10. // 下面主要是对keyHoder进行分析
  11. if(keyHolder == null) {
  12.     return null;
  13. }
  14. Map<String, Object> keys = keyHolder.getKeys();
  15. if(keys == null || keys.size() == 0 || keys.values().size() == 0) {
  16.     return null;
  17. }
  18. Object key = keys.values().toArray()[0];
  19. if(key == null || !(key instanceof Serializable)) {
  20.     return null;
  21. }
  22. if(key instanceof Number) {
  23.     Long k = (Long)key;
  24.     return (idType == int.class || idType == Integer.class) ?
  25.             k.intValue() : k;
  26. } else if(key instanceof String) {
  27.     return (String)key;
  28. } else {
  29.     return (Serializable)key;
  30. } // end of if(key instanceof Number)

如果主键id的类型是int或long上面的代码没有任何问题,但是如果是自定义的UUID等String类型则问题出现了,提示下面的错误:

org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL []; SQL state [HY000]; error code [1364]; Field ‘id’ doesn’t have a default value; nested exception is java.sql.SQLException: Field ‘id’ doesn’t have a default value

有些奇怪了吧?明明id的值已经传入了,但是错误的提示应该是没有传入id的值。进入到Spring的源代码中,发现代码里面有一些debug信息,于是在log4j中将debug打开:

  1. log4j.logger.org.springframework.jdbc.core=debug

从打印出来的信息中看,Spring自动生成的Insert语句中竟然没有id字段!!!继续最终源代码,先在org.springframework.jdbc.core.simple.AbstractJdbcInsert类中找到protected void compileInternal()方法,在代码前加上一个debug信息:

  1. protected void compileInternal() {
  2.     logger.debug("getGeneratedKeyNames: " + getColumnNames());
  3.     tableMetaDataContext.processMetaData(getJdbcTemplate().getDataSource(), getColumnNames(), getGeneratedKeyNames());
  4.     ...
  5. }

这个时候打印的列表中有id字段,继续最终,最后终于在TableMetaDataContext#createInsertString(java.lang.String[])方法里面找到,关键的代码片段如下:

  1. for (String columnName : this.getTableColumns()) {
  2.             // 这里将SimpleJdbcInsert#usingGeneratedKeyColumns方法中所设置的字段去除了
  3.             if (!keys.contains(columnName.toUpperCase())) {
  4.                 columnCount++;
  5.                 if (columnCount > 1) {
  6.                     insertStatement.append(", ");
  7.                 }
  8.                 insertStatement.append(columnName);
  9.             }
  10.         }

看到这里,我也猛然恍然大悟了。既然在INSERT INTO语句中设置了UUID的值,那这里就不需要再使用KeyHolder进行返回了,直接获取就是了。这也是为什么KeyHolder中的getKey()方法的返回类型是Number的原因了,因为通常来说需要Spring返回的就是插入数据库中的自增类型的主键值。

common-configuration中CompositeConfiguration类的一个需要注意的地方

Filed under: JavaPlateform — Jet @ 4:05 下午
原文出处: http://www.javatang.com/archives/2010/07/29/0513435.html
作者: Jet Mah from Java堂
声明: 可以非商业性任意转载, 转载时请务必以超链接形式标明文章原始出处、作者信息及此声明!

Common-Configuration中,CompositeConfiguration类用来对多个配置文件进行组合处理,该类有一个getNumberOfConfigurations()方法,用来读取Configuration对象的个数,但是如果执行下面的代码:

  1. CompositeConfiguration config = new CompositeConfiguration();
  2. int number = config.getNumberOfConfigurations();
  3. System.out.println(number);

这个时候会发现number的值是1而不是0,虽然没有向其中添加任何Configuration对象。CompositeConfiguration构造方法的代码如下:

  1. public CompositeConfiguration()
  2.     {
  3.         clear();
  4.     }
  5.  
  6.     public void clear()
  7.     {
  8.         configList.clear();
  9.         // recreate the in memory configuration
  10.         inMemoryConfiguration = new BaseConfiguration();
  11.         ((BaseConfiguration) inMemoryConfiguration).setThrowExceptionOnMissing(isThrowExceptionOnMissing());
  12.         ((BaseConfiguration) inMemoryConfiguration).setListDelimiter(getListDelimiter());
  13.         ((BaseConfiguration) inMemoryConfiguration).setDelimiterParsingDisabled(isDelimiterParsingDisabled());
  14.         configList.add(inMemoryConfiguration);
  15.     }

可以看到默认构造方法中调用了clear()方法,而clear方法中自动添加了一个BaseConfiguration对象,该对象用于存放自身的一些配置信息。所以这个时候的数量是1而不是0,这一点容易让人迷惑。

参考资料:
Re: [Configuration] CompositeConfiguration.getNumberOfConfigurations( ) question

客户真正的需求原来是这样的

Filed under: JavaPlateform — Jet @ 9:21 上午
原文出处: http://www.javatang.com/archives/2010/07/07/2157401.html
作者: Jet Mah from Java堂
声明: 可以非商业性任意转载, 转载时请务必以超链接形式标明文章原始出处、作者信息及此声明!

m2eclipse插件使用中提示jar包找不到的解决方法

Filed under: JavaPlateform — Jet @ 4:33 下午
原文出处: http://www.javatang.com/archives/2010/01/31/3312389.html
作者: Jet Mah from Java堂
声明: 可以非商业性任意转载, 转载时请务必以超链接形式标明文章原始出处、作者信息及此声明!

在Eclipse中使用m2eclipse开发Maven项目的时候,如果是创建Module项目的时候经常会莫名的出现找不到子模块包的错误信息,但是pom.xml已经加入了改包的引用,并且使用mvn deploy命令等编译也没有任何错误,后来在Eclipse中的Marks View中发现一个项目的warning信息:

Classpath entry org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER will not be exported or published. Runtime ClassNotFoundExceptions may result.

后来Google了一下,解决这个warning的步骤如下:
1. 首先右键项目,然后选择“Properties”,在左边选择Java Build Path,然后在右边的“Order andExport”标签中选中最下面的“Maven Dependencies”,然后确定;

2. 选择“Marks”或“Problems”视图,然后选中那个warning信息,右键选择“Quick Fix”,然后直接选择“Finish”,这样就可以了。

如果还是出现错误的信息,直接在上面的视图中右键删除提示就可以了。

参考资料:
Why the “MAVEN2_CLASSPATH_CONTAINER will not be exported or published”

Maven2部署构件到Nexus时出现的Failed to transfer file错误

Filed under: Architecture,JavaPlateform — Jet @ 12:45 下午
Tags: ,
原文出处: http://www.javatang.com/archives/2010/01/23/4518375.html
作者: Jet Mah from Java堂
声明: 可以非商业性任意转载, 转载时请务必以超链接形式标明文章原始出处、作者信息及此声明!

具体怎样使用deploy命令部署构件到nexus服务器上可以参考经典的《Maven Definitive Guide》(Maven操作指南),书中的16.7节里面讲解的非常详细。假设我们在项目pom.xml文件中对maven服务器的设置信息如下:

  1. <distributionManagement>
  2.       <repository>
  3.           <id>nexus-releases</id>
  4.           <name>Local Nexus Repository</name>
  5.           <url>http://192.168.1.99:8081/content/repositories/releases</url>
  6.       </repository>
  7.       <snapshotRepository>
  8.           <id>nexus-snapshots</id>
  9.           <name>Local Nexus Repository</name>
  10.           <url>http://192.168.1.99:8081/content/repositories/snapshots</url>
  11.       </snapshotRepository>
  12.   </distributionManagement>

这里我要说的是在使用的过程中遇到的几个都是“Failed to transfer file”错误,错误信息如下格式:

Error deploying artifact: Failed to transfer file:… Return code is:4xx

也就是说前面错误的信息都是一样的,只是后面返回的HTTP状态数字不同。

1. Return code is: 405
这个问题害我查了两个多小时才发现错误的根源,简单的错误就是在Maven执行到上传文件到服务器的时候出现一个HTTP 405错误。开始的时候总以为是Maven本身的问题,所以在这个上面浪费了不少时间。后来仔细查了405错误的含义是“用来访问本页面的 HTTP 方法不被允许”,最后终于发现是因为前面repository的地址写错了,或者是端口写错,或者是地址中的某个单词拼错了,反正原因就是repository的地址写错了

2. Return code is: 401或者Return code is: 403
其实403错误就是“禁止访问”的含义,所以问题的根源肯定在授权上面。Maven在默认情况下会使用deployment帐号(默认密码deploy)登录的系统,但是关键的Nexus中Releases仓库默认的Deployment Policy是“Disable Redeploy”,所以无法部署的问题在这个地方,方法是将其修改为“Allow Redeploy”就可以了。

到这里还没有结束,因为如果直接按照上面的设置的话会有一个安全问题,那就是这样所有的开发人员都可以将构件部署到Nexus的releases仓库中了,时间长了会导致这个仓库中非常乱,这也应该是nexus为什么默认情况下将Release仓库的发布权限关闭的原因了。解决这个问题的整体思路就是在部署构件的时候需要使用用户名和密码登录,操作如下:
(1) 首先将Releases仓库默认的Deployment Policy修改为“Allow Redeploy”;
(2) 然后在右边的Security下面的Users中,修改deployment帐号的密码,方法是在帐号上右键,然后选择“Set Password”(PS:这个操作我找了好久,后来无意中右键才找到,呵呵~~);

(3) 这个时候如果直接执行 mvn deploy 命令的话就又会出现401错误,还有一步就是将密码设置到Maven settings.xml中。打开settings.xml文件(${user.home}/.m/settings.xml或%{m2_home}/conf/settings.xml),找到<servers>,然后修改信息如下:

  1. <server>
  2.       <id>nexus-releases</id>
  3.       <username>deployment</username>
  4.       <password>deploydv89</password>
  5.     </server>
  6.  
  7.     <server>
  8.       <id>nexus-snapshots</id>
  9.       <username>deployment</username>
  10.       <password>deploydv89</password>
  11.    </server>

这里需要特别说明一句的是里面的id必须和你在项目pom.xml文件中distributionManagement下面设置的仓库id一致!当然了,这个里面你也可以设置admin帐号,或者参照deployment的权限手动添加新的帐号等等都是可以的。

当然,问题到这里已经得到了比较完美的解放,但是如果有人还要较真的话会想到帐号的密码直接放到配置文件里面不是很安全。其实只要这里不建议放admin帐号,而deployment是无法登录的。如果非要更安全一些的话,也可以使用Maven 2.1.0之后所提供的密码加密功能,操作的步骤如下:
(1) 使用“mvn –encrypt-master-password xxx”或“mvn –emp xxx”创建一个主密钥,后面的xxx就是你所要设置的密钥的内容,这个密钥主要用于后面加密密码来用的;命令执行之后会产生一个类似{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+9EF1iFQyJQ=}形式的字符串。
(2) 在${user.home}/.m/目录下创建一个名为settings-security.xml文件,我们将刚刚产生的主密钥放到这个文件中,文件的内容如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <settingsSecurity>
  3.     <master>{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+9EF1iFQyJQ=}</master>
  4. </settingsSecurity>

注意,这个settings-security.xml文件一定要放在${user.home}/.m/目录下面,而不能放在${m2_home}/conf目录下!
(3) 使用“mvn –encrypt-password xxx”或“mvn –ep xxx”命令对帐号的密码进行加密,后面的xxx就是帐号的密码,加密之后依然会产生一个“{xxx}”形式的字符串,将这个字符串替换上面settings.xml文件中的server下面的password节点内容即可。
还有一种更安全的方式,就是将主密钥放到U盘里面,具体的操作可以看下面的参考资料。

3. Return code is: 400
400错误的含义是“错误的请求”,在这里的原因是往往是没有部署到nexus的仓库中。nexus的repository分三种类型:Hosted、Proxy和Virtual,另外还有一个repository group(仓库组)用于对多个仓库进行组合。部署的时候只能部署到Hosted类型的仓库中,如果是其他类型就会出现这个400错误。

还有一种情况也会出现400错误,就是默认情况下部署构件到Releases仓库中有时也会出现400错误,这个原因就像上面提到的那样,Nexus中Releases仓库默认的Deployment Policy是“Disable Redeploy”,所以无论你在settings.xml文件中将server的username设置为deployment还是使用admin都是无法部署的,就会出现这个400错误。这个问题也困扰了我好长时间,而且我还看到网上有人说admin没有部署构件的权限,这个是不对的。修改的方法可以参考上面第2条的做法。

参考资料:
maven 中 部署构件至Nexus(mvn deploy)
Maven2中需要注意的问题
maven deploy到nexus私服出错问题
Maven Tips and Tricks: Encrypting Passwords
Maven – Password Encryption

Subversion和Apache的安装使用指南

Filed under: JavaPlateform,Web&Server — Jet @ 5:21 上午
原文出处: http://www.javatang.com/archives/2009/12/31/2139330.html
作者: Jet Mah from Java堂
声明: 可以非商业性任意转载, 转载时请务必以超链接形式标明文章原始出处、作者信息及此声明!

虽然Subversion(SVN)直接可以注册为服务程序,但是最方便的还是使用SVN+Apache的方式,因为可以无防火墙限制、方便直接使用浏览器对代码进行浏览等等。下面我就将自己在Windows下安装Subversion(SVN)和Apache的方法记录一下:

1. 从Apache网站上下载Apache的安装包进行安装,这个过程比较简单。需要注意Apache的版本,本文采用2.2,当然也可以使用2.0版本。假定Apache的安装目录为D:\apache2。

2. 在http://subversion.tigris.org/官方下载Subversion的Windows下面与Apache的配合版本,这里需要注意Apache的版本,2.0和2.2的是不一样的,不要下载错了。

然后将下载下来的zip包解压缩到一个目录,比如D:\svn-win32-1.6.6。

3. 将svn安装目录的bin目录下面的mod_authz_svn.so和mod_dav_svn.so两个文件拷贝到Apache安装目录的modules目录下面,然后修改Apache的配置文件httpd.conf,将下面两行的注释去掉:

LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_module modules/mod_dav.so

同时在下面增加两行:

LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

4. 接下来就是对SVN进行配置了,配置文件(包含每条的含义)如下:

# 表示访问SVN的地址,形式为http:///svn
<Location /svn>
# 告诉Apache哪个模块负责服务像那样的URL--在这里就是Subversion模块
DAV svn
# 在Subversion 1.3及更高版本中,这个指示器使得Subversion列出由SVNParentPath指定的目录下所有的版本库
SVNListParentPath on
# 下面制定SVN仓库的位置,有两种选择:
# (1) 单库:一个Apache下面只有一个SVN仓库,这样的话就使用SVNPath来指定唯一的仓库位置,访问仓库的方式是http:///svn
# (2) 多库:一个Apache下面可以有多个SVN仓库,这样的话就使用SVNParentPath来指定所有仓库所在的主目录,访问仓库的方式是http:///svn/仓库1、http:///svn/仓库2等等
SVNPath “D:\Data\SVNData\repository”
#SVNParentPath “D:\Data\SVNData\repository”

# 当一个验证对话框弹出时,告诉用户这个验证是用来做什么的
AuthName “Subversion repositories”
# 启用基本的验证,比如用户名/密码对,通常来做这样做就已经足够了。
AuthType Basic
# 指定密码文件的位置,密码文件中存放了用来验证用户的用户名和密码信息。这个文件的生成方式在后续步骤中会介绍
AuthUserFile “D:\Data\SVNData\config\passwd”
# 对版本库和人员进行权限分配,后面会进行详细的设置和介绍。
AuthzSVNAccessFile “D:\Data\SVNData\config\svnaccessfile”

# 限定用户只有输入正确的用户名及密码后才能访问这个路径
Require valid-user
# 如果想匿名读取的话使用下面的方式
#<LimitExcept GET PROPFIND OPTIONS REPORT>
#Require valid-user
#</LimitExcept>
</Location>

5. 接下来使用Apache中的htpasswd.exe命令来生成密码文件,也就是上面AuthUserFile 设置项所指向的文件,切换到Apache安装目录的bin目录下,指向下面的命令:

# 后面的参数c表示新建文件,在第一次执行的时候使用
htpasswd -c D:\Data\SVNData\config\passwd <username>
# 如果是追加新用户或修改原有用户密码,命令后面不加参数c
htpasswd D:\Data\SVNData\config\passwd <username>

每次执行命令之后会提示输入两遍密码

6. 这个时候如果重启Apache的话会出现一个错误提示,这个是因为svn所使用的一些dll文件apache还无法获取,解决的方法可以将svn安装目录的bin目录下面的dll文件拷贝到系统的system32目录下面,但最好的方式是将bin目录加入到path环境变量中。

7. 这个时候如果访问http:///svn的话,应该会出现一个登录框,输入用户名/密码之后就可以看到SVN仓库的内容了。不过常见下面的几个错误:
(1) 出现“403 Forbidden”错误
出现这个错误的原因有很多种,比如Apache2.2相对于之前的版本来说增强了安全性,默认情况下目录是禁止访问的,将“<Directory />”修改如下:

<Directory />
Options FollowSymLinks
AllowOverride None
Order deny,allow
Allow from all
</Directory>

如果这样还不行的话那就是“多库还是单库”的问题了。上面讲过,在对SVN进行配置的时候,使用SVNParentPath设置所有库的根目录,在根目录下面存放多个SVN的库,那这样的话直接访问父目录是没有权限的,只能通过http:///svn/project1来访问对应的项目仓库;如果使用SVNPath设置为单库的话则不会出现这个错误了。

(2) 出现“<m:human-readable errcode=”720003″>Could not open the requested SVN filesystem</m:human-readable>”错误
出现这个错误是告诉你你所指定的SVN仓库的位置并不是一个合法的SVN仓库,解决的方法是首先创建一个空目录,然后使用“svnadmin create”命令来创建SVN库:

# 首先进入 D:\Data\SVNData\repository 目录下
md project1
svnadmin create D:\Data\SVNData\repository\project1

8. 最后安装SVN客户端就可以访问啦,Eclipse集成的客户端推荐使用Subclipse,Visual Studio集成的客户端推荐使用ankhsvn,系统集成的客户端推荐使用TortoiseSVN

参考资料:
[翻译] windows安装基于Apache的SVN服务器(包括SSL配置)
基于svnserve的服务器,权限文件authz配置的常见问题及解答
Forbidden access or bad repository ?
Subversion for Windows 安裝指南

在Eclipse WTP中加入Resin server adapter

Filed under: JavaPlateform — Jet @ 6:01 上午
原文出处: http://www.javatang.com/archives/2009/12/30/0134324.html
作者: Jet Mah from Java堂
声明: 可以非商业性任意转载, 转载时请务必以超链接形式标明文章原始出处、作者信息及此声明!

目前Eclipse的WTP用来开发JavaEE的功能越来越强大了,再配合上Maven和Ant,完全可以将MyEclipse丢到垃圾桶了。但是在使用WTP进行Server配置的时候发现竟然不支持Resin,后来Google了一下,找到两个解决的方法:
1. Amateras 这个是一个日本人写的Eclipse插件,可以绑定Resin到WTP中,不过他支持的Eclipse和Resin的版本都比较低,而且好久都没有更新了,不推荐使用。

2. The Resin Eclipse plugin 这个是在Resin的官方WIKI上发现的一个Eclipse插件,比较稳定也比较活跃,是Resin官方推荐使用的插件,Eclipse Update地址是:http://caucho.com/eclipse,安装之后就会在Server Adapter里面出现Resin Server了。

参考资料:
IDE-CauchoWiki
WTP扩展(1):增加Resin Server Runtime Environments

Windows下手动安装JRE和Tomcat出现的错误

Filed under: JavaPlateform — Jet @ 5:39 上午
Tags:
原文出处: http://www.javatang.com/archives/2009/12/30/3926321.html
作者: Jet Mah from Java堂
声明: 可以非商业性任意转载, 转载时请务必以超链接形式标明文章原始出处、作者信息及此声明!

我通常不喜欢在系统中使用安装程序来安装JDK,而是直接做一个拷贝,然后指定JAVA_HOME和CLASSPATH环境变量。另外Tomcat的安装我也是喜欢下载zip包的形式,然后解压缩到一个目录下面,启动的时候直接运行bin/startup.bat就可以了。

可是使用bin/service.bat 将Tomcat安装成Windows Service(Windows服务)程序的时候会出现“[Tomcat]Failed creating java ….\jvm.dll”的提示,后来Google了一下,原来是JRE的bin目录下有一个msvcr71.dll文件在启动的时候需要依赖,所以可以将这个文件拷贝到%SystemRoot%\system32下面,也可以拷贝到Tomcat的bin目录下面,当然你可以将%JRE_HOME%\bin加入到path环境变量中,总之要让系统或Tomcat找到这个dll文件。这里比较推荐的方式是使用最后一种,毕竟有可能不仅仅是Tomcat会使用到这个dll文件,也不一定只会用到这一个dll文件。 :)

参考资料:[Tomcat]Failed creating java D:\jre6\bin\client\jvm.dll的解决

使用Jacob时出现的另一个UnsatisfiedLinkError错误:jacob.dll already loaded in another classloader

Filed under: JavaPlateform — Jet @ 12:00 上午
Tags:
原文出处: http://www.javatang.com/archives/2009/06/01/0036305.html
作者: Jet Mah from Java堂
声明: 可以非商业性任意转载, 转载时请务必以超链接形式标明文章原始出处、作者信息及此声明!

之前文章中已经说过Jacob在windows2003环境下使用的时候会出现UnsatisfiedLinkError错误,解决的方法是需要下载Redistributable Package安装即可。

但如果在JavaEE项目中使用Jacob的时候还会出现另外一个UnsatisfiedLinkError错误:jacob.dll already loaded in another classloader,错误往往会出现在Web容器重启之后。后来查到下面的相关资料:

Java API表明:JVM只允许一个默认的ClassLoader来load native library,同时并不提供专门的API来unload一个loaded native library,因此无法在我们的重启Web应用的代码中来手工清除已经load的jacob。

原因找到了,这是因为在重启Web容器的时候并不会自动结束上一次对dll的加载,解决问题的关键在于重启Web程序之后要确保不要再次加载jacob.jar包,有一个方法就是不要将jacob.jar包放在web程序中,而是将jacob.jar包放在Web容积自身的lib目录下面就可以了。

参考资料:
jacob.dll already loaded in another classloader

下一页 »