今天再次尝试使用IntelliJ IDEA搭建基于maven管理的SSH(Struts2,Spring,Hibernate)框架时,一直遇到一个问题,困扰了许久,问题如下:
框架整合项目见:https://github.com/zqhf/SSHfram
显示了路径映射有问题,去百度也看到了很多解决方案,大体有这么几条:
1、首先检查Action名称是否写错。
2、检查配置文件是否写错,struts有一个默认的配置文件,叫struts-default.xml,这个配置文件名字是不能错的,这个是规定。但是光这一个配置文件名字不错,可能还会有问题。
一般大一点的项目,配置文件有好多,可能会一个模块一个配置文件,但是一个项目中只有一个struts-default.xml,所以基本上都是把struts的配置写在各个模块的配置文件中,然后把在struts-default.xml中引用这些配置文件。
所以说,其他配置文件一定要在struts-default.xml中引用,而且名字不能出错。
3、配置文件中的包名不能重复,尤其是采用多个struts配置文件时,各个文件之间的package的name一定不能重复。
4、检查struts-default.xml配置文件所在路径,一般都在src能找到的路径下,而且要确认编译后是否在classes目录下,如下图:
5、可以去掉namespace试试,namespace是action的目录,如果action指定目录的话,就在指定namespace下找,没有的话,就在默认的路径下找。
6、检查struts配置文件中有没有配置
可是很奇怪的是,按以上几条都没有解决报错的问题,后来重新检查一下框架搭建的过程,发现tomcat的配置如果配置不正确,也可能出现这个报错,下图是我的tomcat配置:
如果其中红色部分配置错了,也会导致这样的错误,归纳为第七种原因,解决办法就是配置正确。
但是,由于项目是基于maven管理的,当已经使用maven的打包命令(maven clean package)将项目部署到target目录下的classes目录下时,如果项目丝毫没有修改,再一次使用maven的命令,如:maven clean package或者maven clean install
命令,然后运行项目,会发现struts.xml配置文件没有进入classes目录,此时也会发现上述问题,这就奇怪了,执行两次maven的命令,原有的配置文件反而不见了。接着修改一下配置文件
中的内容,哪怕是增加一个空格,再运行命令mvn clean package,然后运行项目,结果配置文件又回来了。。。。这是什么原因呢?仔细观察,会发现,执行maven的打包命令,struts.xml这个文件并没有进入target的classes目录
而是在运行tomcat时,才会将配置文件加载到classes目录。因此在pom.xml文件中build需要如此配置,才能一块儿打包进入classes目录:1
注:该配置还能解决有时候配置文件找不到导致bean也找不到等问题
下面是maven打包时候的一些细节。
看看maven的源码有这么一段:
protected boolean checkForced()throws ArchiverException
{
if ( !isForced() && isSupportingForced() && isUptodate() )
{
getLogger().debug( “Archive “ + getDestFile() + “ is uptodate.” );
return false;
}
return true;
}
这个方法是校验是否强制重新创建jar包,只有当
- 没有将 jar.forceCreation 参数设为true
- 并且支持强制设置
up to date,意思就是被认为是最新的内容,没有改动
这个时候maven不进行新包的生成直接返回。
protected void execute()throws ArchiverException, IOException
{if ( ! checkForced() ) { return; } if ( doubleFilePass ) { skipWriting = true; createArchiveMain(); skipWriting = false; createArchiveMain(); } else { createArchiveMain(); } finalizeZipOutputStream( zOut );
}
所以除了那个强制的参数以外,就是看什么时候 isUptodate 为true,查看关键代码:
protected boolean isUptodate()throws ArchiverException
{final File zipFile = getDestFile(); final long destTimestamp = zipFile.lastModified(); if ( destTimestamp == 0 ) { getLogger().debug( "isUp2date: false (Destination " + zipFile.getPath() + " not found.)" ); return false; // File doesn't yet exist } final Iterator it = resources.iterator(); if ( !it.hasNext() ) { getLogger().debug( "isUp2date: false (No input files.)" ); return false; // No timestamp to compare } while ( it.hasNext() ) { final Object o = it.next(); final long l; if ( o instanceof ArchiveEntry ) { l = ( (ArchiveEntry) o ).getResource() .getLastModified(); } else if ( o instanceof PlexusIoResourceCollection ) { try { l = ( (PlexusIoResourceCollection) o ).getLastModified(); } catch ( final IOException e ) { throw new ArchiverException( e.getMessage(), e ); } } else { throw new IllegalStateException( "Invalid object type: " + o.getClass() .getName() ); } if ( l == PlexusIoResource.UNKNOWN_MODIFICATION_DATE ) { // Don't know what to do. Safe thing is to assume not up2date. getLogger().debug( "isUp2date: false (Resource with unknown modification date found.)" ); return false; } if ( l > destTimestamp ) { getLogger().debug( "isUp2date: false (Resource with newer modification date found.)" ); return false; } } getLogger().debug( "isUp2date: true" ); return true;
}
代码中提到有这么几个情况,会认为jar包不是最新的:- jar包不存在(其实就是mvn clean的效果)
- 传入比较的文件资源不存在
- Resource with unknown modification date found,资源的修改时间未知
- Resource with newer modification date found,jar包的最后修改时间比资源的最后修改时间早
总结
- 理论上来讲不做mvn clean 得到的jar包应该是最新的,除非其他方式修改jar包中的内容而不修改源代码。
- 平时可以用mvn install,而不进行chean节省时间(如果你觉得节省时间多的话),但最保险还是用 mvn clean install 生成最新的jar包或其他包
- 不想用mvn clean又想保证jar包最新,建议添加 -Djar.forceCreation 参数。