背景

项目中要把spring-boot 2.3.2版本升级到spring boot 2.6.2版本。 如果要升级spring boot 到2.6.2. 就必须要把spring cloud升级到2021.0.x版本(具体可以看最下面参考资料部分)。但是Spring cloud 再2020.0版本的时候已经移除了ribbon, Hystrix,Zuul.. 等等,而我们的项目又再用这些东西。 Gateway是Spring cloud 官方给出的替换方案。到底能不能用OpenFeign或Zuul了?下面是我再尝试的过程中遇到的一些问题。

要升级到的版本

Lib Vresion
spring-cloud-starter-gateway 3.1.0
spring-cloud-dependencies 2021.0.0
spring-cloud-starter-netflix-zuul 2.2.6.RELEASE
spring-cloud-starter-openfeign 3.1.0

1. 单用Zuul做路由时的问题

Lib Vresion
spring-cloud-dependencies 2021.0.0
spring-cloud-starter-netflix-zuul 2.2.6.RELEASE

1.1 问题 java.lang.NoSuchMethodError: org.springframework.boot.web.servlet.error.ErrorController.getErrorPath()Ljava/lang/String;
    at

错误信息

Caused by: java.lang.NoSuchMethodError: org.springframework.boot.web.servlet.error.ErrorController.getErrorPath()Ljava/lang/String;at org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping.lookupHandler(ZuulHandlerMapping.java:87) ~[spring-cloud-netflix-zuul-2.2.10.RELEASE.jar:2.2.10.RELEASE]at org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.getHandlerInternal(AbstractUrlHandlerMapping.java:152) ~[spring-webmvc-5.3.14.jar:5.3.14]at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:498) ~[spring-webmvc-5.3.14.jar:5.3.14]at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1261) ~[spring-webmvc-5.3.14.jar:5.3.14]at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1043) ~[spring-webmvc-5.3.14.jar:5.3.14]... 38 common frames omitted

解决方法:

