使用JNI的struts2项目在tomcat遇到的问题

来源:互联网 发布:edm邮件制作软件 编辑:程序博客网 时间:2024/05/16 06:32

写了一个struts2项目,里边用到了JNI,在MyEclipse下顺利地运行了,可是deploy到tomcat之后遇到了N多错误,让我头疼不已,特此记录一下遇到的错误!


1.deploy出错

不存在的jar包的引入,使得deploy出错

在deploy的时候会提示这个错误:

could not be redeployed because it could not be completely removed inthe undeployment phase. The most common cause of this problem is attempting to redeploy while the server is running,which has locked one or more files.

查看工程状态,有个红色叉叉,可是代码这些却没有错误,最后才在Libraries里边发现原来是有不存在的jar包导入了进去。


把junit.jar从Libraries里边去除,之后将tomcat下的Struts2都删掉,之后再重新将工程部署到tomcat服务器就好了。

因为这个错误,衍生出了新的错误,

2.no Action Mapped

因为部署不成功,使得我在MyEclipse下做的修改在tomcat下是无效的

比如说我新加了个action,在struts.xml中的配置都没错啊,可是就是不断提示我

There is no Action mapped for namespace / and action name。Form action defaulting to 'action' attribute's literal value.

当时被这个错误弄得要气死我了抓狂。看来每个警告都不可小视呀!




3.文件从前台上传到后台

在前台用<input type="file" name="xxx"/>上传文件

那么我在action中为文件变量命名为xxx,则一定要有对应的xxxFileName和xxxContentType!

如下所示,get和set方法也是不能少的:

private File image;
private String imageFileName;
private String imageContentType;

我开始没重视这一点,改成了imageName,然后文件就上传不成功了。

4.tomcat启动问题

严重: Error starting endpoint
java.lang.IllegalStateException: Unable to initialise endpoint. A previous call to init() failed. See previous log messages for details.

因为我下了个phpstudy,它会开机启动它的Apache,我在MyEclipse则是配置了另一个tomcat,所以启动tomcat的时候就出问题啦。

所以先把phpstudy里的Apache服务器关掉,然后再启动tomcat就好了。


5.JNI中的dll加载问题

这个问题在MyEclipse下没遇到过,

将项目部署在tomcat下之后问题便出现了。
网上很多解决方案是这么说的:

Tomcat的Release Notes 里有这么一段话:
=======================
JNI Based Applications:
=======================
Applications that require native libraries must ensure that the libraries have
been loaded prior to use.  Typically, this is done with a call like:

  static {
    System.loadLibrary("path-to-library-file");
  }

in some class.  However, the application must also ensure that the library is
not loaded more than once.  If the above code were placed in a class inside
the web application (i.e. under /WEB-INF/classes or /WEB-INF/lib), and the
application were reloaded, the loadLibrary() call would be attempted a second
time.
To avoid this problem, place classes that load native libraries outside of the
web application, and ensure that the loadLibrary() call is executed only once
during the lifetime of a particular JVM.
简单地说就是JNI库的加载在启动Tomcat的JVM中只能进行一次,如果两次执行System.loadLibrary("path-to-library-file");将会导致错误(Error,不是Exception):
java.lang.UnsatisfiedLinkError:

Native Library xxx.dll already loaded in another classloader。
只有重新启动整个tomcat才能恢复正常,十分麻烦。
找了好久,终于在一个大侠的文章中找到了解决方法:
1、加载JNI库的包放在Tomcat的common/lib目录下,而不要放在各context的lib目录下;
2、每次加载JNI库之前检查是否已经加载过。
由于加载语句不是我能控制的,所以第二种方法不能实现,于是我就通过第一种方法把这个问题解决了。

上面是查到的解决方案,不过尴尬where is the common/lib啊????

最后在CSDN论坛找到了一个解决办法,不过说得还是有些不清楚,下面把我的尝试过程记录下来。

首先我们来看看在MyEclipse中和在tomcat中项目的目录情况。

左边的是在MyEclipse中,右边则是在tomcat下,可以看到在MyEclipse中项目的WebRoot目录 == tomcat下的项目目录。


那么问题就来啦。在MyEclipse下我是把JNI需要的dll放在工程目录里边的,也就是不在WebRoot目录下,这样一来,在tomcat里边就没有与之对应的目录来放dll啦。

关于dll在MyEclipse下放置在哪个目录下可以查看
http://blog.csdn.net/jianjian1992/article/details/46724043#t9

那该肿么办啊!!

1.把使用JNI的类生成jar包

比如说我的MyNative.java代码如下,我把这个java文件Export成一个jar包,这里我选的是JAR File。

import java.util.ArrayList;    public class MyNative  {      static      {          System.loadLibrary( "FindCircles" );      }      public native static ArrayList<Circle> findCircles(String imgUrl);  }  

2.删除这个类的文件

也就是在工程里边把这个类的.java和.class都删掉就好了,我是在MyEclipse工程里边删掉的。


3.把jar包加入到tomcat中

将jar包以及所有相关的dll都加入到tomcat/bin目录中。

jar包里边有MyNative类的信息,dll则是C++中代码生成的,还有3个opencv的dll是cFindCircles.dll的依赖项。




4.把工程deploy到tomcat中

这里要注意一点,在tomcat中的Struts2目录中,(Struts2指部署到tomcat的工程名)上面提到的几个dll都不要加进去啊!
我之前因为在MyEclipse下的工程里边放置了dll,然后每次redeploy都会将这些dll放到Struts2目录里边,导致出现错误,所以
在如下tomcat中工程的目录和其子目录里边,任何dll都别加进去啊!如果不小心deploy了,记得及时删掉!








 com.opensymphony.xwork2.util.logging.jdk.JdkLogger error
严重: Exception occurred during processing request: null
java.lang.NullPointerException


//MyNative myNative = new MyNative();
            //circles = myNative.findCircles(imageUrl, x, y, x+w, y+h);
            circles = new ArrayList<String>();
            circles.add("1:2:4");
            circles.add("2:4:5");
            circles.add("11:21:4");
    System.out.println(circles.size());
    for (int i = 0; i < circles.size(); i++){
    System.out.println(i +" : " + circles.get(i).toString());
    }




0 0