新建Spring Boot项目

怎么新建Spring Boot项目这里不再具体赘述,不会的可以翻看下之前的博客或者直接百度。这里直接贴出对应的pom文件。

pom依赖如下:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.lifengdi</groupId>
<artifactId>gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency> <!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency> <dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>--> <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency> <dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
<scope>compile</scope>
</dependency> <dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

由于是网关项目,所以不需要spring-boot-starter-web相关的依赖。

配置文件如下:

server:
port: 8080
spring:
application:
name: spring-cloud-gateway-demo
cloud:
gateway:
discovery:
locator:
enabled: true #启用路由访问
routes:
- id: path_route
# 指定域名
uri: http://localhost:8081
predicates:
- Path=/jar/**
filters:
# 熔断配置
- name: Hystrix
args:
name: default
fallbackUri: forward:/fallback
- id: path_route2
# 指定域名
uri: http://localhost:8082
predicates:
- Path=/war/**
filters:
# 熔断配置
- name: Hystrix
args:
name: hystrix1
fallbackUri: forward:/fallback mvc:
throw-exception-if-no-handler-found: true # 默认熔断超时时间30s
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
hystrix1:
execution:
isolation:
thread:
timeoutInMilliseconds: 1000

熔断(接口或者项目)

熔断相关jar包如下:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

默认的熔断回调接口:

package com.lifengdi.gateway.hystrix;

import com.lifengdi.gateway.exception.BaseException;
import com.lifengdi.gateway.response.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; /**
* @author: Li Fengdi
* @date: 2020-03-18 16:35
*/
@RestController
@Slf4j
public class DefaultHystrixController {
@RequestMapping("/fallback")
public ResponseResult<Object> fallback(){ log.error("触发熔断......");
return ResponseResult.fail(BaseException.DEFAULT_HYSTRIX.build());
}
}

具体配置文件说明如下:

      routes:
