• springboot+kotlin+springcloud+java+grade+maven混编?


    springboot + maven + java vs springboot + gradle + kotlin

    快速搭建:https://start.spring.io/

    springclould:netflix:

    java:

    pom.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.fly</groupId>
        <artifactId>springboot01</artifactId>
        <version>1.0-SNAPSHOT</version>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.1.RELEASE</version>
            <relativePath/>
        </parent>
        <properties>
            <java.version>1.8</java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
            <!--通用mapper
            已包含jdbc mybatis
            -->
            <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.3</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </project>

    kotlin:

    build.gradle:

    buildscript {
       ext {
          kotlinVersion = '1.2.71'
          springBootVersion = '2.1.1.RELEASE'
       }
       repositories {
          mavenCentral()
       }
       dependencies {
         classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
          classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
          classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
       }
    }
    apply plugin: 'kotlin'
    apply plugin: 'kotlin-spring'
    apply plugin: 'eclipse'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'

    group = 'com.example'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = 1.8
    compileKotlin {
       kotlinOptions {
          freeCompilerArgs = ["-Xjsr305=strict"]
          jvmTarget = "1.8"
       }
    }
    compileTestKotlin {
       kotlinOptions {
          freeCompilerArgs = ["-Xjsr305=strict"]
          jvmTarget = "1.8"
       }
    }
    repositories {
       mavenCentral()
    }
    dependencies {
       implementation('org.springframework.boot:spring-boot-starter-web')
       implementation('com.fasterxml.jackson.module:jackson-module-kotlin')
       implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
       implementation("org.jetbrains.kotlin:kotlin-reflect")
       implementation("tk.mybatis:mapper-spring-boot-starter:2.0.3")
       implementation("mysql:mysql-connector-java:5.1.6")
       testImplementation('org.springframework.boot:spring-boot-starter-test')
    }

    java:8088

    kotlin:8089

    application.yml

    server:
      port: 8088
    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/mybatisdemo
        username: root
        password: root
        hikari:   # jdbc默认连接池
          maximum-pool-size: 20
          minimum-idle: 10
    mybatis:
      type-aliases-package: com.fly.pojo
    logging:
      level:
        com.fly.service: error

    App:

    java:

    @SpringBootApplication
    @MapperScan("com.fly.mapper")
    public class App {
        public static void main(String[] args){
            SpringApplication.run(App.class,args);
        }
    }
    
    kotlin:
    
    @SpringBootApplication
    @MapperScan("com.fly.mapper")
    class Application{
        @Bean
        fun restTemplate():RestTemplate = RestTemplate()
    }
    
    fun main(args: Array<String>) {
    //    SpringApplication.run(Application::class.java,*args)
        runApplication<Application>(*args)
    }
    pojo.User:

    java:

    @Data
    @Table(name = "user")
    public class User {
        @Id
        @KeySql(useGeneratedKeys = true)//插入的表以自增列为主键
        @GeneratedValue(strategy = GenerationType.IDENTITY)//主键生成策略
        @Column(name = "id")
        private Integer id;
        private String username;
        private Date birthday;
        private String sex;
        private String address;
    }

    kotlin:

    @Table(name = "user")
    data class User(
        @Id
        @KeySql(useGeneratedKeys = true)
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        var id: Int? = null,
        var username: String? = null,
        var birthday: Date? = null,
        var sex: String? = null,
        var address: String? = null
    )

    UserMapper:

    java:

    public interface UserMapper extends Mapper<User> {
    }

    kotlin:

    interface UserMapper:Mapper<User>

    UserService:

    java:

    @Service
    public class UserService {
        @Resource
        private UserMapper userMapper;
    
        public List<User> selectAll(){
            return userMapper.selectAll();
        }
    
        @Transactional
        public void insert(User user){
            userMapper.insert(user);
        }
    }

    kotlin:

    @Service
    class UserService {
        @Resource
        lateinit var userMapper:UserMapper

        fun selectAll():List<User> = userMapper.selectAll()

        @Transactional
        fun insert(user: User) = userMapper.insert(user)
    }

    UserController:

    java:

    @RestController
    public class UserController {
        @Resource
        private UserMapper userMapper;
    
        private final UserService userService;
        @Autowired
        public UserController(UserService userService) {
            this.userService = userService;
        }
    
        @GetMapping("/")
        public List<User> selectAll(){
            return userService.selectAll();
        }
        @GetMapping("/{id}")
        public User selectById(@PathVariable("id")int id){
            return userMapper.selectByPrimaryKey(id);
        }
    }

    kotlin:

    @RestController
    class UserController {

        @Autowired
        lateinit var userService: UserService

        @Autowired
        lateinit var restTemplate:RestTemplate

        @GetMapping
        fun selectAll(): List<User> = userService.selectAll()

        @GetMapping("/{id}")
        fun httpSelectAll(@PathVariable("id") id:Int):User?{
            return restTemplate.getForObject("http://localhost:8088/"+id, User::class.java)
        }

    }

    MyInterceptor:

    java:

    /**
     * 拦截器
     */
    @Slf4j
    public class MyInterceptor implements HandlerInterceptor {
    //    private Logger log = LoggerFactory.getLogger(MyInterceptor.class);
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("preHandle......");
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("postHandle.....");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("afterCompletion.....");
        }
    }

    kotlin:

    class MyInterceptor :HandlerInterceptor{
        var log:Logger = LoggerFactory.getLogger(MyInterceptor::class.java)
        override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
            log.info("preHandle......")
            return true
        }

        override fun postHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any, modelAndView: ModelAndView?) {
            log.info("postHandle......")
        }

        override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?) {
            log.info("afterCompletion......")
        }
    }

    MvcConfig:

    java:

    /**
     * 注册拦截器
     */
    @Configuration
    public class MvcConfig implements WebMvcConfigurer {
        @Bean
        public MyInterceptor myInterceptor(){
            return new MyInterceptor();
        }
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //注册拦截器,添加拦截路径
            registry.addInterceptor(myInterceptor()).addPathPatterns("/**");
        }
    }

    kotlin:

    @Configuration
    class MvcConfig :WebMvcConfigurer{
        @Bean
        fun myInterceptor():MyInterceptor = MyInterceptor()

        override fun addInterceptors(registry: InterceptorRegistry) {
            registry.addInterceptor(myInterceptor()).addPathPatterns("/**")
        }
    }

    测试:

    java:

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = App.class)//()内容可省略
    public class UserServiceTest {
        @Autowired
        private UserService userService;
        @Test
        public void test() {
            List<User> list = userService.selectAll();
            for (User user : list) {
                System.out.println(user);
            }
        }
        @Test
        public void test1(){
            User user = new User();
            user.setUsername("测试a");
            user.setBirthday(new Date());
            user.setSex("1");
            user.setAddress("A");
            userService.insert(user);
        }
    }

    kotlin:

    @RunWith(SpringRunner::class)
    @SpringBootTest(classes = arrayOf(Application::class))
    class UserServiceTest {
        @Autowired
        lateinit var userService:UserService
        @Test
        fun test(){
            val list:List<User> = userService.selectAll()
            for (user in list) {
                println(user)
            }
        }

        @Test
        fun test1(){
            val user = User()
            user.username = "Kotlin111"
            user.address = "K"
            user.sex = "1"
            user.birthday = Date()
            userService.insert(user)
        }
    }

    netflix:

    Eureka:注册中心

    Zuul:服务网关

    Ribbon:负载均衡

    Feign:服务调用

    Hystix:熔断器

    Eureka:注册中心

    grade+java搭建eureka服务,客户端分别为上面的java+kotlin

    eureka服务端:

    build.gradle:

    buildscript {
        ext {
            springBootVersion = '2.1.1.RELEASE'
        }
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        }
    }

    apply plugin: 'java'
    apply plugin: 'eclipse'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'

    group = 'com.fly'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = 1.8

    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/milestone" }
    }

    ext['springCloudVersion'] = 'Greenwich.RC2'

    dependencies {
        implementation('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server')
        testImplementation('org.springframework.boot:spring-boot-starter-test')
    }

    dependencyManagement {
        imports {
            mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
        }
    }

    application.yml:

    server:
      port: 8761 # 默认8761
    spring:
      application:
        name: eureka-server
    eureka:
      client:
        register-with-eureka: false # 注册自己的信息到EurekaServer
        fetch-registry: false # 拉取其它服务的信息
        service-url:
          defaultZone: http://127.0.0.1:${server.port}/eureka
      server:
        eviction-interval-timer-in-ms: 60000 # 扫描失效服务的间隔时间 失效剔除 单位是毫秒,生成环境不要修改
        enable-self-preservation: false # 关闭自我保护 默认为true

    EurekaApplication:

    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaApplication {
        public static void main(String[] args){
            SpringApplication.run(EurekaApplication.class,args);
        }
    }

    客户端:

    java:

    pom.xml:

    <!--Eureka客户端-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.0.2.RELEASE</version>
    </dependency>

    application.yml:

    server:
      port: 8088

    spring:
      application:
          name: springboot01
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/mybatisdemo
        username: root
        password: root
        hikari:   # jdbc默认连接池
          maximum-pool-size: 20
          minimum-idle: 10

    mybatis:
      type-aliases-package: com.fly.pojo
    logging:
      level:
        com.fly.service: error
    eureka:
      client:
        service-url: # EurekaServer地址
          defaultZone: http://127.0.0.1:8761/eureka
        registry-fetch-interval-seconds: 30 # 默认值 获取服务列表
      instance:
        prefer-ip-address: true # 当其它服务获取地址时提供ip而不是hostname
        ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
        # 修改服务续约的行为
        lease-expiration-duration-in-seconds: 90 # 服务失效时间,默认值90秒
        lease-renewal-interval-in-seconds: 30 # 服务续约(renew)的间隔,默认为30秒
        instance-id: ${spring.application.name} + ${server.port} # 默认显示的信息${hostname}:${spring.application.name}:${server.port}

    App部分:

    @SpringBootApplication
    //@EnableEurekaClient //开启eureka客户端
    @EnableDiscoveryClient //客户端,支持多种
    @MapperScan("com.fly.mapper")
    public class App {

    服务的消费方:

    build.gradle:

    implementation('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:2.0.2.RELEASE')

    application.yml:

    server:
      port: 8089
    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/mybatisdemo
        username: root
        password: root
      application:
        name: demo
      main:
        allow-bean-definition-overriding: true # 同名bean覆盖
    mybatis:
      type-aliases-package: com.fly.pojo
    eureka:
      client:
        service-url:
          defaultZone: http://127.0.0.1:8761/eureka
        registry-fetch-interval-seconds: 30 # 默认值 获取服务列表
      instance:
        prefer-ip-address: true
        ip-address: 127.0.0.1

    Application.kt:

    @SpringBootApplication
    @EnableEurekaClient
    @MapperScan("com.fly.mapper")
    class Application{
        @Bean
        fun restTemplate():RestTemplate = RestTemplate()
    }

    fun main(args: Array<String>) {
    //    SpringApplication.run(Application::class.java,*args)
        runApplication<Application>(*args)
    }

    UserService:

    @Autowired
    lateinit var restTemplate: RestTemplate
    @Autowired
    lateinit var discoveryClient:DiscoveryClient

    fun queryUserById(id: Int):User?{
        // 根据服务名称,获取服务实例
        // 因为只有一个UserService,因此我们直接get(0)获取
        val instances = discoveryClient.getInstances("springboot01").get(0)
        // 获取ip和端口信息
        val url:String = "http://"+instances.host + ":" + instances.port +"/"+ id
        return restTemplate.getForObject(url, User::class.java)
    }

    UserController:

    @GetMapping("/user/{id}")
    fun eurekaQueryUserById(@PathVariable("id") id: Int):User?{
        return userService.queryUserById(id)
    }

    Ribbon:负载均衡

    负载均衡:

    spring-cloud netfix已经包含,无需再导入

    org.springframework.cloud:spring-cloud-starter-netflix-ribbon

    Application.kt

    @Bean
    @LoadBalanced // 开启负载均衡
    fun restTemplate():RestTemplate = RestTemplate()

    UserService:

    //    负载均衡 使用 @LoadBalanced
        fun queryUserById(id: Int):User?{
            // url直接写服务名,LoadBalancerInterceptor会根据服务名获取服务实例的ip与端口
            val url = "http://springboot01/"
            return restTemplate.getForObject(url+id, User::class.java)
        }

    重试机制

    build.gradle

    // 重试机制
    implementation('org.springframework.retry:spring-retry:1.2.2.RELEASE')

    application.yml部分:

    server:
      port: 8089
    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/mybatisdemo
        username: root
        password: root
      application:
        name: demo
      main:
        allow-bean-definition-overriding: true # 同名bean覆盖
      cloud:
        loadbalancer:
          retry:
            enabled: true # 开启Spring Cloud的重试功能
    springboot01: # 服务名称 负载均衡规则的配置入口
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 默认轮训 值为IRule的实现类
        ConnectTimeout: 250 # Ribbon的连接超时时间
        ReadTimeout: 1000 # Ribbon的数据读取超时时间
        OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
        MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
        MaxAutoRetries: 1 # 对当前实例的重试次数

    Hystix:熔断器

    熔断器:

    build.gradle

    //熔断器
    implementation('org.springframework.cloud:spring-cloud-starter-netflix-hystrix:2.0.2.RELEASE')

    Application.kt:

    //@SpringBootApplication
    //@EnableCircuitBreaker //熔断
    //@EnableDiscoveryClient //注册客户端
    //@EnableEurekaClient

    @SpringCloudApplication //包含上面前3

    UserService部分:

    @Service
    //@DefaultProperties(defaultFallback = "queryUserByIdFallBack")
    class UserService {
        @Autowired
        lateinit var restTemplate: RestTemplate
    //    负载均衡 使用 @LoadBalanced
        @HystrixCommand(fallbackMethod = "queryUserByIdFallBack") //失败回滚 默认是1000毫秒

    //    @HystrixCommand(commandProperties =
    //        [HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")] //超时时间
    //    )
    //    @HystrixCommand
        fun queryUserById(id: Int):User?{
            val begin:Long = System.currentTimeMillis()
            // url直接写服务名,LoadBalancerInterceptor会根据服务名获取服务实例的ip与端口
            val url = "http://springboot01/"
            val user:User? = restTemplate.getForObject(url+id, User::class.java)
            val end:Long = System.currentTimeMillis()
            val t:Long = end - begin
            println("访问时间:$t")
            return user
        }
        fun queryUserByIdFallBack():User?{
            val user = User()
            user.username = "服务器太拥挤了!!!"
            return user
        }

        fun queryUserByIdFallBack(id: Int):User?{
            val user = User()
            user.username = "服务器太拥挤了!!!"
            return user
        }

    配置文件方式配置:

    application.yml:

    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 3000 # 设置hystrix的超时时间为3000ms

    服务提供方模拟超时:

    @GetMapping("/")
    public List<User> selectAll(){
        return userService.selectAll();
    }
    @GetMapping("/{id}")
    public User selectById(@PathVariable("id")int id) throws InterruptedException {
        Thread.sleep(2000L); //模拟超时
        return userMapper.selectByPrimaryKey(id);
    }

    断路器配置:

    @HystrixCommand(commandProperties =
        [
            //具体参数位置 HystrixCommandProperties.java
            /* 状态机的三种状态
            *  Closed:关闭状态(断路器关闭),所有请求都正常访问
            *  Open:打开状态(断路器打开),所有请求都被降级,hystix会对请求情况进行计数,当失败的百分比达到阀值
            *       ,则触发熔断,断路器完全关闭
            *  Half Open:半开状态,Closed状态不是永久的,关闭后会进入休眠,随后断路器自动进入半开状态,
            *       此时会释放部分请求通过。若请求是健康的,则会完全打开断路器,否则保持关闭,再进行休眠计时
            *
            * */
            HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"), //执行超时时间 默认1000
            HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), // 触发熔断器的最小请求次数 默认20
            HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // 休眠时长 默认5000毫秒
            HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50") //触发熔断的失败请求最小占比 默认50%
        ] //超时时间
    )

    Feign:服务调用

    Feign:(伪装

    build.gradle

    // feign
    implementation('org.springframework.cloud:spring-cloud-starter-openfeign:2.0.2.RELEASE')

    Application.kt

    @EnableFeignClients // 开启Feign功能

    feign,熔断器设置:

    UserFeignClient

    @FeignClient(value = "springboot01",fallback = UserFeignClientFallback::class,configuration = [FeignConfig::class])
    interface UserFeignClient {
        @GetMapping("/{id}")
        fun feignQueryUserById(@PathVariable("id")id:Int): User
    }

    UserFeignClientFallback

    @Component
    class UserFeignClientFallback:UserFeignClient {
        override fun feignQueryUserById(id: Int): User {
            val user = User()
            user.username = "未知用户???"
            return user
        }
    }

    UserController

    @Resource
    lateinit var userFeignClient: UserFeignClient
    @GetMapping("/feignUser/{id}")
    fun feignQueryUserById(@PathVariable("id") id: Int):User{
        return userFeignClient.feignQueryUserById(id)
    }

    负载均衡,熔断器,日志设置:

    application.yml

    feign:
      hystrix:
        enabled: true # 开启Feign的熔断功能 默认关闭

    ribbon: # feign的ribbon的配置 也可以使用上面ribbon的配置方式
      ConnectTimeout: 250 # 连接超时时间(ms)
      ReadTimeout: 3000 #  通信超时时间(ms)
    #  OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
    #  MaxAutoRetriesNextServer: 1 # 同一服务不同实例的重试次数
    #  MaxAutoRetries: 1 # 同一实例的重试次数

    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 4000 # 设置hystrix的超时时间为 ms

    logging: # 日志级别
      level:
        com.fly: debug

    请求压缩

    feign:
      compression:
        request:
          enabled: true # 开启请求压缩
          mime-types: text/html,application/xml,application/json # 设置压缩的数据类型 默认
          min-request-size: 2048 # 设置触发压缩的大小下限 默认
        response:
          enabled: true # 开启响应压缩

    Zuul:服务网关

    面向服务:

    pom.xml

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            <version>2.0.2.RELEASE</version>
        </dependency>
        <!--Eureka客户端依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
    </dependencies>

    ZuulApplication

    @SpringBootApplication
    @EnableZuulProxy //开启Zuul的功能
    @EnableDiscoveryClient
    public class ZuulApplication {

        public static void main(String[] args) {
            SpringApplication.run(ZuulApplication.class, args);
        }

    }

    application.yml

    server:
      port: 9901
    spring:
      application:
        name: zuul
    #zuul:
    #  routes:
    #    springboot01: # 路由id,随意写 将 /user/**开头的请求,代理到http://127.0.0.1:8087
    #      path: /user/** # 这里是映射路径
    ##      url: http://127.0.0.1:8087  # 映射路径对应的实际url地址
    #      serviceId: springboot01 # 指定服务名称 ,会利用Ribbon进行负载均衡访问
    #  简化的路由配置
    #zuul:
    #  routes:
    #    springboot01: springboot01/** # 服务名与映射地址相同可以省略

    #  路由前缀
    zuul:
    #  prefix: /api # 添加路由前缀
      routes:
        springboot01:
          path: /user/**
          serviceId: springboot01
      retryable: true # 重试 默认false

    #  ignored-services: # 忽略的服务
    #    - springboot02
    #    - springboot03

    # 熔断
    ribbon: # ribbon的配置 详见 AbstractRibbonCommand.java
      ConnectTimeout: 250 # 连接超时时间(ms) 默认1000
      ReadTimeout: 2000 #  通信超时时间(ms) 默认1000
      OkToRetryOnAllOperations: true # 是否对所有操作重试
      MaxAutoRetriesNextServer: 1 # 同一服务不同实例的重试次数 默认1
      MaxAutoRetries: 0 # 同一实例的重试次数 默认0

    # 负载均衡
    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 6000 # 熔断超时时长:6000ms > (ReadTimeout+ConnectTimeout)*2,ribbon默认重试1次
    # ribbonTimeout = (ribbonReadTimeout + ribbonConnectTimeout) * (maxAutoRetries + 1) * (maxAutoRetriesNextServer + 1)
    #   (250 + 2000)* (0+1)*(1+1)

    eureka:
      client:
        service-url: # EurekaServer地址
          defaultZone: http://127.0.0.1:8761/eureka
        registry-fetch-interval-seconds: 30 # 默认值 获取服务列表
      instance:
        prefer-ip-address: true # 当其它服务获取地址时提供ip而不是hostname
        ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找

    自定义过滤器

    /**
     * 自定义过滤器
     */
    @Component
    public class LoginFilter extends ZuulFilter {
        @Override
        public String filterType() {//返回字符串,代表过滤器的类型
            /**
             * - pre:请求在被路由之前执行
             * - routing:在路由请求时调用
             * - post:在routing和errror过滤器之后调用
             * - error:处理请求时发生错误调用
             */
    //        return "pre";
            return FilterConstants.PRE_TYPE;
        }

        @Override
        public int filterOrder() {//通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高
            return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;//4
        }

        @Override
        public boolean shouldFilter() {//返回一个`Boolean`值,判断该过滤器是否需要执行。返回true执行,返回false不执行
            return true;
        }

        @Override
        public Object run() throws ZuulException {//过滤器的具体业务逻辑
            // 获取Zuul提供的请求上下文对象
            RequestContext context = RequestContext.getCurrentContext();
            // 从上下文中获取request对象
            HttpServletRequest request = context.getRequest();
            String token = request.getParameter("user-token");
            //判断是否存在
            if (StringUtils.isBlank(token)){
                context.setSendZuulResponse(false);
                context.setResponseStatusCode(HttpStatus.FORBIDDEN.value());//403
            }
            return null;
        }
    }

     

  • 相关阅读:
    利用Java API通过路径过滤上传多文件至HDFS
    docker-compose部署haproxy
    PM2 常用命令
    shell脚本循环访问url直到状态码返回200跳出循环
    CentOS 7.6安装配置Chrony同步系统时钟
    PostgreSQL9.5数据库锁表问题分析与解决
    linux系统netstat命令详解(netstat常用运维命令)
    linux目录备份脚本
    PostgreSQL 锁等待监控 珍藏级SQL
    docker部署pgadmin4并通过nginx反向代理
  • 原文地址:https://www.cnblogs.com/fly-book/p/10233923.html
Copyright © 2020-2023  润新知