基于Vue+SpringCloudAlibaba微服务电商项目实战-技术选型-002:代码管理GitLab与Maven私服

1 Maven私服与Gateway整合Swagger演示

今日课程任务

  1. 微服务Api接口响应Code规范
  2. 微服务接口Api文档管理整合
  3. SpringCloudGateway整合Swagger文档
  4. 构建企业级Maven私服管理

2 构建微服务接口响应Code码

接口规范的定义
{“code”:500,“msg”:“appId不能为空!”,“data”:null}
创建模块mt-shop-service-api-base
mt-shop-parent
--------mt-shop-service-base
---------------- mt-shop-service-api-base 相关base继承类
拷贝工具类

public interface Constants {
    // 响应请求成功
    String HTTP_RES_CODE_200_VALUE = "success";
    // 系统错误
    String HTTP_RES_CODE_500_VALUE = "fail";
    // 响应请求成功code
    Integer HTTP_RES_CODE_200 = 200;
    // 系统错误
    Integer HTTP_RES_CODE_500 = 500;

}
@Data
public class BaseResponse<T> {

   /**
    * 返回码
    */
   private Integer code;
   /**
    * 消息
    */
   private String msg;
   /**
    * 返回
    */
   private T data;
   // 分页

   public BaseResponse() {

   }

   public BaseResponse(Integer code, String msg, T data) {
      super();
      this.code = code;
      this.msg = msg;
      this.data = data;
   }

}
@Data
public class BaseApiService<T> {

    public BaseResponse<T> setResultError(Integer code, String msg) {
        return setResult(code, msg, null);
    }

    /**
     * 返回错误,可以传msg
     *
     * @param msg
     * @return
     */
    public BaseResponse<T> setResultError(String msg) {
        return setResult(Constants.HTTP_RES_CODE_500, msg, null);
    }

    /***
     * 返回成功,可以传data值
     * @param data
     * @return
     */
    public BaseResponse<T> setResultSuccess(T data) {
        return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, data);
    }

    /**
     * 返回成功,沒有data值
     *
     * @return
     */
    public BaseResponse<T> setResultSuccess() {
        return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, null);
    }


    /**
     * 通用封装 通用封装
     *
     * @param code
     * @param msg
     * @param data
     * @return
     */

    public BaseResponse<T> setResult(Integer code, String msg, T data) {
        return new BaseResponse<T>(code, msg, data);
    }

}

mt-shop-service-api 工程引入mt-shop-service-api-base项目即可
会员实现类继承BaseApiService类

@RestController
public class WeiXinServiceImpl extends BaseApiService implements WeiXinService {

    @Override
    public BaseResponse<String> addApp(String appId, String appPwd) {
        if (StringUtils.isEmpty(appId)) {
            return setResultError("appId不能为空");
        }
        if (StringUtils.isEmpty(appPwd)) {
            return setResultError("appPwd不能为空");
        }
        return setResultSuccess("蚂蚁课堂");
    }
}

测试效果:
在这里插入图片描述

3 微服务项目整合Swagger文档

构建企业级别Api文档管理
接口文档主要提供给前端使用,包括请求地址、请求类型、请求方法、请求参数、响应code、响应的data等,使用swagger可以基于注解的形式生成文档。

Maven依赖配置

<!-- swagger-spring-boot -->
<dependency>
    <groupId>com.spring4all</groupId>
    <artifactId>swagger-spring-boot-starter</artifactId>
    <version>1.7.0.RELEASE</version>
</dependency>

application.yml新增Swagger相关配置

swagger:
  base-package: com.mayikt.service.impl
  title: SpringCloud2.x构建微服务电商项目-微信服务接口
  description: 基于SpringCloud2.x构建微服务电商项目
  version: 1.1
  terms-of-service-url: www.mayikt.com
  contact:
    name: maplefire
    email: 1109733977@qq.com
    url: www.mayikt.com
  enabled: true

接口中Swagger注解配置

@Api(tags = "微信基本服务接口")
public interface WeiXinService {

    /**
     * 微信接口
     *
     * @return
     */
    @GetMapping("appInfo")
    @ApiOperation("appInfo接口")
    @ApiImplicitParam(name = "userId", value = "用户Id", required = true)
    @ApiResponse(code = 200, message = "响应成功")
    String appInfo(@RequestParam("userId") Long userId);

