zoukankan      html  css  js  c++  java
  • SpringBoot+SpringCloud 笔记

    1. SpringBoot总结 使用Typora打开https://pan.baidu.com/s/1tXS45j6ooXpnzhy1Zp78Gw 提取码: c8fi

    2. SpringCloud总结 使用XMind打开https://pan.baidu.com/s/1yDeZ9bhZIuBTQIipyIfzqw 提取码: batn

      • SpringBoot默认读取主配置文件
        • application.properties
        • application.yml
      • SpringBoot的四种属性注入
        1. @Autowired注入
        2. 构造方法注入
        3. @Bean方法形参注入
        4. 直接在@Bean方法上使用@ConfigurationProperties(prefix="前缀名")
      • SpringBoot注解
        1. @RestController 包括@Controller+@ResponseBody
        2. @EnableAutoConfiguration 开启SpringBoot自动配置
        3. @ComponentScan 组件扫描 类似于 扫描当前所在包以及子包
        4. @SpringBootApplication 包括 @EnableAutoConfiguration+@ComponentScan+@SpringBootConfiguration
        5. @SpringBootConfiguration SpringBoot配置
        6. @Configuration 标注是一个配置类 相当于xml配置文件
        7. @PropertiesSource 指定一个资源文件 @PropertySource("classpath:jdbc.properties")
        8. @Bean 把方法的返回值注入到Spring容器
        9. @Value 注入指定属性值 需要有setter
        10. @ConfigurationProperties 指定配置文件 @ConfigurationProperties(prefix = "前缀名")
        11. @EnableConfigurationProperties 开启配置 @EnableConfigurationProperties(JdbcProperties.class)
    3. 之前的架构

      • Tomcat(前台,后台,用户管理,订单管理,购物车管理...)
        1. 单点故障(一台服务器挂了,全部挂,全部访问不了)
        2. 并发数低(不能实现高并发)
        3. 代码耦合度高,不方便优化(你调用我,我调用你,)
        4. 不方便扩展(要么都扩展,要么都不扩展)
      • 好处:维护简单
    4. SpringBoot

      • 整合springMVC
        1. 修改端口(server.port=8081)
        2. 访问静态资源("classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/")
        3. springboot的拦截器
          1. 创建类MyInterceptor 实现 HandlerInterceptor接口
          2. 并且在MyInterceptor类上配置@Component
          3. 重写方法preHandle(前置方法),postHandle(后置方法),afterCompletion(完成方法)
          4. preHandle返回false拦截,返回true放行,return false开启拦截,return true关闭拦截
          5. 创建类WebWvcConfiguration 实现 WebMvcConfigurer接口
          6. 在WebWvcConfiguration上标注@Configuration
          7. 在WebWvcConfiguration中写上@Autowired MyInterceptor myInterceptor;
          8. 在WebWvcConfiguration中重写addInterceptors方法
          9. registry.addInterceptor(myInterceptor).addPathPatterns("/**").excludePathPatterns("/student/**");
          10. 表示拦截所有请求,但不拦截/student下的所有请求
          11. /** 表示所有

          12. /* 表示一级

      • 整合数据源 DataSource
        1. 引入依赖spring-boot-starter-jdbc mysql-connector-java
        2. 添加配置properties
          #不用导入驱动,也会自动帮你找到合适的驱动
          #spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
          #jdbc:mysql:///student 相当于 jdbc:mysql://localhost:3306/student
          #在后面加 ?serverTimezone=UTC 防止报错 java.sql.SQLException: The server time zone value '�й���׼
          spring.datasource.url=jdbc:mysql:///student?serverTimezone=UTC
          spring.datasource.username=root
          spring.datasource.password=123456
      • 整合MyBatis
        1. 引入依赖 mybatis-spring-boot-starter
        2. 覆盖默认配置
          mybatis.type-aliases-package=tpfstudent.pojo
          #如果需要配置映射文件,
          #mybatis.mapper-locations=classpath:mybatis/mappers/**/*.xml
      • 整合通用Mapper
        1. 引入依赖 mapper-spring-boot-starter
        2. 继承接口public interface StudentMapper extends Mapper
          @Service
          public class StudentService
          {
              @Autowired
              private StudentMapper studentMapper;
          
              public Student selectStudentById(Integer id){
                  //this表示全局
                  return this.studentMapper.selectByPrimaryKey(id);
              }
      • 整合事务:数据库查询方法上添加注解@Transactional
      • Thymeleaf

        • 默认前缀 "classpath:/templates/";
        • 默认后缀 = ".html";
      • 什么是SpringBoot

        • 搭建spring应用的工作平台,内置Tomcat,打包成jar,自动配置(根据引入的依赖) 混乱的依赖管理,简化配置
      • Java配置

        • 原生的Java配置
          1. @Configuration 标注一个类为配置类 相当于xml配置
          2. @Bean 把方法的返回值注入到spring容器
          3. @Value 注入参数
          4. @PropertySource 读取资源文件
        • SpringBoot提供Java配置
          1. @ConfigurationProperties(prefix="jdbc") 声明一个类是一个属性读取类,读取application.properties yml
          2. @EnableConfigurationProperties (属性读取类.class)
            1. @Autowired注入
            2. 构造方法注入
            3. 通过@Bean方法参数注入
            4. 直接在@Bean方法上使用@ConfigurationProperties(prefix="前缀名")
      • SpringBoot的基本使用,搭建SpringBoot的基本应用

        1. 引入统一父工程,以及需要的启动器
        2. 覆盖默认配置
        3. 添加引导类,@SpringBootApplication(EnableAutoConfiguration @ComponentScan @SpringBootConfiguration)
    5. Eureka服务注册中心,服务提供者,服务消费者

      1. 架构的演变
        
        传统架构-->水平拆分-->垂直拆分(最早的分布式)-->soa(dubbo)-->微服务(springCloud)
      2. 远程调用技术:rpc http
        
        rpc协议:远程过程调用(Remote Procedure Call),自定义数据格式,限定技术,传输速度快,效率高 tcp,dubbo
        http协议:统一的数据格式,不限定技术,需要rest接口  tcp协议 springCloud
      3. 什么是SpringCloud
        
        微服务架构的解决方案,是很多组件的集合
        
        eureka:注册中心,服务的注册与发现
        zuul:网关协议,路由请求,过滤器(集成ribbon,集成hystrix)
        ribbon:负载均衡组件
        hystrix:熔断组件,电路保险丝
        feign:远程调用组件(集成ribbon,集成hystrix)
      4. Eureka 服务注册中心,服务提供者,服务消费者

        • 服务注册中心: tpf-eureka

          1. 引入依赖<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> 可以使用spring初始化器进行勾选
          2. 配置application.properties
            #修改端口号为8761
            server.port=8761
            
            #将Module的名称作为微服务名称注入eureka容器
            spring.application.name=tpf-eureka
            
            #配置eureka客户端服务地址
            #默认 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
            eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

            #失效服务剔除时间,默认为60秒,单位毫秒,生产环境不要修改.
            eureka.server.eviction-interval-timer-in-ms=60000
            #1,服务下线
            #当服务进行正常关闭操作时,它会触发一个服务下线的REST请求给Eureka Server,
            #告诉服务注册中心:“我要下线了”。服务中心接受到请求之后,将该服务置为下线状态。
            #2,失效剔除
            #有些时候,我们的服务提供方并不一定会正常下线,可能因为内存溢出、网络故障等原因导致服务无法正常工作。
            #Eureka Server需要将这样的服务剔除出服务列表。
            #因此它会开启一个定时任务,每隔60秒对所有失效的服务(超过90秒未响应)进行剔除。

            #解决错误EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN
            #THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
            #自我保护模式,默认为true,如果设置为false就不会报上面的错
            eureka.server.enable-self-preservation=true
          3. 在主配置类的类上加@EnableEurekaServer 启用eureka服务注册中心
        • 服务提供者: tpf-service-provider

          1. 引入启动器 spring-cloud-starter-netflix-eureka-client 可以使用spring初始化器进行勾选
          2. 配置application.properties
            #修改端口号为8081
            server.port=8081
            
            #将服务提供者的Module名作为微服务名称
            spring.application.name=tpf-service-provider
            
            #配置eureka客户端服务地址
            #默认 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
            eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

            #默认为true
            #服务启动时,检测为true会注册给eureka,为false则不会注册
            eureka.client.register-with-eureka=true

            #服务失效时间,默认90秒过期
            eureka.instance.lease-expiration-duration-in-seconds=90
            #服务续约(renew)的间隔,默认30秒一次心跳
            eureka.instance.lease-renewal-interval-in-seconds=30
            #服务提供者启动时,默认30秒向注册中心发一次心跳,证明自己还活着,90秒没有发送心跳,eureka server会认为该服务宕机,会从服务列表移除
            #这两个生产环境默认就好,不要改.
          3. 在主配置类的类上加@EnableDiscoveryClient 启动eureka客户端
        • 服务消费者: tpf-service-consumer

          1. 引入启动器 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 可以使用spring初始化器进行勾选
          2. 配置application.properties
            #修改端口号为8082
            server.port=8082
            
            #将服务消费者的Module名作为微服务名称
            spring.application.name=tpf-service-consumer
            
            #配置eureka客户端服务地址
            #默认 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
            eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

            #服务更新时间间隔
            eureka.client.registry-fetch-interval-seconds=30
            #默认为true表示需要用来注册,false不需要用来注册
            eureka.client.fetch-registry=true
            #服务消费者启动时,会检查eureka.client.fetch-registry为true时,则会拉取eureka server服务列表只读备份,进行缓存到本地,默认没30秒更新一次数据
            #这两个生产环境默认就好,不要改.
          3. 在主配置类
            • 类上加@EnableDiscoveryClient 启动eureka客户端
            • 类中写
                  @Bean
                  public RestTemplate restTemplate(){
                      return new RestTemplate();
                  }
          4. controller中,这里方法调用需要Student实体类,从provider中copy,只要属性和setter getter toSting
                @Autowired
                private RestTemplate restTemplate;
            
                //包含了所有服务信息
                //DiscoveryClient需要导入import org.springframework.cloud.client.discovery.DiscoveryClient;
                @Autowired
                private DiscoveryClient discoveryClient;
            
                @GetMapping("select/{id}")
                @ResponseBody
                public Student selectStudentById(@PathVariable("id") Integer id)
                {
                    //getInstances("服务名称");
                    List<ServiceInstance> serviceInstance_list = discoveryClient.getInstances("tpf-service-provider");
                    //get(0);0表示第一个
                    ServiceInstance serviceInstance = serviceInstance_list.get(0);
                    //服务地址
                    String host=serviceInstance.getHost();
                    //服务端口号
                    Integer port=serviceInstance.getPort();
                    return this.restTemplate.getForObject("http://"+host+":"+port+"/provider/student/select/"+id,Student.class);
                }
        • Ribbon 负载均衡

          1. 在consumer主配置类的restTemplate方法上加@LoadBalanced开启负载均衡,默认策略:简单轮询
          2. 在consumer的测试类里编写
            @Autowired
                private RibbonLoadBalancerClient ribbonLoadBalancerClient;
                
                //测试负载均衡,调用50次,看看都是调用哪个服务
                @Test
                public void test()
                {
                    for (int i = 1; i < 51; i++)
                    {
                        ServiceInstance serviceInstance = this.ribbonLoadBalancerClient.choose("tpf-service-provider");
                        System.out.println("调用"+i+"次---"+serviceInstance.getHost()+":"+serviceInstance.getPort());
                        //打印信息 5 3 1 7 5 3 1 7... 由此可见负载均衡策略:简单轮询
                    }
                }
          3. 修改负载均衡策略,在provider的application.properties中添加
            #服务名.ribbon.类型=具体类名
            #例如下面这个,但是这个不可用
            #配置负载均衡策略
            #tpf-service-provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
        • 运行不同端口SpringBootApplication主配置

          1. 打开Run Dashboard,
          2. 运行已有配置类,对着想copy的主配置类,鼠标右键 copy configuration ,
          3. 全部默认,可以修改名称,左下角Before launch:Activate tool window,点击+,选择build,再点ok即可
    6. Hystrix 熔断器

      • Hystrix解决雪崩问题的方式有两个

        • 线程隔离
        • 服务熔断
      • 触发Hystrix服务降级的情况

        • 线程池已满
        • 请求超时
      • Hystrix 熔断器的服务降级--->(检查每次请求,是否请求超时或者连接池已满)

        1. 引入启动器spring-cloud-starter-netflix-hystrix
        2. 在主配置类上添加@EnableCircuitBreaker 开启熔断器
        3. 定义全局熔断方法
          1. 在被熔断的方法中自定义一个方法,返回值类型要被熔断的方法一致,参数列表必须为空
          2. 在被熔断的方法中,在类上标注 @DefaultProperties(defaultFallback = "自定义的全局方法名") 指定全局默认熔断方法
          3. 给被熔断方法上添加@HystrixCommand 使用默认熔断方法
        4. 定义指定熔断方法
          • 在被熔断的方法中自定义一个方法,要和被熔断的方法返回值和参数列表一致
          • 给被熔断方法上添加@HystrixCommand(fallbackMethod = "自定义的指定方法名") 使用指定熔断方法
        5. 设置hystrix的超时时间
          • 在consumer的application.properties中加
            hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000
          • 修改provider的controller中的方法,添加休眠
                @GetMapping("select/{id}")
                @ResponseBody
                public Student selectStudentById(@PathVariable("id") Integer id)
                {
                    try {
                        Thread.sleep(6000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return this.studentService.selectStudentById(id);
                }
      • 熔断:不再发送请求,
      • 熔断的三个状态
        1. close:闭合状态,所有请求正常方法
        2. open:打开状态,所有请求都无法访问.如果在一定时间内容,失败的比例不小于50%或者次数不少于20次
        3. half open:半开状态,打开状态默认5s休眠期,在休眠期所有请求无法正常访问.过了休眠期会进入半开状态,放部分请求通过
        4. 测试用例:
          1. 在consumer的controller中方法之前写上 if (id==1){throw new RuntimeException();} 
          2. 如果我们准备两个请求窗口,
          3. 一个请求http://localhost:8082/consumer/student/select/1   请求失败
          4. 一个请求 http://localhost:8082/consumer/student/select/2 请求成功
          5. 当我们疯狂访问id为1的请求时(超过20次),就会触发熔断。断路器会断开,一切请求都会被降级处理。
          6. 此时你访问id为2的请求,会发现返回的也是失败,而且失败时间很短,只有几毫秒左右
      • @SpringCloudApplication 相当于@SpringBootApplication + @EnableDiscoveryClient + @EnableCircuitBreaker
    7. Feign

      • 简单使用
        1. consumer中引入feign ,注意这里是 openfeign 而不是 feign,spring-cloud-starter-openfeign
        2. 在consumer的主配置类上添加@EnableFeignClients 启用feign组件,注释consumer中主配置类的restTemplate方法
        3. consumer的controller内容
          //启用feign组件
          @EnableFeignClients
          //相当于@SpringBootApplication + @EnableDiscoveryClient + @EnableCircuitBreaker
          @SpringCloudApplication
          //开启熔断器
          //@EnableCircuitBreaker
          //启动eureka客户端,等同于 @EnableEurekaClient
          //@EnableDiscoveryClient SpringCloud提供
          //@EnableEurekaClient eureka提供
          //@EnableDiscoveryClient
          //@SpringBootApplication
          public class TpfServiceConsumerApplication
          {
          
              /*//开启负载均衡,默认策略:简单轮询
              @LoadBalanced
              //将方法返回结果注入spring容器
              @Bean
              public RestTemplate restTemplate(){
                  return new RestTemplate();
              }*/
          
              public static void main(String[] args)
              {
                  SpringApplication.run(TpfServiceConsumerApplication.class, args);
              }
          
          }
        4. 创建一个接口StudentClient
          @FeignClient("tpf-service-provider")
          public interface StudentClient
          {
              @GetMapping("provider/student/select/{id}")
              public Student selectStudentById(@PathVariable("id") Integer id);
          }
          
          feign整合hystrix熔断器
          1,在consumer的application.properties添加feign.hystrix.enabled=true 开启feign的熔断功能,默认为false
          2,创建一个类StudentClientFallback
          //注入容器
          @Component
          public class StudentClientFallback implements StudentClient
          {
              @Override
              public Student selectStudentById(Integer id)
              {
                  Student student=new Student();
                  student.setStu_name("StudentClientFallback_selectStudentById---服务器正忙,请稍后再试...");
                  return student;
              }
          }
      • Feign整合Hystrix熔断器
        1. 在consumer的application.properties添加feign.hystrix.enabled=true 开启feign的熔断功能,默认为false
        2. 创建一个类StudentClientFallback
          //注入容器
          @Component
          public class StudentClientFallback implements StudentClient
          {
              @Override
              public Student selectStudentById(Integer id)
              {
                  Student student=new Student();
                  student.setStu_name("StudentClientFallback_selectStudentById---服务器正忙,请稍后再试...");
                  return student;
              }
          }
        3. 把StudentClient类上注解@FeignClient("tpf-service-provider")改为@FeignClient(value = "tpf-service-provider",fallback = StudentClientFallback.class)
    8. Zuul 服务网关

      • 简单使用

        1. 指定zuul依赖spring-cloud-starter-netflix-zuul
        2. 配置properties
          #服务网关
          
          #修改端口号为8180
          server.port=8180
          #将服务提供者的Module名作为微服务名称
          spring.application.name=tpf-zuul
        3. 在主配置类上添加 @EnableZuulProxy 开启zuul服务网关功能
        4. 可默认访问 http://localhost:8180/tpf-service-provider/provider/student/select/1
      • Zuul+Eureka使用

        1. 引入eureka client依赖 spring-cloud-starter-netflix-eureka-client
        2. 配置properties
          #zuul.routes.路由id... 可以自定义,一般都写服务名
          #path 映射路径
          #url 映射路径对应的实际url地址
          #service-id 服务名称
          
          #配置方式1,
          #zuul.routes.tpf-service-provider.path=/tpf-service-provider/**
          #zuul.routes.tpf-service-provider.url=http://localhost:8081
          
          #配置方式2,
          #zuul.routes.tpf-service-provider.path=/tpf-service-provider/**
          #zuul.routes.tpf-service-provider.service-id=tpf-service-provider
          
          #配置方式3,
          #默认访问 http://localhost:8180/tpf-service-provider/provider/student/select/1
          #配置访问 http://localhost:8180/tpf/provider/student/select/1
          #zuul.routes.tpf-service-provider=/tpf/**
          
          #配置方式4,
          #就是不配置,使用默认,也可以访问 http://localhost:8180/tpf-service-provider/provider/student/select/1
          
          #配置前缀
          #之前访问 http://localhost:8180/tpf-service-provider/provider/student/select/1
          #现在访问 http://localhost:8180/diy-prefix/tpf-service-provider/provider/student/select/1
          zuul.prefix=/diy-prefix
        3. 在主配置类上添加 @EnableDiscoveryClient 启动eureka客户端
      • Zuul 过滤器

        1. 创建一个类LoginFilter 继承 ZuulFilter
          //@Component注入组件,再在主配置类中用@Bean注入LoginFilter到spring容器
          @Component
          public class LoginFilter extends ZuulFilter
          {
              //过滤类型:pre route post error
              //pre(路由之前),route(路由之时),post(路由之后),error(发生错误时调用)
              @Override
              public String filterType()
              {
                  //return null;
                  return "pre";
              }
          
              //过滤顺序,返回值越小,优先级越高
              @Override
              public int filterOrder()
              {
                  return 0;
              }
          
              //是否过滤(是否执行run方法),true过滤,false不过滤
              @Override
              public boolean shouldFilter()
              {
                  //return false;
                  return true;
              }
          
              //编写过滤器的具体逻辑,比如:权限判断,合法校验...
              @Override
              public Object run() throws ZuulException
              {
                  //初始化context上下文对象 import com.netflix.zuul.context.RequestContext;
                  RequestContext context=RequestContext.getCurrentContext();
                  //获取request对象
                  HttpServletRequest request = context.getRequest();
                  //获取参数
                  String token = request.getParameter("token");
                  //如果为空 import org.apache.commons.lang.StringUtils;
                  if (StringUtils.isBlank(token)){
                      //拦截,不转发请求
                      context.setSendZuulResponse(false);
          
                      //响应状态码 HttpStatus.SC_UNAUTHORIZED=401,未经授权的意思 import org.apache.http.HttpStatus;
                      //context.setResponseStatusCode(401);
                      context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
          
                      //设置响应提示
                      context.setResponseBody("{"status":"401", "text":"request error..."}");
                  }
          
                  //返回值为null,就代表该过滤器什么都不做
                  return null;
              }
          
          }
        2. 在主配置类中添加
              //把返回值注入spring容器
              @Bean
              public LoginFilter loginFilter(){
                  return new LoginFilter();
              }
    9. 1
    10. 1
    11. 1
    12. 1
    13. 1
    14. 1
  • 相关阅读:
    运维常见面试题
    python常见面试题
    常见面试题
    常用算法之‘归并排序’
    python库大全
    Springboot拦截器无效,解决办法
    Springboot 不返回页面,只反回文本
    SpringBoot 接收参数的几种常用方式(转载)
    mysql 查询每个分组的前几名
    Java中TimeZone类的常用方法
  • 原文地址:https://www.cnblogs.com/taopanfeng/p/11080113.html
Copyright © 2011-2022 走看看