Skip to content

单体应用

单体架构:

通俗地讲,“单体应用(monolith application)”就是将应用程序的所有功能都打包成一个独立的单元,可以是JAR、EXE、BIN或其它归档格式。 Spring Boot 完整的部署了一个项目,项目所有功能都在单个项目中做了实现。

单体应用基于SpringBoot进行开发,与微服务应用实现的功能是一样的,但是因为部署和实现方式不同,有如下区别:

  • 单体应用没有网关 - 单机部署无需网关

    微服务版中在网关服务实现的过滤器,对应实现是在springboot的拦截器中实现相同的功能。

  • 单体应用只有一个启动模块

    微服务各个服务的配置在Nacos中配置,单体应用的配置文件、启动类、配置类则配置在启动模块中。

  • 单体应用暴漏给前端的接口需要代理转接,实现微服务和单体应用使用同一个前端。具体见前端配置。

  • 对于模块间的调用,微服务使用feign在不同的微服务之间调用,而单体应用则直接引入类调用即可。

  • 接口地址校验也有区别

java
/**
* 检查指定接口是否有访问权限
*
* @param path   请求路径
* @param method 请求方法
* @return 是否有权限
*/
public Boolean checkUri(String path, String method) {
   // 中间代码省略...
   return apiList.parallelStream().distinct().anyMatch(item -> {
     String uri = item.getUri();
     /*
      * 若您确定只使用acuity-boot,而非acuity-cloud,请将def_resource_api表中uri的代理的前缀(/base、/system、/oauth)去除,即可 删除删除删除 if里面的代码!
      * 因为脚本数据是基于acuity-cloud配置的,所以uri地址会多一段gateway代理前缀。如
      * acuity-cloud 中地址为:/base/baseEmployee/page
      * 对应acuity-boot的地址为:/baseEmployee/page
      * 其中/base是因为使用了gateway增加的!
      */
     if (!StrUtil.startWithAny(uri, "/gateway")) {
         uri = StrUtil.subSuf(uri, StrUtil.indexOf(uri, '/', 1));
     }

     boolean matchUri = PATH_MATCHER.match(StrUtil.trim(uri), StrUtil.trim(path));

     log.info("path={}, uri={}, matchUri={}, method={} apiId={}", path, uri, matchUri, item.getRequestMethod(), item.getId());
     if (HttpMethod.ALL.name().equalsIgnoreCase(item.getRequestMethod())) {
         return matchUri;
     }
     return matchUri && StrUtil.equalsIgnoreCase(method, item.getRequestMethod());
 });

}
/**
* 检查指定接口是否有访问权限
*
* @param path   请求路径
* @param method 请求方法
* @return 是否有权限
*/
public Boolean checkUri(String path, String method) {
   // 中间代码省略...
   return apiList.parallelStream().distinct().anyMatch(item -> {
     String uri = item.getUri();
     /*
      * 若您确定只使用acuity-boot,而非acuity-cloud,请将def_resource_api表中uri的代理的前缀(/base、/system、/oauth)去除,即可 删除删除删除 if里面的代码!
      * 因为脚本数据是基于acuity-cloud配置的,所以uri地址会多一段gateway代理前缀。如
      * acuity-cloud 中地址为:/base/baseEmployee/page
      * 对应acuity-boot的地址为:/baseEmployee/page
      * 其中/base是因为使用了gateway增加的!
      */
     if (!StrUtil.startWithAny(uri, "/gateway")) {
         uri = StrUtil.subSuf(uri, StrUtil.indexOf(uri, '/', 1));
     }

     boolean matchUri = PATH_MATCHER.match(StrUtil.trim(uri), StrUtil.trim(path));

     log.info("path={}, uri={}, matchUri={}, method={} apiId={}", path, uri, matchUri, item.getRequestMethod(), item.getId());
     if (HttpMethod.ALL.name().equalsIgnoreCase(item.getRequestMethod())) {
         return matchUri;
     }
     return matchUri && StrUtil.equalsIgnoreCase(method, item.getRequestMethod());
 });

}
java
/**
* 检查指定接口是否有访问权限
*
* @param path   请求路径
* @param method 请求方法
* @return 是否有权限
*/
public Boolean checkUri(String path, String method) {
   // 中间代码省略...
 return apiList.parallelStream().distinct().anyMatch(item -> {
     String uri = item.getUri();
     boolean matchUri = PATH_MATCHER.match(StrUtil.trim(uri), StrUtil.trim(path));

     log.info("path={}, uri={}, matchUri={}, method={} apiId={}", path, uri, matchUri, item.getRequestMethod(), item.getId());
     if (HttpMethod.ALL.name().equalsIgnoreCase(item.getRequestMethod())) {
         return matchUri;
     }
     return matchUri && StrUtil.equalsIgnoreCase(method, item.getRequestMethod());
 });
}
/**
* 检查指定接口是否有访问权限
*
* @param path   请求路径
* @param method 请求方法
* @return 是否有权限
*/
public Boolean checkUri(String path, String method) {
   // 中间代码省略...
 return apiList.parallelStream().distinct().anyMatch(item -> {
     String uri = item.getUri();
     boolean matchUri = PATH_MATCHER.match(StrUtil.trim(uri), StrUtil.trim(path));

     log.info("path={}, uri={}, matchUri={}, method={} apiId={}", path, uri, matchUri, item.getRequestMethod(), item.getId());
     if (HttpMethod.ALL.name().equalsIgnoreCase(item.getRequestMethod())) {
         return matchUri;
     }
     return matchUri && StrUtil.equalsIgnoreCase(method, item.getRequestMethod());
 });
}
  • 初始化数据源的实现也有所区别