加一个类就可以了。

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.CallbackFilter;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.cloud.netflix.zuul.web.ZuulController;
import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** Fix for Zuul configuration with Spring Boot 2.5.x + Zuul - "NoSuchMethodError: ErrorController.getErrorPath()":*/
@Configuration
public class ZuulConfiguration {/*** The path returned by ErrorController.getErrorPath() with Spring Boot < 2.5* (and no longer available on Spring Boot >= 2.5).*/private static final String ERROR_PATH = "/error";private static final String METHOD = "lookupHandler";/*** Constructs a new bean post-processor for Zuul.** @param routeLocator    the route locator.* @param zuulController  the Zuul controller.* @param errorController the error controller.* @return the new bean post-processor.*/@Beanpublic ZuulPostProcessor zuulPostProcessor(@Autowired RouteLocator routeLocator,@Autowired ZuulController zuulController,@Autowired(required = false) ErrorController errorController) {System.out.println("ZuulPostProcessor....");return new ZuulPostProcessor(routeLocator, zuulController, errorController);}private enum LookupHandlerCallbackFilter implements CallbackFilter {INSTANCE;@Overridepublic int accept(Method method) {if (METHOD.equals(method.getName())) {return 0;}return 1;}}private enum LookupHandlerMethodInterceptor implements MethodInterceptor {INSTANCE;@Overridepublic Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {if (ERROR_PATH.equals(args[0])) {// by entering this branch we avoid the ZuulHandlerMapping.lookupHandler method to trigger the // NoSuchMethodError return null;}return methodProxy.invokeSuper(target, args);}}private static final class ZuulPostProcessor implements BeanPostProcessor {private final RouteLocator routeLocator;private final ZuulController zuulController;private final boolean hasErrorController;ZuulPostProcessor(RouteLocator routeLocator, ZuulController zuulController, ErrorController errorController) {this.routeLocator = routeLocator;this.zuulController = zuulController;this.hasErrorController = (errorController != null);}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (hasErrorController && (bean instanceof ZuulHandlerMapping)) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(ZuulHandlerMapping.class);enhancer.setCallbackFilter(LookupHandlerCallbackFilter.INSTANCE); // only for lookupHandlerenhancer.setCallbacks(new Callback[] {LookupHandlerMethodInterceptor.INSTANCE, NoOp.INSTANCE});Constructor<?> ctor = ZuulHandlerMapping.class.getConstructors()[0];return enhancer.create(ctor.getParameterTypes(), new Object[] {routeLocator, zuulController});}return bean;}}
}

参考资料

java - NoSuchMethodError: org.springframework.boot.web.servlet.error.ErrorController.getErrorPath() in latest spring-cloud-starter-netflix-zuul - Stack Overflow

1.2 问题 com.netflix.client.ClientException: Load balancer does not have available server for client: spring-cloud-client2

相关代码

zuul.routes.test.path=/spring-cloud-client2/**
zuul.routes.test.serviceId=spring-cloud-client2

如果你想用Eureka取其它组件的host和port是。会报下面错误

Caused by: com.netflix.client.ClientException: Load balancer does not have available server for client: spring-cloud-client2at com.netflix.loadbalancer.LoadBalancerContext.getServerFromLoadBalancer(LoadBalancerContext.java:483) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:184) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]at rx.Observable.unsafeSubscribe(Observable.java:10327) ~[rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94) ~[rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42) ~[rxjava-1.3.8.jar:1.3.8]at rx.Observable.unsafeSubscribe(Observable.java:10327) ~[rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1.call(OperatorRetryWithPredicate.java:127) ~[rxjava-1.3.8.jar:1.3.8]at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.enqueue(TrampolineScheduler.java:73) ~[rxjava-1.3.8.jar:1.3.8]at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.schedule(TrampolineScheduler.java:52) ~[rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:79) ~[rxjava-1.3.8.jar:1.3.8]at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:45) ~[rxjava-1.3.8.jar:1.3.8]

原因:

spring-cloud-netfix-eureka-client已经把Ribbon利用Eureka取注册在其上的信息这部分代码已经移除了。所有Zuul只能利用静态信息了。

原来是利用DomainExtractingServerList类取Eureka里注册信息。

org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList

现在是用ConfigurationBasedServerList只能读配置文件的信息。

com.netflix.loadbalancer.ConfigurationBasedServerList

解决方法:

1. 加下面配置类

@RibbonClients(defaultConfiguration = RibbonEurekaClientConfig.class)

2. 创建下面配置类


import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Bean;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AvailabilityFilteringRule;
import com.netflix.loadbalancer.DummyPing;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;public class RibbonEurekaClientConfig {@Beanpublic IPing ribbonPing(IClientConfig config) {return new DummyPing();}@Beanpublic IRule ribbonRule(IClientConfig config) {return new AvailabilityFilteringRule();}@AutowiredDiscoveryClient discoveryClient;@Beanpublic ServerList<Server> getServerList(IClientConfig config) {return new ServerList<Server>() {@Overridepublic List<Server> getInitialListOfServers() {return new ArrayList<>();}@Overridepublic List<Server> getUpdatedListOfServers() {List<Server> serverList = new ArrayList<>();List<ServiceInstance> list = discoveryClient.getInstances(config.getClientName());for (ServiceInstance instance : list) {serverList.add(new Server(instance.getHost(), instance.getPort()));}return serverList;}};}
}

参考资料

microservices - Zuul Forwarding error, Load balancer does not have available server for client - Stack Overflow

2.  Zuul 与OpenFeign 一起使用的问题

错误信息


java.lang.AbstractMethodError: org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.choose(Ljava/lang/String;Lorg/springframework/cloud/client/loadbalancer/Request;)Lorg/springframework/cloud/client/ServiceInstance;at org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient.execute(FeignBlockingLoadBalancerClient.java:97) ~[spring-cloud-openfeign-core-3.1.0.jar:3.1.0]at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:119) ~[feign-core-11.7.jar:na]at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89) ~[feign-core-11.7.jar:na]at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100) ~[feign-core-11.7.jar:na]at com.sun.proxy.$Proxy126.test1(Unknown Source) ~[na:na]at com.spring_cloud_client1.CarController.test12(CarController.java:28) ~[classes/:na]at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_51]at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_51]at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_51]at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_51]at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.14.jar:5.3.14]at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.14.jar:5.3.14]at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.14.jar:5.3.14]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.14.jar:5.3.14]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.14.jar:5.3.14]at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.14.jar:5.3.14]at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.14.jar:5.3.14]at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.14.jar:5.3.14]at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.14.jar:5.3.14]at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.14.jar:5.3.14]at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.56.jar:4.0.FR]at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.14.jar:5.3.14]at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.56.jar:4.0.FR]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.56.jar:9.0.56]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56]at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.56.jar:9.0.56]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.56.jar:9.0.56]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56]at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.14.jar:5.3.14]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.14.jar:5.3.14]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.56.jar:9.0.56]at 

原因:

OpenFeign依赖spring-cloud-starter-loadbalancer做负载均衡,之前是用Ribbon的。如果加了spring-cloud-starter-netflix-zuul后,zuul依赖了Ribbon做负载均衡。

LoadBalancerClient 有两个RibbonLoadBalancerClient和BlockingLoadBalancerClient类。结果OpenFeigin用RibbonLoadBalancerClient使用报错。

如果单用OpenFeign是不会有这个问题的。

总结:

OpenFeigin 用BlockingLoadBalancerClient, 但是Zuul用RibbonLoadBalancerClient。 但是这两类继承同一个类LoadBalancerClient而且只能实例化一个。

public class BlockingLoadBalancerClientAutoConfiguration {@Bean@ConditionalOnBean(LoadBalancerClientFactory.class)@ConditionalOnMissingBeanpublic LoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {return new BlockingLoadBalancerClient(loadBalancerClientFactory);}
public class RibbonAutoConfiguration {...@Bean@ConditionalOnMissingBean(LoadBalancerClient.class)public LoadBalancerClient loadBalancerClient() {return new RibbonLoadBalancerClient(springClientFactory());}

解决方法:

   @Beanpublic LoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {return new BlockingLoadBalancerClient(loadBalancerClientFactory);}

3. OpenFeign与Gateway同时用的问题

Lib Vresion
spring-cloud-starter-gateway 3.1.0
spring-cloud-dependencies 2021.0.0
spring-cloud-starter-openfeign 3.1.0

错误信息


java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83) ~[reactor-core-3.4.13.jar:3.4.13]Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):*__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]*__checkpoint ⇢ HTTP GET "/test1-2" [ExceptionHandlingWebHandler]
Original Stack Trace:at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83) ~[reactor-core-3.4.13.jar:3.4.13]at reactor.core.publisher.Mono.block(Mono.java:1707) ~[reactor-core-3.4.13.jar:3.4.13]at org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.choose(

原因:

spring-cloud-starter-gateway 依赖的是 spring-boot-starter-webflux, 但是 OpenFeign 用的是spring-boot-starter-web。

spring-boot-starter-webflux和spring-boot-starter-web 二者只能选一。如果选了spring-boot-starter-webflux。就报上面的错误。

如果你选了spring-boot-starter-web。 那么就下面错误

Description:Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway.Action:Please set spring.main.web-application-type=reactive or remove spring-boot-starter-web dependency.

解决方法:

只能把spring-cloud-starter-gateway分到一个独立的spirng-boot项目了。如果要做路由,就用这个独立的项目

4. 参考资料

4.1. Spring boot 与spring cloud 对应匹配版本

Spring Cloud

Spring cloudTrain

Spring Boot Version

2021.0.x aka Jubilee

2.6.x

2020.0.x aka Ilford

2.4.x, 2.5.x (Starting with 2020.0.3)

Hoxton

2.2.x, 2.3.x (Starting with SR5)

Greenwich

2.1.x

Finchley

2.0.x

Edgware

1.5.x

Dalston

1.5.x

Table 1. Release train Spring Boot compatibility

4.2. Spring cloud 2020.0版本的release Notes

https://github.com/spring-cloud/spring-cloud-release/wiki/Spring-Cloud-2020.0-Release-Notes

Breaking changes

  • As announced, the following modules have been removed from spring-cloud-netflix:

    • spring-cloud-netflix-archaius
    • spring-cloud-netflix-concurrency-limits
    • spring-cloud-netflix-core
    • spring-cloud-netflix-dependencies
    • spring-cloud-netflix-hystrix
    • spring-cloud-netflix-hystrix-contract
    • spring-cloud-netflix-hystrix-dashboard
    • spring-cloud-netflix-hystrix-stream
    • spring-cloud-netflix-ribbon
    • spring-cloud-netflix-sidecar
    • spring-cloud-netflix-turbine
    • spring-cloud-netflix-turbine-stream
    • spring-cloud-netflix-zuul
    • spring-cloud-starter-netflix-archaius
    • spring-cloud-starter-netflix-hystrix
    • spring-cloud-starter-netflix-hystrix-dashboard
    • spring-cloud-starter-netflix-ribbon
    • spring-cloud-starter-netflix-turbine
    • spring-cloud-starter-netflix-turbine-stream
    • spring-cloud-starter-netflix-zuul
    • Support for ribbon, hystrix and zuul was removed across the release train projects.

4.3. Spring cloud 官方对于Hystrix,Riboon, zuul和Archaius给出的替换方案

Spring Cloud Greenwich.RC1 available now

Replacements

We recommend the following as replacements for the functionality provided by these modules.

Current Replacement
Hystrix Resilience4j
Hystrix Dashboard / Turbine Micrometer + Monitoring System
Ribbon Spring Cloud Loadbalancer
Zuul 1 Spring Cloud Gateway
Archaius 1 Spring Boot external config + Spring Cloud Config

Look for a future blog post on Spring Cloud Loadbalancer and integration with a new Netflix project Concurrency Limits.

OpenFeign, Zuul, Gateway相互不兼容的问题总结相关推荐

  1. springboot+openFeign+nacos+gateway开发实战

    前面说了openFeign整合nacos进行服务之间的调用,本文来说下springboot+openFeign+nacos+gateway开发实战.说下服务网关gateway实战相关的内容. 文章目录 ...

  2. Zuul Gateway 网关

    当controller变得很多,那么就需要网关进行路由. 拦截请求,分析请求,定位到具体的controller. 当然了 zuul也可以用来权限鉴定... 其实都是框架都是套路,都是为了解决高并发.

  3. 网关 Gateway

    1 Spring Cloud Gateway 能做什么? 路由寻址(主要功能) 负载均衡 限流 鉴权 2 Gateway VS Zuul Gateway Zuul 1.x Zuul 2.x 靠谱性 官 ...

  4. Spring Cloud(八)Zuul路由网关

    文章目录 1 概述 1.1 什么是Zuul 1.2 为什么要建造Zuul 1.3 Zuul有哪些功能 1.4 理解 2 Zuul路由功能 2.1 创建zuul服务 2.2 测试 2.3 路由访问映射规 ...

  5. 一到两年工作经验的看完这些面试轻松拿offer

    Java基础面试题 1.面向对象的特征有哪些方面 面向对象的特征主要有以下几个方面: 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪些属性和行为 ...

  6. 尚硅谷-SpringCloud

    尚硅谷SpringCloud框架开发教程(SpringCloudAlibaba微服务分布式架构丨Spring Cloud) 1.是什么:Spring Cloud是一系列框架的有序集合 2.版本选型:S ...

  7. SpringCloud知识概括

    SpringCloud知识概括 SpringCloud简介 Eureka Zookeeper Consul Ribbon OpenFeign Hystrix Gateway Config Bus St ...

  8. SpringCloud【面试题】

    目录 什么是SpringCloud? SpringCloud常用组件 什么是Eureka? Eureka与Nacos的区别? 如何避免Eureka注册中心挂掉? Eureka的工作原理 Spring ...

  9. 大淘宝服务端技术干货沉淀和总结

    网络基础 TCP三次握手 三次握手过程 客户端--发送带有SYN标志的数据包--服务端 一次握手 Client进入syn_sent状态 服务端--发送带有SYN/ACK标志的数据包--客户端 二次握手 ...

最新文章

  1. swif 在字符串中查找特定字符索引以及改变字符串的指定位置的颜色 字体大小
  2. 用go语言制作读取excel模板批量生成表格工具
  3. Git与Repo入门
  4. SAP_SD_客户退货需要做哪些处理
  5. JQuery Tips
  6. python类2继承-抽象-多态
  7. IDEA 搭建Java WEB 开发环境
  8. 水土不服?谈一谈机器学习在金融风控实践经验
  9. java常用算法_五分钟记住Java常用的八种排序算法与代码实现
  10. 数据挖掘之Apriori算法详解和Python实现代码分享_python
  11. 自己动手写操作系统——开发环境搭建
  12. python+selenium+autoit实现自动百度识图
  13. lol刷金币python脚本_用Python写王者荣耀刷金币脚本
  14. 凸优化第一【凸集与凸优化简介】
  15. db4o官方停止支持及面向对象数据库的一些感想
  16. 《江南style》影射的经济style
  17. OCR文本检测模型—pixel_link
  18. 区域惯性矩matlab,图示截面图形对形心轴z的惯性矩Iz= 。【图片
  19. 拳王虚拟项目公社:普通人是怎么废掉的?
  20. 『跟着雨哥学AI』系列之七:趣味案例——动手制作专属证件照

热门文章

  1. 谷歌帮助开发人员面向教育应用
  2. 十四个方法提高博客的页面访问量
  3. Android深入浅出系列之实例应用—弹出消息Toast对象的使用纯文本方式(一)
  4. Visio中如何画正弦波
  5. windows2003 iis 配置 php
  6. Nginx配置HTTP2.0
  7. TypeScript入门教程 之 为什么使用TypeScript
  8. matlab中-psi_建议收藏 | 生物信息学中的可变剪切,这些内容你了解吗?
  9. 前端技术基础(一):浏览器相关
  10. Spring框架声明式事务管理