坦白来讲,如果我看到有人还在热心于ssm是如何集成的,我觉得他一定是年纪不小了。那为啥我还要干这件事情呢?主要是想实践下maven的archetype如何制造。本以为应该很简单,但是国内的博客不给力,写的不清晰而且maven的文档实在伤人。所以折腾出来了就想出来说两句,让后来者能够省点心力。

成品请见github,欢迎star,水平有限,见笑。

maven的archetype是啥呢?就是按照一个模板来生成项目,啪一下就能够弄出一个目录结构和配置文件。阅读各种文章过程中,发觉archetype是基于velocity实现的。也就是说,使用archetype来创建项目的过程实际上就是一个复制文件夹,复制目录,替换文件中的变量(就是velocity的变量${var}形式的)。这样想来,archetype并没有什么神奇的。一项技术你感觉神奇的时候,最容易用上它,当你再感觉不神奇了,就是开始明白它了。

来说说具体做法,我没有用mvn archetype:create-from-project主要是尝试了几遍都失败了,而且不知道怎么下手。索性手动来了。

大致步骤:
1 mvn archetype:generate -DarchetypeCatalog=internal 选择 maven-archetype-archetype 创建一个archetype项目
2 将需要生成的文件和代码放置到src\main\resources\archetype-resources下 3 在src\main\resources\META-INF\maven下增加一个archetype-metadata.xml删除archetype.xml。根据你的实际情况修改archetype-metadata.xml
4 修改各种变量,以适应生成的需要
5 其他配置
6 测试

下面来详解

###生成archetype项目
见以下内容,GAV请自定义

mvn archetype:generate -DarchetypeCatalog=internal