    @GetMapping("/addApp")
    @ApiOperation("addApp接口")
    @ApiImplicitParams({@ApiImplicitParam(name = "appId", value = "应用Id", required = true)
            , @ApiImplicitParam(name = "appPwd", value = "应用密码", required = true)})
    @ApiResponses({@ApiResponse(code = 200, message = "响应成功"),
            @ApiResponse(code = 500, message = "系统错误")})
    BaseResponse<String> addApp(@RequestParam("appId") String appId, @RequestParam("appPwd") String appPwd);
}

Swagger注解配置说明

@Api:用在请求的类上,表示对类的说明
    tags="说明该类的作用,可以在UI界面上看到的注解"
    value="该参数没什么意义,在UI界面上也看到,所以不需要配置"
@ApiOperation:用在请求的方法上,说明方法的用途、作用
    value="说明方法的用途、作用"
    notes="方法的备注说明"
@ApiImplicitParams:用在请求的方法上,表示一组参数说明
    @ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
        name:参数名
        value:参数的汉字说明、解释
        required:参数是否必须传
        paramType:参数放在哪个地方
            · header --> 请求参数的获取:@RequestHeader
            · query --> 请求参数的获取:@RequestParam
            · path(用于restful接口)--> 请求参数的获取:@PathVariable
            · body(不常用)
            · form(不常用)    
        dataType:参数类型,默认String,其它值dataType="Integer"       
        defaultValue:参数的默认值
@ApiResponses:用在请求的方法上,表示一组响应
    @ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
        code:数字,例如400
        message:信息,例如"请求参数没填好"
        response:抛出异常的类
@ApiModel:用于响应类上,表示一个返回响应数据的信息
            (这种一般用在post创建的时候,使用@RequestBody这样的场景,
            请求参数无法使用@ApiImplicitParam注解进行描述的时候)
@ApiModelProperty:用在属性上,描述响应类的属性

启动类新增配置
@EnableSwagger2Doc 注意不是@EnableSwagger2(Swagger原生启动注解)
访问地址:http://127.0.0.1:9090/swagger-ui.html
测试效果:
在这里插入图片描述
Swagger2Doc启动的原理
封装了SwaggerConfig类,底层自动加载SwaggerAutoConfiguration类。

4 Gateway整合Swagger

基于网关整合 Api文档
使用微服务网关统一管理整个微服务所有接口文档。
原理分析:网关把服务名称转换成ip获得接口文档。
在这里插入图片描述
创建模块mt-shop-basics-springcloud-gateway
mt-shop-parent
--------mt-shop-basics
----------------mt-shop-basics-springcloud-gateway
Maven依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
        <version>2.2.1.RELEASE</version>
    </dependency>
</dependencies>

注意:将mt-shop-parent中spring-boot-starter-web和spring-cloud-starter-openfeign依赖组件移到mt-shop-service-api的pom中,否则产生冲突报错。

application.yml

server:
  port: 80
spring:
  application:
    name: mayikt-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      locator:
        enabled: true
      routes:
        - id: mayikt-weixin
          uri: lb://mayikt-weixin
          predicates:
            - Path=/mayikt-weixin/**
          filters:
            - SwaggerHeaderFilter
            - StripPrefix=1
        - id: mayikt-member
          uri: lb://mayikt-member
          predicates:
            - Path=/mayikt-member/**
          filters:
            - SwaggerHeaderFilter
            - StripPrefix=1
      x-forwarded:
        enabled: false

网关项目类

@Component
@Primary
@AllArgsConstructor
public class SwaggerProvider implements SwaggerResourcesProvider {
    public static final String API_URI = "/v2/api-docs";
    private final RouteLocator routeLocator;
    private final GatewayProperties gatewayProperties;


    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        List<String> routes = new ArrayList<>();
        routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
        gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId()))
                .forEach(routeDefinition -> routeDefinition.getPredicates().stream()
                        .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
                        .forEach(predicateDefinition -> resources.add(swaggerResource(routeDefinition.getId(),
                                predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
                                        .replace("/**", API_URI)))));
        return resources;
    }

    private SwaggerResource swaggerResource(String name, String location) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }
}
@Component
@Deprecated
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
    private static final String HEADER_NAME = "X-Forwarded-Prefix";

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getURI().getPath();
            if (!StringUtils.endsWithIgnoreCase(path, SwaggerProvider.API_URI)) {
                return chain.filter(exchange);
            }
            String basePath = path.substring(0, path.lastIndexOf(SwaggerProvider.API_URI));

            ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
            ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
            return chain.filter(newExchange);
        };
    }
}
@RestController
@RequestMapping("/swagger-resources")
public class SwaggerHandler {
    @Autowired(required = false)
    private SecurityConfiguration securityConfiguration;
    @Autowired(required = false)
    private UiConfiguration uiConfiguration;
    private final SwaggerResourcesProvider swaggerResources;

    @Autowired
    public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
        this.swaggerResources = swaggerResources;
    }


    @GetMapping("/configuration/security")
    public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
    }

    @GetMapping("/configuration/ui")
    public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
    }

    @GetMapping("")
    public Mono<ResponseEntity> swaggerResources() {
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    }
}
@SpringBootApplication
public class AppGateway {
    /**
     * Gateway的底层是基于webflux
     * SpringMVC底层基于我们的servlet实现
     * Spring-web封装了我们SpringMVC
     * @param args
     */
    public static void main(String[] args) {
        SpringApplication.run(AppGateway.class);
    }
}

