使用IntelliJ IDEA搭建基于maven管理的SSH(Struts2,Spring,Hibernate)框架小结

今天再次尝试使用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包,只有当

  1. 没有将 jar.forceCreation 参数设为true
  2. 并且支持强制设置
  3. 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包不是最新的:

  4. jar包不存在(其实就是mvn clean的效果)
  5. 传入比较的文件资源不存在
  6. Resource with unknown modification date found,资源的修改时间未知
  7. Resource with newer modification date found,jar包的最后修改时间比资源的最后修改时间早

总结

  1. 理论上来讲不做mvn clean 得到的jar包应该是最新的,除非其他方式修改jar包中的内容而不修改源代码。
  2. 平时可以用mvn install,而不进行chean节省时间(如果你觉得节省时间多的话),但最保险还是用 mvn clean install 生成最新的jar包或其他包
  3. 不想用mvn clean又想保证jar包最新,建议添加 -Djar.forceCreation 参数。

本文标题:使用IntelliJ IDEA搭建基于maven管理的SSH(Struts2,Spring,Hibernate)框架小结

文章作者:zhaoqing

发布时间:2018年04月23日 - 13:04

最后更新:2018年05月03日 - 19:05

原始链接:https://zqhf.github.io/2018/04/23/article6/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!