[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.4:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.4:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: internal -> org.apache.maven.archetypes:maven-archetype-archetype (An archetype which contains a sample archetype.)
2: internal -> org.apache.maven.archetypes:maven-archetype-j2ee-simple (An archetype which contains a simplifed sample J2EE application.)
3: internal -> org.apache.maven.archetypes:maven-archetype-plugin (An archetype which contains a sample Maven plugin.)
4: internal -> org.apache.maven.archetypes:maven-archetype-plugin-site (An archetype which contains a sample Maven plugin site.
      This archetype can be layered upon an existing Maven plugin project.)
5: internal -> org.apache.maven.archetypes:maven-archetype-portlet (An archetype which contains a sample JSR-268 Portlet.)
6: internal -> org.apache.maven.archetypes:maven-archetype-profiles ()
7: internal -> org.apache.maven.archetypes:maven-archetype-quickstart (An archetype which contains a sample Maven project.)
8: internal -> org.apache.maven.archetypes:maven-archetype-site (An archetype which contains a sample Maven site which demonstrates
      some of the supported document types like APT, XDoc, and FML and demonstrates how
      to i18n your site. This archetype can be layered upon an existing Maven project.)
9: internal -> org.apache.maven.archetypes:maven-archetype-site-simple (An archetype which contains a sample Maven site.)
10: internal -> org.apache.maven.archetypes:maven-archetype-webapp (An archetype which contains a sample Maven Webapp project.)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 7: 1   

Define value for property 'groupId': : test
Define value for property 'artifactId': : test
Define value for property 'version':  1.0-SNAPSHOT: :
Define value for property 'package':  test: :
Confirm properties configuration:
groupId: test
artifactId: test
version: 1.0-SNAPSHOT
package: test
 Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-archetype:1.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: basedir, Value: C:\tmp
[INFO] Parameter: package, Value: test
[INFO] Parameter: groupId, Value: test
[INFO] Parameter: artifactId, Value: test
[INFO] Parameter: packageName, Value: test
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: C:\tmp\test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 06:27 min
[INFO] Finished at: 2017-09-13T17:11:49+08:00
[INFO] Final Memory: 13M/155M
[INFO] ------------------------------------------------------------------------

放置文件及代码

archetype项目的不同之处在于resource目录下的archetype-resources目录,这个目录就是将应用于生成的项目的目录及代码,所以直接将文件放入即可。注意如果是从其他项目拷贝,需要拷贝pom.xml和src两个目录。

区别在于目录,比如你原始项目的代码包是com.abc.def.ssh,那么java目录下的结构应该如下

└── com

    └── abc
        └── def
            └── ssh
                ├── common
                ├── dal
                ├── exceptions
                ├── service
                └── web

这里我们很容易意识到,com.abc.def.ssh这部分不应该包含在生成项目中而是要根据生成项目是package来生成,所以在添加目录时需要去掉该部分目录,所以archetype-resources的java目录下是这样的

archetype-resources/src/main/
├── java
│   ├── common
│   ├── dal
│   ├── exceptions
│   ├── service
│   └── web
├── resources
│   ├── generatorConfig.xml
│   ├── logback.xml
│   ├── mappers
│   └── sql
└── webapp
    ├── components
    ├── css
    ├── fonts
    ├── images
    ├── index.jsp
    ├── js
    └── WEB-INF

增加archetype-metadata.xml

我的做法找一个archetype作为demo拷贝一个archetype-metadata.xml过来。我参考的是spring-boot-sample-actuator-log4j-archetype这个archetype,跟我的结构相似。如果你是文档控,可以看官方文档
贴出全文供参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="spring-boot-sample-actuator-log4j"
xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/main/webapp</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.jsp</include>
<include>**/*.html</include>
<include>**/*.properties</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory>src/main/webapp</directory>
<includes>
<include>**/*.jpg</include>
<include>**/*.css</include>
<include>**/*.npmignore</include>
<include>**/*.svg</include>
<include>**/*.ttf</include>
<include>**/*.png</include>
<include>**/*.js</include>
<include>**/*.eot</include>
<include>**/*.woff</include>
<include>**/*.ico</include>
<include>**/*.md</include>
<include>**/*.json</include>
<include>**/*.map</include>
</includes>
</fileSet>
</fileSets>
</archetype-descriptor>

修改各种变量,以适应生成的需要

首先需要修改的是archetype-resources下的pom.xml,将GAV全部替换成变量,语法同velocity

1
2
3
4
5
6
7
8
9
10
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<packaging>war</packaging>
<version>${version}</version>
<name>${artifactId} SSM APP</name>
...
<build>
<finalName>${artifactId}</finalName>
...
</build>

其次,每个java文件的,package语句部分需要修改,如果你原项目的包名为com.abc.def.ssh,那就把这部分替换为${package}
以一个java文件为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package ${package}.web;

import org.springframework.format.datetime.DateFormatter;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

public class BaseController {

@InitBinder
public void initBind(WebDataBinder webDataBinder){
webDataBinder.addCustomFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss"));
}


}

再次,涉及到配置的包路径部分全部需要替换为${package},包含但不限于mybatis的mapper配置、spring和springmvc中的配置。
BookMapper.xml

1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${package}.dal.mapper.BookMapper">
<resultMap id="BaseResultMap" type="${package}.dal.model.Book">
<!--

applicationContext.xml

1
2
3
4
5
<!-- 内容扫描 -->
<context:component-scan base-package="${package}">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>

ssm-servlet.xml

1
2
3
4
<!-- 内容扫描 -->
<context:component-scan
base-package="${package}.web" >
</context:component-scan>

其他配置

springmvc的配置文件名我是在web.xml直接通过init-param指定的,具体请见servlet配置部分。

archetype项目本身的pom里我加入了编译插件,指定编译的encoding。

测试

做完了以后,需要反复测试,因为很可能会遗漏各种细节。
首先在该项目根目录下执行mvn clean install 一定要clean,不然更改不会部署进去。
然后在根目录下执行mvn archetype:update-local-catalog更新本地的archetype-catalog
然后到另一个目录执行 mvn archetype:generate -DarchetypeCatalog=local 选择你自己的类型的数字,跟着指示一步步完成就可以了。这样项目就完成了