- id: path_route
# 指定域名
uri: http://localhost:8081
predicates:
- Path=/jar/**
filters:
# 熔断配置
- name: Hystrix
args:
name: default
fallbackUri: forward:/fallback
- id: path_route2
# 指定域名
uri: http://localhost:8082
predicates:
- Path=/war/**
filters:
# 熔断配置
- name: Hystrix
args:
name: hystrix1
fallbackUri: forward:/fallback mvc:
throw-exception-if-no-handler-found: true # 默认熔断超时时间30s
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
hystrix1:
execution:
isolation:
thread:
timeoutInMilliseconds: 1000

defaulthystrix1为自定义的参数,可以配置多个熔断策略,不同的接口、服务可以单独配置对应的超时时间,不需要额外的进行开发,不过需要增加额外的配置文件。

全局session共享

依赖jar包:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency> <dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency> <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

相关yml配置:

spring:
redis:
database: 0
host: localhost
port: 6379
password: 123456
lettuce:
pool:
max-active: 300
max-idle: 8
max-wait: -1ms
min-idle: 0
session:
store-type: redis

spring.session.store-typeSpring默认就是redis实现的,也有其他的,配置不同罢了。

增加代码如下:

权限相关,这里默认全部放行:

package com.lifengdi.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain; @Configuration
@EnableWebFluxSecurity
public class GatewaySecurityConfig {
@Bean
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity serverHttpSecurity)
throws Exception {
serverHttpSecurity
.csrf().disable()
.authorizeExchange().pathMatchers("/**").permitAll()
.anyExchange()
.authenticated();
return serverHttpSecurity.build();
}
}

session相关:

package com.lifengdi.gateway.config;

import com.lifengdi.gateway.resolver.MyCookieWebSessionIdResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseCookie;
import org.springframework.session.data.redis.config.annotation.web.server.EnableRedisWebSession;
import org.springframework.web.server.session.CookieWebSessionIdResolver;
import org.springframework.web.server.session.WebSessionIdResolver; import java.util.function.Consumer; @Configuration
@EnableRedisWebSession(maxInactiveIntervalInSeconds = 10*60*60, redisNamespace = "my:spring:session")
public class WebSessionConfig { @Bean
public WebSessionIdResolver webSessionIdResolver() {
CookieWebSessionIdResolver resolver = new MyCookieWebSessionIdResolver();
resolver.setCookieName("SESSIONID"); Consumer<ResponseCookie.ResponseCookieBuilder> consumer = responseCookieBuilder -> {
responseCookieBuilder.path("/");
};
resolver.addCookieInitializer(consumer);
return resolver;
} }

注意这里使用的是@EnableRedisWebSession注解,而不是@EnableRedisHttpSession,这个是和zuul不一样的地方。

用zuul做网关的时候,直接使用@EnableRedisHttpSession在配置里面就可以通过redis共享session信息

Spring同时提供了@EnableRedisWebSession来对WebFlux的支持。

值得一提的是这两个注解内部实现并不相同,需要自定义的配置也不一样。

这里自定义cookieName、path等是自定义了webSessionIdResolver来实现的,而不是cookieSerializer。如果使用cookieSerializer的话,对@EnableRedisWebSession来说是不起作用的。这个坑之前坑了好半天!

MyCookieWebSessionIdResolver代码如下:

package com.lifengdi.gateway.resolver;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpCookie;
import org.springframework.session.web.http.DefaultCookieSerializer;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.session.CookieWebSessionIdResolver; import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors; /**
* 自定义WebSessionId解析器,以兼容{@link org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession}
* <p>
* 使用EnableRedisHttpSession时{@link DefaultCookieSerializer}中useBase64Encoding默认为true,将cookie中的sessionId使用base64
* 加密,但是如果使用{@link org.springframework.session.data.redis.config.annotation.web.server.EnableRedisWebSession},默认
* 的解析器没有将sessionId解密,导致获取不到正确的session
* </p>
*
* @author: Li Fengdi
* @date: 2020/3/16 15:41
*/
@Slf4j
public class MyCookieWebSessionIdResolver extends CookieWebSessionIdResolver { @Override
public List<String> resolveSessionIds(ServerWebExchange exchange) {
MultiValueMap<String, HttpCookie> cookieMap = exchange.getRequest().getCookies();
List<HttpCookie> cookies = cookieMap.get(getCookieName());
if (cookies == null) {
return Collections.emptyList();
}
return cookies.stream().map(HttpCookie::getValue).map(this::base64Decode).collect(Collectors.toList());
} /**
* base64解码
*
* @param base64Value base64Value
* @return 解码后的字符串
*/
private String base64Decode(String base64Value) {
try {
byte[] decodedCookieBytes = Base64.getDecoder().decode(base64Value);
return new String(decodedCookieBytes);
} catch (Exception ex) {
log.debug("Unable to Base64 decode value: " + base64Value);
return null;
}
} }

其实这段代码本就是参考了cookieSerializer中的代码来实现的。

如果指定了useBase64Encoding为false,即不加密sessionId,那么就不需要这一段代码了。

代码已上传到git上,需要的可以去看看。

git代码地址:https://github.com/lifengdi/spring-cloud-gateway-demo

原文地址:https://www.lifengdi.com/archives/article/1776