java
// acuity-boot 项目GeneratorController位于acuity-boot-server
@ResponseBody
@ApiOperation(value = "查询在线服务的前缀")
@GetMapping("/gateway/findOnlineServicePrefix")
public R<Map<String, String>> findOnlineServicePrefix() {

   Map<String, String> map = MapUtil.newHashMap();
   map.put(application, "base");
   return R.success(map);
}
// acuity-boot 项目GeneratorController位于acuity-boot-server
@ResponseBody
@ApiOperation(value = "查询在线服务的前缀")
@GetMapping("/gateway/findOnlineServicePrefix")
public R<Map<String, String>> findOnlineServicePrefix() {

   Map<String, String> map = MapUtil.newHashMap();
   map.put(application, "base");
   return R.success(map);
}
java
// acuity-cloud 项目GeneratorController位于acuity-gateway-server
   @ResponseBody
   @ApiOperation(value = "查询在线服务的前缀")
   @GetMapping("/gateway/findOnlineServicePrefix")
   public R<Map<String, String>> findOnlineServicePrefix() {
       List<String> services = discoveryClient.getServices();

       Map<String, String> map = MapUtil.newHashMap();
       services.forEach(service ->
               gatewayProperties.getRoutes().forEach(route -> {
                   if (StrUtil.equalsIgnoreCase(service, route.getUri().getHost())) {
                       if (CollUtil.isEmpty(route.getPredicates())) {
                           return;
                       }
                       PredicateDefinition predicateDefinition = route.getPredicates().get(0);
                       predicateDefinition.getArgs().forEach((k, v) -> {
                           map.put(service, StrUtil.subBetween(v, "/", "/**"));
                       });
                   }
               })
       );
       return R.success(map);
   }
// acuity-cloud 项目GeneratorController位于acuity-gateway-server
   @ResponseBody
   @ApiOperation(value = "查询在线服务的前缀")
   @GetMapping("/gateway/findOnlineServicePrefix")
   public R<Map<String, String>> findOnlineServicePrefix() {
       List<String> services = discoveryClient.getServices();

       Map<String, String> map = MapUtil.newHashMap();
       services.forEach(service ->
               gatewayProperties.getRoutes().forEach(route -> {
                   if (StrUtil.equalsIgnoreCase(service, route.getUri().getHost())) {
                       if (CollUtil.isEmpty(route.getPredicates())) {
                           return;
                       }
                       PredicateDefinition predicateDefinition = route.getPredicates().get(0);
                       predicateDefinition.getArgs().forEach((k, v) -> {
                           map.put(service, StrUtil.subBetween(v, "/", "/**"));
                       });
                   }
               })
       );
       return R.success(map);
   }

欢迎使用天源云Saas快速开发系统