SpringBoot---学习笔记

微服务阶段


JavaSE:OOP

MySQL:持久化

HTML+CSS+JS+jQuery+框架:视图,框架不熟练,CSS不好

Javaweb:独立开发MVC三层架构的网站

SSM:框架 简化了开发流程 配置也开始较为复杂

SpringBoot


什么是SpringBoot

Spring Boot基于Spring 开发,Spirng Boot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring 的解决方案,而是和Spring框架紧密结合用于提升Spring 开发者体验的工具。SpringBoot以约定大于配置的核心思想,默认帮我们进行了很多设置,多数Spring Boot应用只需要很少的Spring 配置。同时它集成了大量常用的第三方库配置(例如Redis、MongoDB、Jpa、RabbitMQ、Quartz等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用。

简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包, spring boot整合了所有的框架。

Spring Boot的主要优点:

  • 为所有Spring开发者更快的入门
  • 开箱即用,提供各种默认配置来简化项目配置
  • 内嵌式容器简化Web项目
  • 没有冗余代码生成和XML配置的要求

微服务


什么是微服务

微服务是一种架构风格,它要求我们在开发一个应用的时候,这个应用必须构建成一系列小服务的组合;可以通过http的方式进行互通。要说微服务架构,先得说说过去我们的单体应用架构。

单体应用架构

所谓单体应用架构(all in one)是指,我们将一个应用的中的所有应用服务都封装在一个应用中。

无论是ERP、CRM或是其他什么系统,你都把数据库访问,web访问,等等各个功能放到一个war包内。

  • 这样做的好处是,易于开发和测试;也十分方便部署;当需要扩展时,只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了。
  • 单体应用架构的缺点是,哪怕我要修改一个非常小的地方,我都需要停掉整个服务,重新打包、部署这个应用war包。特别是对于一个大型应用,我们不可能吧所有内容都放在一个应用里面,我们如何维护、如何分工合作都是问题。

微服务架构

all in one的架构方式,我们把所有的功能单元放在一个应用里面。然后我们把整个应用部署到服务器上。如果负载能力不行,我们将整个应用进行水平复制,进行扩展,然后在负载均衡。

所谓微服务架构,就是打破之前all in one的架构方式,把每个功能元素独立出来。把独立出来的功能元素的动态组合,需要的功能元素才去拿来组合,需要多一些时可以整合多个功能元素。所以微服务架构是对功能元素进行复制,而没有对整个应用进行复制。

这样做的好处是:

1.节省了调用资源。

2.每个功能元素的服务都是一个可替换的、可独立升级的软件代码。

如何构建微服务

一个大型系统的微服务架构,就像一个复杂交织的神经网络,每一个神经元就是一个功能元素,它们各自完成自己的功能,然后通过http相互请求调用。比如一个电商系统,查缓存、连数据库、浏览页面、结账、支付等服务都是一个个独立的功能服务,都被微化了,它们作为一个个微服务共同构建了一个庞大的系统。如果修改其中的一个功能,只需要更新升级其中一个功能服务单元即可。

但是这种庞大的系统架构给部署和运维带来很大的难度。于是,spring为我们带来了构建大型分布式微服务的全套、全程产品:

  • 构建一个个功能独立的微服务应用单元,可以使用springboot,可以帮我们快速构建一个应用;
  • 大型分布式网络服务的调用,这部分由spring cloud来完成,实现分布式;
  • 在分布式中间,进行流式数据计算、批处理,我们有spring cloud data flow。
  • spring为我们想清楚了整个从开始构建应用到大型分布式应用全流程方案。

SpringBoot原理初探


自动配置

pom.xml

  • spring-boot-dependencies在父工程中存放核心依赖
  • 在写或者引入一些SpringBoot依赖的时候,不需要指定版本,就因为这些版本仓库

启动器

  •         
                org.springframework.boot
                spring-boot-starter
            
  • 启动器:说白了就是SpringBoot的启动场景
  • 比如spring-boot-starter-web,它会自动导入web环境下的依赖
  • spring boot会将所有的功能场景,变成一个个启动器
  • 如果要使用什么功能,就只需要找到对应的启动器就可以

主程序

  • //@SpringBootApplication:标注这个类是一个spring boot的应用 启动类下的所有被导入
    @SpringBootApplication
    public class HelloworldApplication {
    
        public static void main(String[] args) {
            //将spring boot启动起来 通过反射
            SpringApplication.run(HelloworldApplication.class, args);
        }
    
    }
  • 注解
    • @SpringBootConfiguration:springboot的配置
          @Configuration:spring配置类
              @Component:说明这也是一个spring的组件
      
      @EnableAutoConfiguration:自动配置
          @AutoConfigurationPackage:自动配置包
              @Import({Registrar.class}):自动配置 包注册
          @Import({AutoConfigurationImportSelector.class}):自动导入选择
               
      
      //获取所有配置
      List configurations = this.getCandidateConfigurations(annotationMetadata, attributes); 
      
      //获取候选的配置
          protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
              List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
              Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
              return configurations;
          }
      
          protected Class getSpringFactoriesLoaderFactoryClass() {
              return EnableAutoConfiguration.class;
          }
      
      
       META-INF/spring.factories:自动配置的核心文件