测试效果:
在这里插入图片描述
Swagger网关重复发送服务别名解决
application.yml文件中加上配置spring.cloud.gateway.x-forwarded.enabled=false

5 企业级Maven私服仓库实现原理

什么场景用Maven私服?
在实际开发中,项目中可能会用到第三方的jar、内部通讯的服务接口都会打入到公司的私服中。

  1. 缓存企业级内部使用的jar包
  2. rpc远程调用发布微服务接口
    实现原理:
    在这里插入图片描述

6 基于docker安装Maven私服仓库

基于docker安装Maven私服

1 下载一个nexus3的镜像
docker pull sonatype/nexus3
2 将容器内部/var/nexus-data挂载到主机/root/nexus-data目录。
docker run -d -p 8081:8081 --name nexus -v /root/nexus-data:/var/nexus-data --restart=always sonatype/nexus3

Maven私服启动容器稍微比较慢,等待1分钟即可。
可以查看正在启动的日志 docker attach 容器的id
在这里插入图片描述
看到这个界面,说明我们的maven私服启动成功
访问http://ip:8081
在这里插入图片描述
maven私服仓库默认密码配置
进入到容器中
docker ps 查看dockerId
docker exec -it 8a1dcfb84f53(dockerId) bash
cat /nexus-data/admin.password
复制该密码 账号为admin,登录以后重新设置密码
在这里插入图片描述

7 向Maven仓库上传jar包项目

创建一个SpringBoot项目发布
创建私服仓库

创建仓库,点击Create repository,然后选择maven2(hosted)然后输入仓库名称(mayikt-release)。在version policy中选择这个仓库的类型,这里选择Release,在Deployment policy中选择Allow redeploy.

创建私服账号
点击左侧菜单栏的Users菜单,然后点击Create local user。这里创建了一个用户,账号密码都是:mayikt mayikt

本地maven路径/conf/settings.xml

<servers>
	<server>
        <id>mayikt</id>
        <username>mayikt</username>
        <password>mayikt</password>
      </server>
  </servers>

SpringBoot项目核心配置pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mayikt</groupId>
    <artifactId>mayikt2020-springboot</artifactId>
    <version>1.0-RELEASE</version>
    <!--注意限定版本一定为RELEASE,因为上传的对应仓库的存储类型为RELEASE -->
    <!--指定仓库地址 -->
    <distributionManagement>
        <repository>
            <!--此名称要和.m2/settings.xml中设置的ID一致 -->
            <id>mayikt</id>
            <url>http://192.168.0.121:8081/repository/mayikt-release/</url>
        </repository>
    </distributionManagement>

    <build>
        <plugins>
            <!--发布代码Jar插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.7</version>
            </plugin>
            <!--发布源码插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>2.2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Maven 执行命令 mvn deploy 上传jar包即可
注意版本号码一定要是为:release版本 ,否则上传jar报错
在这里插入图片描述
本地项目引入maven私服jar

<dependencies>
    <dependency>
        <groupId>com.mayikt</groupId>
        <artifactId>mayikt2020-springboot</artifactId>
        <version>2.0-RELEASE</version>
    </dependency>
</dependencies>
<repositories>
    <repository>
        <id>mayikt</id>
        <url>>http://192.168.0.121:8081/repository/mayikt-release/</url>
    </repository>
</repositories>

如何判断文件是否发生改变
如何知道一个文件是否改变了呢?用比较文件hash值的方法,文件hash又叫文件签名,文件中哪怕一个bit位被改变了,文件hash就会不同。比较常用的文件hash算法有MD5和SHA-1。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值