从零搭建Spring Cloud Gateway网关(一)的更多相关文章

  1. 从零搭建Spring Cloud Gateway网关(二)—— 打印请求响应日志

    作为网关,日志记录是必不可少的功能,可以在网关出增加requestId来查询整个请求链的调用执行情况等等. 打印请求日志 打印请求日志最重要的就是打印请求参数这些东西,不过RequestBody通常情 ...

  2. 从零搭建Spring Cloud Gateway网关(三)——报文结构转换

    背景 作为网关,有些时候可能报文的结构并不符合前端或者某些服务的需求,或者因为某些原因,其他服务修改报文结构特别麻烦.或者需要修改的地方特别多,这个时候就需要走网关单独转换一次. 实现 话不多说,直接 ...

  3. Spring Cloud gateway 网关服务二 断言、过滤器

    微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...

  4. Spring Cloud gateway 网关四 动态路由

    微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...

  5. Spring Cloud实战 | 第十一篇:Spring Cloud Gateway 网关实现对RESTful接口权限控制和按钮权限控制

    一. 前言 hi,大家好,这应该是农历年前的关于开源项目 的最后一篇文章了. 有来商城 是基于 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT实现的统 ...

  6. .net core下,Ocelot网关与Spring Cloud Gateway网关的对比测试

    有感于 myzony 发布的 针对 Ocelot 网关的性能测试 ,并且公司下一步也需要对.net和java的应用做一定的整合,于是对Ocelot网关.Spring Cloud Gateway网关做个 ...

  7. 微服务架构spring cloud - gateway网关限流

    1.算法 在高并发的应用中,限流是一个绕不开的话题.限流可以保障我们的 API 服务对所有用户的可用性,也可以防止网络攻击. 一般开发高并发系统常见的限流有:限制总并发数(比如数据库连接池.线程池). ...

  8. 从0开始构建你的api网关--Spring Cloud Gateway网关实战及原理解析

    API 网关 API 网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题 ...

  9. Spring Cloud gateway 网关服务 一

    之前我们介绍了 zuul网关服务,今天聊聊spring cloud gateway 作为spring cloud的亲儿子网关服务.很多的想法都是参照zuul,为了考虑zuul 迁移到gateway 提 ...

随机推荐

  1. UFT基本操作

    1.打开界面F6快捷录制 2.选择web或者C/S架构软件 3.以C/S为例,点击添加找到相应的地址 4.点击左键添加断点 5.切换视图,初级模式或者代码模式 6.新增步骤 7.点击“手指”图标获取元 ...

  2. proxmox新版本使用了lxc容器,导致以前的vzlist命令无法使用,于是自己写了一个脚本来获取所有半虚拟化主机的信息状态

    #!/usr/bin/env python #encoding:utf-8 # desc:用来描述各个主机信息 import os #CTID NPROC STATUS IP_ADDR HOSTNAM ...

  3. CF-1114C-Trailing Loves (or L'oeufs?)

    题意: 输入n和m,求n!转换成m进制之后末尾有多少个0: 思路: 转换一下题意就可以看成,将n表示成x * (m ^ y),求y的最大值.^表示次方而不是异或: 这就比较好想了,将m分解质因数,对于 ...

  4. keepalive笔记之二:keepalive+nginx(自定义脚本实现,上述例子也可以实现)

    keepalive的配置文件 ! Configuration File for keepalived global_defs { notification_email { acassen@firewa ...

  5. 基于Jquery的textarea滚动条插件(原创)

    之前项目中自己写的滚动条插件.先前太忙没有好好整理.现在项目间歇期拿出来整理后贴出来 Demo Here css 我是把mCustomScrollbar 的UI 扣下来的. 这里我要介绍下这个插件不错 ...

  6. Android开发之《ffmpeg解码mjpeg视频流》

    MJPEG格式和码流分析,MJPEG格式的一些简介 FFmpeg解码USB摄像头MJPEG输出:http://blog.csdn.net/light_in_dark/article/details/5 ...

  7. Trie图 模板

    trie图实际上是优化的一种AC自动机. trie图是在trie树上加一些失配指针,实际上是类似KMP的一种字符串匹配算法. 失配指针类似KMP的nx数组,有效地利用了之前失配的信息,优化了时间复杂度 ...

  8. 原创:CentOS 环境中 Zabbix 3.4 的安装部署实践

    IT管理工作中,如果没有对服务器.网络设备.服务.进程.应用等的监控,往往是用户发送问题报告后才知道出了问题.事后救火显得被动,不能从容面对问题. 才有了部署一套网络监控系统的想法,机缘巧合下结识了Z ...

  9. appium ios真机自动化环境搭建&运行(送源码)

    appium ios真机自动化环境搭建&运行(送源码) 原创: f i n  测试开发社区  6天前 Appium测试环境的搭建相对比较烦琐,不少初学者在此走过不少弯路 首先是熟悉Mac的使用 ...

  10. 代工黑马,纬创如何强吞iPhone?

    ​ 现在,智能手机市场非常得意兴阑珊,以苹果为首的最强大脑似乎再也想不出什么好的创意,iPhone7也只不过是旧机种的翻新款式,看上去跟一块板砖.一块镜子差不多:软体方面则出现了大批的"过度 ...