流程图:自动配置原理分析 | ProcessOn免费在线作图,在线流程图,在线思维导图

结论:SpringBoot所有自动配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器,有了启动器,自动装配就会生效,就配置成功。

  • springboot在启动的时候,从类路径下/META-INF/ spring.factories获取指定的值
  • 将这些自动配置的类导入容器,自动配置就会生效,帮我进行自动配置!
  • 以前我们需要自动配置的东西,现在springboot帮我们做了!
  • 整合javaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure-2.2.0.RELEASE.jar这个包下
  • 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器;
  • 容器中也会存在非常多的xxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景需要的所有组件;并自动配置,@Configuration , JavaConfig !
  • 有了自动配置类,免去了我们手动编写配置文件的工作!

Run

//@SpringBootApplication:标注这个类是一个spring boot的应用
@SpringBootApplication
public class HelloworldApplication {

    public static void main(String[] args) {
        //将spring boot启动起来 通过反射
        SpringApplication.run(HelloworldApplication.class, args);
    }

}

最初以为就是运行了一个main方法,没想到却开启了一个服务;

SpringApplication.run分析

分析该方法主要分两部分,一部分是SpringApplication的实例化,二是run方法的执行;

SpringApplication

这个类主要做了以下四件事情

  1. 推断应用的类型是普通的项目还是Web项目
  2. 查找并加载所有可用初始化器,设置到initializers属性中
  3. 找出所有的应用程序监听器,设置到listeners属性中
  4. 推断并设置main方法的定义类,找到运行的主类

关于SpringBoot,谈谈你的理解:

  • 自动装配
  • run()

SpringBoot配置


配置文件

SpringBoot使用一个全局的配置文件,配置文件名称是固定的.

  • application.properties
    • 语法结构: key=value.
  • application.yml
    • 语法结构: key:空格value

配置文件的作用︰修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了;

yml

可以直接给实体类赋值

自动配置原理

application.yml和spring.factories的联系

//表示这是一个配置类
@Configuration(proxyBeanMethods = false)

//自动配置属性: HttpProperties
@EnableConfigurationProperties

//Spring的底层注解: 根据不同的条件 来判断当前配置或者类是否生效
@ConditionalOnWebApplicatioin(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding",value = "enabled",matchIfMissing = true)

精髓:

1) 、SpringBoot启动会加载大量的自动配置类

2)、我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;

3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)

4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;

xxxxAutoConfigurartion:自动配置类;给容器中添加组件

xxxxProperties:封装配置文件中相关属性;

SpringBoot Web开发


