目录
一、简介
在做生成接口调用前,我们还得补充一个知识,那就是自定义Archetype,什么是Archetype?我其实 官网 说得很详细了,大家可以仔细阅读,主要还是在于archetype-metadata.xml的配置。
1.1、archetype目录结构
archetype
|-- pom.xml
`-- src
`-- main
`-- resources
|-- META-INF
| `-- maven
| `--archetype-metadata.xml
`-- archetype-resources
|-- pom.xml
`-- src
|-- main
| `-- java
| `-- App.java
`-- test
`-- java
`-- AppTest.java
我们把我们的项目分成了两个部分,一个部分是实体相关Archetype Domain,一部分是我们主要的业务逻辑Archetype Project,看看在我们这个springCloud项目里应该怎么定义,这可是实打实的实操哦。本来是发布两个,官方说我(篇幅太短,广告涉嫌违规,外链过多,缺少代码,图片涉嫌违规?想不通哪一点满足了!!!),不得不删除Archetype Domain,只留下Archetype Project,我还是希望官方能认真审查,不要让人寒心。说实话,因为官方的审核的原因,我都想换平台了。
很多小伙伴不知道自定义的Archetype应该怎么写,尤其是项目的结构不清楚,一定要记得我们的资源一定是放到resources下面一个叫做archetype-resources的目录里面,然后我们需要配置文件目录是META-INF/maven, 没有目录就手动新建。
1.2、Archetype Domain结构图
1.3、Archetype Project结构图
这个结构图和domain也没有多少区别,只是多了一些示例代码。
二、Archetype Project
2.1、项目的pom
pom.xml
<parent>
<groupId>cn.alian.microservice</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>archetype-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
<build>
<extensions>
<extension>
<groupId>org.apache.maven.archetype</groupId>
<artifactId>archetype-packaging</artifactId>
<version>3.2.0</version>
</extension>
</extensions>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-archetype-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<includeEmptyDirs>true</includeEmptyDirs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.12.RELEASE</version>
<inherited>false</inherited>
<executions>
<execution>
<id>spring-boot-repackage</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
2.2、archetype-metadata.xml
<?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="archetype"
xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<requiredProperties>
<requiredProperty key="groupId">
<defaultValue>cn.alian</defaultValue>
</requiredProperty>
<requiredProperty key="artifactId"/>
<requiredProperty key="version"/>
<requiredProperty key="app"/>
<requiredProperty key="configUri"/>
</requiredProperties>
<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" packaged="true" encoding="UTF-8">
<directory>src/test/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/test/resources</directory>
<includes>
<include>**/*.properties</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>bin</directory>
<includes>
<include>**/*.bat</include>
</includes>
</fileSet>
<fileSet filtered="false" packaged="false">
<directory/>
<includes>
<include>.gitignore</include>
</includes>
</fileSet>
</fileSets>
</archetype-descriptor>
<fileset>是要包含的文件,filtered=“true”表示该fileset中的文件在生成项目时要进行占位符替换。
Archetype Domain会包含如下文件:
- src/main/java下所有的 .java文件
- src/main/resources下所有的 .properties和 .xml文件
- src/test/java下所有的 .java文件
- src/test/resources下所有的 .properties文件
- 根目录下 .gitignore文件,一般用于git版本控制
- bin目录下的打包脚本
2.3、要生成项目的pom
pom.xml
<parent>
<groupId>cn.alian.microservice</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<description>请添加服务说明</description>
<properties>
</properties>
<dependencies>
<dependency>
<groupId>cn.alian.microservice</groupId>
<artifactId>common-db</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.alian.microservice</groupId>
<artifactId>common-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.log4jdbc</groupId>
<artifactId>log4jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.dozermapper</groupId>
<artifactId>dozer-core</artifactId>
</dependency>
<dependency>
<groupId>com.github.dozermapper</groupId>
<artifactId>dozer-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
需要注意的是,我这里的版本很多还是根据我们自己写的bom来决定的。
2.4、主类
__app__Application.java
package ${package};
import com.alian.microservice.common.gracefullshutdown.GracefulSpringApplication;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@Slf4j
@SpringBootApplication
//@EnableConfigurationProperties(AppProperties.class)
public class ${app}Application{
public static void main(String[] args) {
GracefulSpringApplication.run(${app}Application.class, args);
}
}
生成的项目直接可以实现优雅停服
2.5、配置类
AppProperties.java
package ${package}.config;
import com.alian.microservice.common.config.BaseProperties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
@Data
@Component
@RefreshScope
@ConfigurationProperties(prefix = "app")
public class AppProperties extends BaseProperties{
private String p1;
private String p2;
}
属性配置类事例也有了
config.java
package ${package}.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
@Slf4j
@Configuration
public class Config {
}
2.6、控制层
__app__ApiController.java
package ${package}.modulea.api;
import java.util.List;
import java.util.stream.Collectors;
import com.github.dozermapper.core.Mapper;
import com.google.common.collect.Lists;
import com.alian.microservice.common.swagger.dto.ApiResponseDto;
import com.alian.microservice.common.swagger.helper.MapperHelper;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.validation.annotation.Validated;
import ${package}.dto.${app}Dto;
//@Auth(type = AuthType.SESSION)//验证请求方式,可在配置文件启用及配置默认方式
@Slf4j
@RestController
@RequestMapping("api/v1/module")
@Validated//使用javax.validation.constraints进行参数验证
public class ${app}ApiController {
@Autowired
private Mapper mapper;
@Autowired
private MapperHelper mapperHelper;
@ApiOperation("list ${app}")//无此注解不生成接口文档
@GetMapping("list")
public ApiResponseDto<List<${app}Dto>> list(){
//domain转dto
//List<${app}> ${artifactId}s=Lists.newArrayList(new ${app}(),new ${app}());
//List<${app}Dto> list = ${artifactId}s.stream().map(e -> mapper.map(e, ${app}Dto.class)).collect(Collectors.toList());
//return ApiResponseDto.success(list);
//return ApiResponseDto.success(mapperHelper.map(list, ${app}Dto.class));
return ApiResponseDto.success(Lists.newArrayList(new ${app}Dto(),new ${app}Dto()));
}
@GetMapping("noApiOperation")
public ApiResponseDto noApiOperation(){
return ApiResponseDto.SUCCESS;
}
}
接口写法也有示例。
2.7、module
__app__Dto.java
package ${package}.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;
// 使用此种方式,set方法会return this,可以链式调用
// 由于set方法签名返回值不是void,会导致BeanUtils框架无法反射调用set方法
// 此时可以使用下面的Builder方式进行链式操作
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Data
@ApiModel(description = "数据结构信息")//不要使用value来进行备注,避免不能生成客户端
public class ${app}Dto{
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("日期时间")
private Date date;
@NotBlank
@ApiModelProperty("字符串")
private String str;
@NotNull
@ApiModelProperty("数字")
private Integer num;
}
请求及响应的实体示例也有
2.8、配置文件
bootstrap.properties
#应用名
spring.application.name=${artifactId}
#开发环境
spring.profiles.active=dev
#配置标签(根据配置中心,本文全是采用master)
spring.cloud.config.label=master
#配置中心地址
spring.cloud.config.uri=${configUri}
#设置为true时,如果服务无法连接到配置中心服务器,则服务启动失败
spring.cloud.config.fail-fast=true
#日志配置,通过配置中心获取
logging.config=${spring.cloud.config.uri}/logback/${spring.application.name}.xml
build.properties
build.groupId=${pom.groupId}
build.artifactId=${pom.artifactId}
build.version=${pom.version}
# 生成的文档说明
build.description=${pom.description}
# spring-boot:run -Ppack时方便生成api客户端
build.pack=${package}
ebean.properties
# 使用ebean配置响应的实体目录即可
ebean.packages=
以上的配置文件都有了,不用手动创建了。
三、发布到私服
通过我们发布脚本,把我们这两个项目发布到私服。
deploy.bat
cd %~dp0
cd..
call mvn clean deploy -Dmaven.test.skip=true
cd bin
pause
3.1、Archetype Domain打包发布
<dependency>
<groupId>cn.alian.microservice</groupId>
<artifactId>archetype-domain</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
3.2、Archetype Project打包发布
<dependency>
<groupId>cn.alian.microservice</groupId>
<artifactId>archetype-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
后续我们生成接口调用api或者创建新的项目都可以使用了。