| <!DOCTYPE html> |
| <html class="writer-html5" lang="en" > |
| <head> |
| <meta charset="utf-8" /> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| <link rel="shortcut icon" href="../../img/favicon.ico" /> |
| <title>1.3.0 升级 2.0.0指导 - ServiceComb Java Chassis 开发指南</title> |
| <link rel="stylesheet" href="../../css/theme.css" /> |
| <link rel="stylesheet" href="../../css/theme_extra.css" /> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/github.min.css" /> |
| |
| <script> |
| // Current page data |
| var mkdocs_page_name = "1.3.0 \u5347\u7ea7 2.0.0\u6307\u5bfc"; |
| var mkdocs_page_input_path = "featured-topics/upgrading/1_3_0T2_0_0.md"; |
| var mkdocs_page_url = null; |
| </script> |
| |
| <script src="../../js/jquery-3.6.0.min.js" defer></script> |
| <!--[if lt IE 9]> |
| <script src="../../js/html5shiv.min.js"></script> |
| <![endif]--> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script> |
| <script>hljs.initHighlightingOnLoad();</script> |
| </head> |
| |
| <body class="wy-body-for-nav" role="document"> |
| |
| <div class="wy-grid-for-nav"> |
| <nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav"> |
| <div class="wy-side-scroll"> |
| <div class="wy-side-nav-search"> |
| <a href="../../index.html" class="icon icon-home"> ServiceComb Java Chassis 开发指南 |
| </a> |
| </div> |
| |
| <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu"> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../toc.html">目录</a> |
| </li> |
| </ul> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../index.html">概述</a> |
| </li> |
| </ul> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../start/catalog.html">快速入门</a> |
| </li> |
| </ul> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../start/design.html">设计选型参考</a> |
| </li> |
| </ul> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../build-provider/definition/service-definition.html">微服务定义</a> |
| </li> |
| </ul> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../build-provider/catalog.html">开发服务提供者</a> |
| </li> |
| </ul> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../build-consumer/catalog.html">开发服务消费者</a> |
| </li> |
| </ul> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../general-development/catalog.html">通用功能开发</a> |
| </li> |
| </ul> |
| <p class="caption"><span class="caption-text">多样化的通信协议功能参考</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../transports/introduction.html">多协议介绍</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../transports/rest-over-servlet.html">REST over Servlet</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../transports/rest-over-vertx.html">REST over Vertx</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../transports/http2.html">REST over HTTP2</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../transports/highway-rpc.html">Highway</a> |
| </li> |
| </ul> |
| <p class="caption"><span class="caption-text">多样化的服务注册与发现功能参考</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../registry/introduction.html">注册发现说明</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../registry/service-center.html">使用服务中心</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../registry/local-registry.html">本地注册发现</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../registry/distributed.html">去中心化注册发现</a> |
| </li> |
| </ul> |
| <p class="caption"><span class="caption-text">管理服务配置</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../config/general-config.html">通用配置说明</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../config/read-config.html">在程序中读取配置信息</a> |
| </li> |
| </ul> |
| <p class="caption"><span class="caption-text">服务治理功能参考</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../references-handlers/intruduction.html">处理链介绍</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../references-handlers/loadbalance.html">负载均衡</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../references-handlers/ratelimit.html">限流</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../references-handlers/router.html">灰度发布</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../references-handlers/fault-injection.html">故障注入</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../references-handlers/governance.html">流量特征治理</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../references-handlers/fail-retry.html">快速失败和重试</a> |
| </li> |
| </ul> |
| <p class="caption"><span class="caption-text">网关功能参考</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../edge/open-service.html">介绍</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../edge/by-servicecomb-sdk.html">使用 Edge Service 做网关</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../edge/zuul.html">使用 `zuul` 和 `spring cloud gateway` 做网关</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../edge/nginx.html">nginx 网关简单介绍</a> |
| </li> |
| </ul> |
| <p class="caption"><span class="caption-text">安全特性参考</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../references-handlers/publickey.html">公钥认证</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../security/tls.html">使用TLS通信</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../security/shi-yong-rsa-ren-zheng.html">使用RSA认证</a> |
| </li> |
| </ul> |
| <p class="caption"><span class="caption-text">服务打包和运行</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../packaging/standalone.html">以standalone模式打包</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../packaging/web-container.html">以WEB容器模式打包</a> |
| </li> |
| </ul> |
| <p class="caption"><span class="caption-text">专题文章</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../using-java-chassis-in-spring-boot/using-java-chassis-in-spring-boot.html">在Spring Boot中使用java chassis</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../features.html">新功能介绍系列文章</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../compatibility.html">兼容问题和兼容性策略</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../upgrading.html">升级指导系列文章</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../performance.html">性能问题分析和调优</a> |
| </li> |
| </ul> |
| <p class="caption"><span class="caption-text">常用配置项参考</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../config-reference/rest-transport-client.html">REST Transport Client 配置项</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../config-reference/config-center-client.html">Config Center Client 配置项</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../config-reference/service-center-client.html">Service Center Client 配置项</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../config-reference/kie-client.html">ServiceComb Kie Client 配置项</a> |
| </li> |
| </ul> |
| <p class="caption"><span class="caption-text">常见问题</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../question-and-answer/faq.html">FAQ</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../question-and-answer/question_answer.html">Q & A</a> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../../question-and-answer/interface-compatibility.html">微服务接口兼容常见问题</a> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </nav> |
| |
| <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"> |
| <nav class="wy-nav-top" role="navigation" aria-label="Mobile navigation menu"> |
| <i data-toggle="wy-nav-top" class="fa fa-bars"></i> |
| <a href="../../index.html">ServiceComb Java Chassis 开发指南</a> |
| |
| </nav> |
| <div class="wy-nav-content"> |
| <div class="rst-content"><div role="navigation" aria-label="breadcrumbs navigation"> |
| <ul class="wy-breadcrumbs"> |
| <li><a href="../../index.html" class="icon icon-home" alt="Docs"></a> »</li> |
| <li>1.3.0 升级 2.0.0指导</li> |
| <li class="wy-breadcrumbs-aside"> |
| </li> |
| </ul> |
| <hr/> |
| </div> |
| <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article"> |
| <div class="section" itemprop="articleBody"> |
| |
| <h1 id="130-200">1.3.0 升级 2.0.0指导</h1> |
| <p>2.0.0 版本实现了 <a href="../features/weak-type-contrast.html">弱类型契约</a>。 |
| 总体而言,对于 <code>REST</code> 通信模式, 弱类型契约不仅增强了写代码的灵活性, 还完整保留了强类型契约的写代码方式,几乎不 |
| 存在用户需要感知的变更。 对于 <code>HIGHWAY</code> 通信模式, 由于底层采用 ProtoBuffer 编码, 而 ProtoBuffer 天然就是一种 |
| 强类型契约的编解码过程, java-chassis 为了支持弱类型契约, 做了大量努力, 在一些边界条件处理上与弱类型契约存在 |
| 变更,两个版本的编解码是不兼容的,需要同时升级提供者和消费者。 在编码方式上,差异主要体现在对于缺省值的处理,对于 |
| <code>null</code> 的处理等问题上。</p> |
| <h2 id="highway">Highway通信协议的变更</h2> |
| <p>Highway通信协议是2.0.0最大的变更点。如果业务采用了Highway通信协议,需要确保所有相关的consumer |
| 和provider都必须升级,低版本的consumer和高版本的provider之间无法直接通信。此外,从代码风格的层面, |
| 还有如下一些变更。</p> |
| <ol> |
| <li>空字符串和null的传输:protoBuffer 协议对空字符串和null都序列化为空,反序列化的结果都是null。 |
| 应用程序的业务逻辑不应该使用空字符串和null表达不同语义。尽管对于REST,程序底层支持这样的区分, |
| 仍然不建议将业务逻辑构筑在这个假设之上,避免后期升级和兼容陷阱。 </li> |
| <li>如果请求参数或者返回值是一个POJO,假设Person,REST可以返回null,但是HIGHWAY始终会创建一个 |
| Person 对象返回。业务逻辑尽可能不要依赖于null对象提供语义。</li> |
| <li>在contrast first编程模式情况下,用户先写契约,然后通过契约生成代码,并将契约文件放 |
| 到 <code>microservices/{microservice name}/{schema id}.yaml</code> 文件中,这种情况下不会通过代码生成 |
| 契约。通常通过工具生成代码,工具生成的数据类型和契约的数据类型匹配,但是如果这种场景的代码经过 |
| 修改,并且yaml中的数据类型是number,而代码中的类型是Integer,在HIGHWAY通信模式下会报告错误。 |
| HIGHWAY 会将 number 类型解析为 protoBuffer 的 double 类型, 对应的 JAVA 类型为 double。 |
| protoBuffer 不支持将Integer类型采用Double的方式序列化。在contract first编程模式下,建议通过 |
| 生成工具生成代码,这样用户就不用了解swagger数据类型和JAVA数据类型映射的细节,避免一些陷阱。</li> |
| <li>HIGHWAY 的数据类型定义不支持一些特殊字符串,比如 <code>H.264</code> 和 <code>MPEG-2</code> 在OPEN API里面是合法的 |
| 参数名称,但是在 protoBuffer 里面是不合法的参数名称。带有"."和"-"的参数名字不能用于 HIGHWAY。 |
| 如果存在,第一次访问这个接口的时候,会报告: |
| <code>io.protostuff.compiler.parser.ParserException: Could not parse syntax</code> 异常。 </li> |
| <li>对于 ENUM 有一个需要特别注意的地方,protoBuffer 采用int来序列化 ENUM ,int的默认值(即0)不会序列化,那么反 |
| 序列化的时候,ENUM 的缺省值必须为第一个值。应用程序需要将null和第一个缺省值当成一样的语义对待。比 |
| 较好的做法是在程序里面显示的给 ENUM 字段赋缺省值。</li> |
| <li>HIGHWAY 不支持数组参数存在 null 值的情况。如果一个接口的参数是String[],那么里面的元素不能 |
| 为 null,否则序列化和反序列化会失败。</li> |
| <li>对于 primitive 类型,并且接口声明为 @Required,由于 HIGHWAY 并不会序列化缺省值,比如 0 等, |
| 在Consumer端传递的参数值为 0 的时候,Provider 端并不能区分这个值是传递了0,还是没有传递。因 |
| 此 HIGHWAY 会忽略 @Required 声明,使用缺省值0。</li> |
| <li> |
| <p>如果一个属性的名称采用一个小写字母开头,并且只有一个小写字母,即使生成的getter/setter是合法 |
| 的, swagger 生成的属性名称还是会出现错误。应该尽可能避免使用这样的属性名称。必须使用的场景,需要 |
| 显示的使用 @JsonProperty 声明。</p> |
| <pre><code> ```java |
| public class SpecialNameModel { |
| // names starts with only one lower case , although getter/setter generated by IDE is correct, |
| // will cause jackson generate incorrect swagger names. |
| // @JsonProperty must be used to make json work in a predictable way. |
| @JsonProperty("aIntName") |
| private int aIntName; |
| |
| public int getaIntName() { |
| return aIntName; |
| } |
| |
| public void setaIntName(int aIntName) { |
| this.aIntName = aIntName; |
| } |
| } |
| ``` |
| </code></pre> |
| </li> |
| <li> |
| <p>返回多种类型或者通过 ContextUtils 设置状态码 HIGHWAY 不再支持。 尽管 1.3.0 之前用户也不会在 HIGHWAY 模式下 |
| 使用类似下面的代码, 但是在 1.3.0 之前的版本, 这些代码部分确实能够工作。</p> |
| <pre><code>```java |
| @PUT |
| public String sayHi(@PathParam("name") String name) { |
| ContextUtils.getInvocationContext().setStatus(202); |
| return name + " sayhi"; |
| } |
| ``` |
| </code></pre> |
| </li> |
| </ol> |
| <p><strong><em>优秀实践</em></strong>:</p> |
| <p>如果项目中需要同时使用 REST 和 HIGHWAY 对外提供服务, 并且会使用到一些 HIGHWAY 协议有差异的用法, |
| 可以将这些接口定义到不同的类中, 使用不一样的 Schema ID 进行区分,比如 <code>MySchemaHighwayOnly</code> , |
| <code>MySchemaRestOnly</code> , <code>MySchema</code> 。</p> |
| <h2 id="edge-service-model">使用 Edge Service 场景下 Model 的缺省值</h2> |
| <p>假设业务应用采用 Edge Service 转发请求。 并且定义了一个接口, 有如下 Model 作为参数:</p> |
| <pre><code class="language-java">public class Person { |
| private Integer age = 30; |
| private List<String> items; |
| } |
| </code></pre> |
| <p>用户从浏览器调用这个接口, JSON 内容为 <code>{}</code> , 不传递任何内容, 1.3.0 版本得到的 age = null, items = null 。 |
| 2.0.0 版本 age = 30, items 为空表, 不为 null 。 这个行为是由于 1.3.0 版本 Edge Service 会自动生成一个 Person |
| 类, 这个类没有缺省值, Edge Service 重新序列化, 造成服务端取到了 null。 弱类型契约没有中间类型, 序列化的结果 |
| 和用户从浏览器传递过来的值一样。 </p> |
| <h2 id="resttemplate">RestTemplate的使用</h2> |
| <p>对于下面的 consumer 和 provider 代码:</p> |
| <pre><code>// provider |
| @PostMapping(path = "/object") |
| public Object testObject(@RequestBody Object input) |
| |
| // consumer |
| Object result = restTemplate.postForObject(prefix + "/object", |
| new EmptyObject(), EmptyObject.class); |
| </code></pre> |
| <p>1.3.0 版本返回的 result 类型为 Map。 2.0.0 版本返回的类型和 postForObject 指定的类型一致,上面的示例 |
| 中,result 类型为 EmptyObject。</p> |
| <p>下面的代码,1.3.0 和 2.0.0 版本运行的结果是一样的:</p> |
| <pre><code>List<GenericObjectParam<List<RecursiveObjectParam>>> response = consumers.getSCBRestTemplate() |
| postForObject("/testListObjectParam", request, List.class); |
| </code></pre> |
| <p>前提条件是 GenericObjectParam 和 RecursiveObjectParam 在 consumer 的 classpath 中存在对应的 |
| 类,并且 package 和服务端定义的类一样。如果不一样, 则 response 类型为 List<Map>,上面的代码会 |
| 抛出类型转换异常。2.0.0 没有相同 package 的约束,并且在保持兼容的情况下,支持下面的用法:</p> |
| <pre><code>HttpEntity<SpringmvcBasicRequestModel> requestEntity = new HttpEntity<>(requestModel, null); |
| List<SpringmvcBasicResponseModel> responseModelList = |
| template.exchange("/postListObject", HttpMethod.POST, requestEntity, |
| new ParameterizedTypeReference<List<SpringmvcBasicResponseModel>>() { |
| }).getBody(); |
| </code></pre> |
| <p>这种方式的语义根据清晰,在使用泛型的时候,建议采用这种用法。</p> |
| <p>在1.3.0版本支持如下用法:</p> |
| <pre><code class="language-java">template.postForEntity(url, |
| "{\"time\":3073113710456,\"date\":3073113710456,\"holder\":\"test\"}", |
| DateTimeModel.class) |
| </code></pre> |
| <p>即通过 JSON String 的方式传递参数给后台的 DateTimeModel 对象。 由于这种用法在解析的时候存在二义性, 2.0.0 |
| 不再支持这种用法。 可以使用 Map 或者 JsonObject 来传递。 </p> |
| <h2 id="asyncresttemplate">AsyncRestTemplate的使用</h2> |
| <p>1.3.0 和 2.0.0 中 AsyncRestTemplate 的使用方式一样,没有变化。但是由于 2.0.0 只支持spring 5版 |
| 本,而 spring 5 将 AsyncRestTemplate 标记为废弃状态,开发者在后续开发过程中尽可能不要使 |
| 用 AsyncRestTemplate 。可以使用 CompletableFuture 来替代,可以参考这 |
| 个<a href="https://github.com/apache/servicecomb-samples/pull/41/files">例子</a>。</p> |
| <h2 id="spring-boot">Spring Boot 集成的变化</h2> |
| <p>2.0.0 不再支持 spring 4 和 spring boot 1, 缺省使用 spring 5 和 spring boot 2, 并修改了相 |
| 关 starters 的名称。 可以通过阅 |
| 读 <a href="../../using-java-chassis-in-spring-boot/using-java-chassis-in-spring-boot.html">在Spring Boot中使用java chassis</a> 了解 |
| 相关变化。</p> |
| <h2 id="jdk-11">支持 JDK 11</h2> |
| <p>2.0.0 版本可以在 JDK 11 下运行,并进行了简单的集成测试。 2.0.0 支持的核心 JDK 版本仍然是 8, 并没有采用 JDK 11 编译。 |
| JDK 11 的一个主要变化是后续可能不再支持通过反射改变类的封装性。 这个特性目前有很多地方使用, 2.0.0 版本为了适配 JDK 11, |
| 某些特性的使用会发生变化。 具体有如下几个特性 :</p> |
| <ul> |
| <li>使用 EventManager 注册事件</li> |
| </ul> |
| <p>在 1.3.0 版本, 允许采用 private 类 或者 内部匿名类作为事件监听对象, 比如:</p> |
| <pre><code class="language-java">public void myMethod() { |
| Object receiveEvent = new Object() { |
| @Subscribe |
| public void onEvent(AlarmEvent circutBreakerEvent) { |
| taskList.add(circutBreakerEvent); |
| } |
| }; |
| EventManager.getEventBus().register(receiveEvent); |
| } |
| </code></pre> |
| <p>在 2.0.0 版本不允许,启动的时候会报告异常。 2.0.0 版本注册的事件监听器,必须保证对于 EventManager 类具有可访问性。 通常 |
| 定义的类和 EventManager 不属于同一个 package , 因此这个类必须是 public 的, 事件处理方法也必须是 public 的。 </p> |
| <ul> |
| <li>定义接口的 Model 使用匿名内部类</li> |
| </ul> |
| <p>在 1.3.0 版本, 使用匿名内部类作为 REST 接口的 Model 是允许的, 但是 2.0.0 版本不允许。 如果采用这样的类型作为接口参数, |
| 启动的时候会报告异常。</p> |
| <ul> |
| <li>其他方面的影响</li> |
| </ul> |
| <p>由于 JDK 11 不允许通过反射破坏封装, 早期通过反射修改 private 字段的值,来规避一些三方软件的 bug, 以及做一些额外 |
| 定制变得不可行, 使用这些特性 JDK 11 暂时只是打印警告, 在 JDK 13 等更高版本会彻底禁止。 因此业务开发的时候, 尽可能 |
| 不要使用破坏封装的特性。 </p> |
| <h2 id="_1">常见问题</h2> |
| <ul> |
| <li>java-chassis运行时依赖于接口定义里面的名字</li> |
| </ul> |
| <p>为了更好的基于swagger对服务进行治理,以及提高客户端代码书写的灵活性,java-chassis要求书写的接口定义代码在编译的时候,带上参数名称信息,否则会报告如下错误:</p> |
| <pre><code>Caused by: java.lang.IllegalStateException: parameter name is not present, method=org.apache.servicecomb.samples.porter.file.api.InternalAccessEndpoint:localAccess |
| solution: |
| change pom.xml, add compiler argument: -parameters, for example: |
| <plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-compiler-plugin</artifactId> |
| <configuration> |
| <compilerArgument>-parameters</compilerArgument> |
| </configuration> |
| </plugin> |
| </code></pre> |
| <p>解决该问题可以通过配置maven compiler plugin, 加上-parameters参数。如果在IDE下面运行,需要设置 build -> java compilers 在编译参数里面增加-parameters。</p> |
| <ul> |
| <li>spring 5变更</li> |
| </ul> |
| <p>cse.bean.xml文件如果采用了classpath查找定义文件</p> |
| <pre><code><beans xmlns="http://www.springframework.org/schema/beans" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" |
| xmlns:util="http://www.springframework.org/schema/util" |
| xmlns:context="http://www.springframework.org/schema/context" |
| xmlns:tx="http://www.springframework.org/schema/tx" |
| xsi:schemaLocation=" |
| http://www.springframework.org/schema/beans classpath:org/springframework/beans/factory/xml/spring-beans-3.0.xsd |
| http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd |
| http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> |
| </code></pre> |
| <p>会报告下面的错误:</p> |
| <pre><code>[main][WARN][org.springframework.beans.factory.xml.XmlBeanDefinitionReader:48] Ignored XML validation warning |
| org.xml.sax.SAXParseException: schema_reference.4: 无法读取方案文档 'classpath:org/springframework/beans/factory/xml/spring-beans-3.0.xsd', 原因为 1) 无法找到文档; 2) 无法读取文档; 3) 文档的根元素不是 <xsd:schema>。 |
| at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203) ~[?:1.8.0_131] |
| at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.warning(ErrorHandlerWrapper.java:99) [?:1.8.0_131] |
| at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:392) [?:1.8.0_131] |
| </code></pre> |
| <p>修改为:</p> |
| <pre><code><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xmlns:context="http://www.springframework.org/schema/context" |
| xsi:schemaLocation=" |
| http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd |
| http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> |
| </code></pre> |
| <ul> |
| <li>SCBEngine使用时机</li> |
| </ul> |
| <p>代码</p> |
| <pre><code>@RestSchema(schemaId = "inspector") |
| @Path("/inspector") |
| public class InspectorEndpoint { |
| private InspectorConfig inspectorConfig; |
| |
| public InspectorEndpoint() { |
| this.inspectorConfig = SCBEngine.getInstance().getPriorityPropertyManager().createConfigObject(InspectorConfig.class); |
| } |
| </code></pre> |
| <pre><code>Caused by: java.lang.NullPointerException |
| at org.apache.servicecomb.core.SCBEngine.<init>(SCBEngine.java:126) |
| at org.apache.servicecomb.core.SCBEngine.getInstance(SCBEngine.java:159) |
| at org.apache.servicecomb.samples.porter.file.api.InspectorEndpoint.<init>(InspectorEndpoint.java:82) |
| at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) |
| at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) |
| at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) |
| at java.lang.reflect.Constructor.newInstance(Constructor.java:423) |
| </code></pre> |
| <p>不能够在bean的初始化里面使用SCBEngine的实例。这个实例业务需要在事件AFTER_REGISTRY等处理函数中使用。</p> |
| <h2 id="_2">编译错误</h2> |
| <p>2.0.0 相对于 1.0.0 升级了大量三方件,包括netty, vert.x, spring, spring boot等,直接引用这些组件的代码可能编译失败。同时还对代码进行了一定重构,有些代码使用了java-chassis未公开接口,使用这些接口可能编译失败。下面是一些常见的问题。下面一些PR的修改可以参考:</p> |
| <ul> |
| <li><a href="https://github.com/apache/servicecomb-java-chassis/pull/1394">升级netty&vertx</a></li> |
| <li><a href="https://github.com/apache/servicecomb-java-chassis/pull/1381">升级jackson</a></li> |
| <li><a href="https://github.com/apache/servicecomb-java-chassis/pull/1415">删除spring 4和spring boot 1的支持</a></li> |
| <li><a href="https://github.com/apache/servicecomb-java-chassis/pull/1439">调整2.x版本spring boot starter名字</a></li> |
| </ul> |
| <p>下面是一些场景的问题:</p> |
| <ul> |
| <li><code>router.routeWithRegex(regex).handler(CookieHandler.create())</code> 提示 CookieHandler deprecated,删除这行代码 |
| 即可,新版本的vert.x已经默认提供了cookie处理。</li> |
| <li>io.vertx.ext.web中的 <code>io.vertx.ext.web.Cookie已过时</code> , 修改 |
| 为 <code>io.vertx.core.http.Cookie</code></li> |
| </ul> |
| <p>2.0.0 一些可能被外部使用的内部接口调整:</p> |
| <ul> |
| <li><code>Invocation</code> 类删除了 <code>getArgs</code> 接口, 替换为 <code>getSwaggerArguments</code> , 同时新增了 <code>getInvocationArguments</code>, |
| 关于这个变更的说明,请参考新特性介绍文章<a href="../features/weak-type-contrast.html">弱类型契约</a>。 </li> |
| <li>删除 <code>DynamicSchemaLoader</code> , 这个类早期版本提供出来是方便注册契约, 最新版本客户端契约发现可以通过服务中心 |
| 完成,不再需要这样的功能。</li> |
| <li><code>CseContext.getInstance().getTransportManager().findTransport(Const.RESTFUL)</code> 修改 |
| 为 <code>SCBEngine.getInstance().getTransportManager().findTransport(Const.RESTFUL)</code></li> |
| <li>测试代码可能使用 <code>CseContext.getInstance().getConsumerProviderManager().setTransport(microserviceName, transport)</code> , 修改 |
| 为 <code>ArchaiusUtils.setProperty("servicecomb.references.transport." + microserviceName, transport);</code></li> |
| </ul> |
| <h2 id="_3">已知缺陷</h2> |
| <ul> |
| <li>2.0.0 版本将 <code>servicecomb.service.registry.registerUrlPrefix</code> 弄丢了。 这个配置项是为一个特殊场景服务的的, |
| 默认值为 false。 在使用 WEB 容器(比如 tomcat) java-chassis的场景下, 如果设置了 context-path, 使用 java-chassis |
| 提供的 RestTemplate 访问服务的时候, 不需要指定 context-path,以保证用户不用关注微服务的部署方式,提供了很大的便利。 |
| 但是有些用户的代码是历史遗留代码改造过来的,期望 URL 包含完整的 context-path。 使用 2.0.0 版本如果存在这个特殊要 |
| 求, 程序会运行错误,访问接口提示 NOT FOUND。这个问题在 2.0.1 修复。 </li> |
| </ul> |
| |
| </div> |
| </div><footer> |
| |
| <hr/> |
| |
| <div role="contentinfo"> |
| <!-- Copyright etc --> |
| </div> |
| |
| Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. |
| </footer> |
| |
| </div> |
| </div> |
| |
| </section> |
| |
| </div> |
| |
| <div class="rst-versions" role="note" aria-label="Versions"> |
| <span class="rst-current-version" data-toggle="rst-current-version"> |
| |
| |
| |
| </span> |
| </div> |
| <script>var base_url = '../..';</script> |
| <script src="../../js/theme_extra.js" defer></script> |
| <script src="../../js/theme.js" defer></script> |
| <script src="../../search/main.js" defer></script> |
| <script defer> |
| window.onload = function () { |
| SphinxRtdTheme.Navigation.enable(true); |
| }; |
| </script> |
| |
| </body> |
| </html> |