总结:

  1. 在springboot中,可以使用一下方式处理静态资源
    1. webjars        localhost:8080/webjars/
    2. public static  /** resources           直接映射到localhost:8080/
  2. 优先级: resources>static(默认)>public

首页如何定制

factory.ico

模板引擎

thymeleaf

结论:只要需要使用thymeleaf,只需要导入对应的依赖就可以了,将html放在templates目录下即可。

public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";

自定义视图解析器

//如果 你想diy一些定制化的功能 只要写这个组件 然后将它交给spring boot ,spring boot就会帮我们自动装配
//扩展 springmvc
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    // public interface ViewResolver 实现了视图解析器接口的类 我们就可以把它看做视图解析器
    @Bean
    public ViewResolver myViewResolver(){
        return new MyViewResolver();
    }

    //自定义一个自己的视图解析器MyViewResolver
    private class MyViewResolver implements ViewResolver {
        @Override
        public View resolveViewName(String viewName, Locale locale) throws Exception {
            return null;
        }
    }
}

在springboot中,有非常多的XXX Configuration帮助我们进行扩展配置,只要看见这个,就需要注意。

springboot - 员工管理练习项目

  1. 首页配置:
    1. 注意点,所有页面的静态资源都需要使用thymeleaf接管
    2. url:@{}
  2. 页面国际化:
    1. 我们需要配置i8n文件
    2. 如果需要在项目中进行按钮自动切换,需要自定义一个组件LovaleResolver
    3. 记得将自己写的组件配置到spring容器@Bean
    4. #{}
  3. 登录+拦截器
  4. 员工列表展示
    1. 提取公共页面
      1. th:fragment=" "
      2. th:replace=" "
      3. 如果要传递参数,可以直接使用()传参,接受判断即可
    2. 列表循环展示
  5. 添加员工
    1. 按钮提交
    2. 跳转到添加页面
    3. 添加员工成功
    4. 返回首页
  6. CRUD
  7. 404页面

前端:

  • 模板:别人写好的,我们拿来就用根据需要改
  • 框架:组件:自己手动组合拼接 Bootstrap,Layui,semantic-ui
    • 栅格系统
    • 导航栏
    • 侧边栏
    • 表单

Data


Druid

@Configuration
public class DruidConfig {

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druidDataSource(){
        return new DruidDataSource();
    }

    //后台监控:web.xml  死代码 直接使用
    //因为Springboot内置了servlet容器 所以没有web.xml
    @Bean
    public ServletRegistrationBean statViewServlet(){
        ServletRegistrationBean bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/**");

        //后台需要有人登录 账号密码配置
        HashMap initParameters = new HashMap<>();
        //增加配置
        initParameters.put("loginUsername","admin"); // 登录key是固定的 loginUsername loginPassword
        initParameters.put("loginPassword","123456");

        //允许谁可以访问
        initParameters.put("allow","localhost");

        //禁止谁能访问

        bean.setInitParameters(initParameters); //设置初始化参数
        return bean;
    }

    //filter
    public FilterRegistrationBean webStatFilter(){
        FilterRegistrationBean bean = new FilterRegistrationBean();

        bean.setFilter(new WebStatFilter());

        //可以过滤哪些请求
        HashMap initParameters = new HashMap<>();

        //这些东西不进行统计
        initParameters.put("exclusions","*.js,*.css,/druid/*");

        return bean;
    }
}

数据源配置

    type: com.alibaba.druid.pool.DruidDataSource

    #SpringBoot默认是不注入这些属性的 需要自己绑定
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuert: SELECT 1 FROM DUAL
    testwhileIdle: false
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #配置监控统计拦截的filters stat:监控统计 log4j: 日志记录 wall:防御sql注入
    #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #则导入log4j 依赖即可 Maven地址: https://mvnrepository.com/artifact/Log4j/log4j
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

Mybatis


整合包

mybatis-spring-boot-starter

  1. 导入包
  2. 配置文件
  3. mybatis配置
  4. 编写sql
  5. service层调用dao层
  6. controller调用service

SpringSecurity(安全)


在web开发中,安全第一位。过滤器,拦截器

非功能性需求

做网站:安全应该在什么时候考虑?设计之初

  • 漏洞,隐私泄露
  • 架构一旦确定,不好修改

Shiro


什么是Shiro?

  •  Apache Shiro是一个Java的安全(权限)框架。
  • Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境。
  • Shiro可以完成,认证,授权,加密,会话管理,Web集成,缓存等。

有哪些功能?

  • Authentication:身份认证、登录,验证用户是不是拥有相应的身份;
  • Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限.即判断用户能否进行什么操作,如:验证某个用户是否拥有某个角色,或者细粒度的验证某个用户对某个资源是否具有某个权限!
  • Session Manager:会话管理,即用户登录后就是第一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通的JavaSE环境,也可以是Web环境;
  • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库中,而不是明文存储;
  • web Support: Web支持,可以非常容易的集成到Web环境;
  • Caching: 缓存,比如用户登录后,其用户信息,拥有的角色、权限不必每次去查,这样可以提高效率·Concurrency: Shiro支持多线程应用的并发验证,即,如在一个线程中开启另一个线程,能把权限自动的传播过去
  • Testing:提供测试支持;
  • Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
  • Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了

 Shiro架构(外部)

从外部看Shiro,即从应用程序角度来观察如何使用shiro完成工作:

SpringBoot---学习笔记_第1张图片

  • subject: 应用代码直接交互的对象是Subject,也就是说Shiro的对外API核心就是Subject,Subject代表了当前的用户,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等,与Subject的所有交互都会委托给SecurityManager; Subject其实是一个门面,SecurityManageer才是实际的执行者
  • SecurityManager:安全管理器,即所有与安全有关的操作都会与SercurityManager交互,并且它管理着所有的Subject,可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVC的DispatcherServlet的角色

Swagger


学习目标:

  • 了解Swagger的作用和概念
  • 了解前后端分离
  • 在SpringBoot中集成Swagger

Swagger简介

前后端分离

Vue + SpringBoot

后端时代:前端只用管理静态页面;HTML==》后端,模板引擎JSP

前后端分离时代:

  • 后端:后端控制层,服务层,数据访问层
  • 前端:前端控制层,视图层
    • 伪造后端数据,json。已经存在了,不需要后端,前端依旧可以跑起来
  • 前后端如何交互?API接口
  • 前后端相对独立,松耦合;
  • 前后端甚至可以部署在不同的服务器上;

产生一个问题:

  • 前后端集成联调,前端人员和后端人员无法做到,及时协商,尽早解决,最终导致问题集中爆发;

解决方案:

  • 首先制定schema,实时更新最新的API,降低集成风险;
  • 早些年:制定Word文档;
  • 前后端分离:
    • 前端测试后端接口:postman
    • 后端提供接口,需要实时更新最新的消息及改动

Swagger

  • 号称世界最流行的API框架;
  • RestFul API 文档在线自动生成工具   API文档与API定义同步更新
  • 直接运行,可以在线测试API接口;
  • 支持多种语言:Java,PHP...

官网:API Documentation & Design Tools for Teams | Swagger

在项目中使用Swagger需要Springfox;

  • swagger2
  • ui

SpringBoot集成Swagger

  1. 新建一个springboot-web项目
  2. 导入相关依赖
            
                io.springfox
                springfox-swagger2
                3.0.0
            
            
                io.springfox
                springfox-swagger-ui
                3.0.0
            
  3. 编写一个Hello工程
  4. 配置Swagger ==》 Config
    @Configuration
    @EnableSwagger2 //开启Swagger2
    public class SwaggerConfig {
        
    }
    
  5. 测试运行,http://localhost:8080/swagger-ui.html

配置Swagger

Swagger的bean实例Docket;

@Configuration
@EnableSwagger2 //开启Swagger2
public class SwaggerConfig {

    //配置了Swagger的Docket的bean实例
    @Bean
    public Docket docket(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo());
    }

    //配置Swagger信息 ==》 apiInfo
    private ApiInfo apiInfo(){
        //作者信息
        Contact contact = new Contact("hzx","http://localhost:8080","[email protected]");
        return new ApiInfo(
                "hzx的SwaggerAPI文档",
                "即使再小的帆也能远航",
                "1.0",
                "http://localhost:8080",
                contact,
                "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList());

    }

}

Swagger配置扫描接口

Docket.select()

    //配置了Swagger的Docket的bean实例
    @Bean
    public Docket docket(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                //RequestHandlerSelectors配置要扫描接口的方式
                //basePackage指定要扫描的包
                //any() 扫描全部
                //none 都不扫描
                //withclassAnnotation 扫描类上的注解  参数是一个注解的反射对象
                //withMethodAnnotation 扫描方法上的注解
                .apis(RequestHandlerSelectors.basePackage("com.hzx.controller"))
                //paths 过滤什么路径
                .paths(PathSelectors.ant("/hzx/**"))
                .build();
    }

配置是否启动Swagger

docket里有enable 设置为false 不启动

我只希望我的Swagger在生产环境中使用,在发布的时候不适用?

  • 判断是否是生产环境 flag = false
  • 注入enable(flag)
 @Bean
    public Docket docket(Environment environment){

        //设置要显示的Swagger环境
        Profiles profiles = Profiles.of("dev","test");
        //获取项目环境 通过environment.acceptsProfiles判断环境
        boolean b = environment.acceptsProfiles(profiles);

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                //enable是否启动Swagger 如果为false 则Swagger不能在浏览器中访问
                .enable(b)
                .select()
                //RequestHandlerSelectors配置要扫描接口的方式
                //basePackage指定要扫描的包
                //any() 扫描全部
                //none 都不扫描
                //withclassAnnotation 扫描类上的注解  参数是一个注解的反射对象
                //withMethodAnnotation 扫描方法上的注解
                .apis(RequestHandlerSelectors.basePackage("com.hzx.controller"))
                //paths 过滤什么路径
//                .paths(PathSelectors.ant("/hzx/**"))
                .build();
    }

配置API文档的分组

.groupName("hzx")

如何配置多个分组?多个Docket实例即可

    @Bean
    public Docket docket1(){
        return  new Docket(DocumentationType.SWAGGER_2).groupName("a1");
    }
    @Bean
    public Docket docket2(){
        return  new Docket(DocumentationType.SWAGGER_2).groupName("a2");
    }
    @Bean
    public Docket docket3(){
        return  new Docket(DocumentationType.SWAGGER_2).groupName("a3");
    }

实体类配置

//@Api(注释)
@ApiModel("用户实体类")
public class User {

    @ApiModelProperty("用户名")
    public String username;
    @ApiModelProperty("密码")
    public String password;
}

任务


异步任务~@Async

定时任务~@Scheduled

邮件发送~

    public void sendMail() throws MessagingException {
        MimeMessage mimeMessage = mailSender.createMimeMessage();

        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);

        mimeMessageHelper.setSubject("你好啊");
        mimeMessageHelper.setText("

1111

",true); mimeMessageHelper.addAttachment("1.jpg",new File("")); mimeMessageHelper.setTo("[email protected]"); mimeMessageHelper.setFrom("[email protected]"); mailSender.send(mimeMessage); }

分布式Dubbo+Zookeeper


什么是分布式系统?

在《分布式系统原理与范型》一书中有如下定义:“分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统”;

分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据。

分布式系统(distributed system)是建立在网络之上的软件系统。

首先需要明确的是,只有当单个节点的处理能力无法满足日益增长的计算、存储任务的时候,且硬件的提升(加内存、加磁盘、使用更好的CPU)高昂到得不偿失的时候,应用程序也不能进一步优化的时候,我们才需要考虑分布式系统。因为,分布式系统要解决的问题本身就是和单机系统一样的,而由于分布式系统多节点、通过网络通信的拓扑结构,会引入很多单机系统没有的问题,为了解决这些问题又会引入更多的机制、协议,带来更多的问题。。。

RPC


什么是RPC?

RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。

也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。为什么要用RPC呢?就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如不同的系统间的通讯,甚至不同的组织间的通讯,由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用。RPC就是要像调用本地的函数一样去调远程函数;

RPC两个核心模块:通信、序列化

Dubbo


什么是dubbo?

Apache Dubbo |'dxbeu|是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

步骤:

前提:zookeeper服务已开启

  1. 提供者提供服务
    1. 导入依赖
    2. 配置注册中心的地址,以及服务发现名,和要扫描的包
    3. 在想要被注册的服务上面 增加一个注解@Service
  2. 消费者如何消费
    1. 导入依赖
    2. 配置注册中心的地址,配置自己的服务名
    3. 从远程注入服务@Reference

学习Java关注狂神说

你可能感兴趣的:(java,spring,后端)