spring boot实现超轻量级网关(反向代理、转发)的示例

作者: JadePeng

出处:https://www.cnblogs.com/xiaoqi/p/spring-boot-route.html

在我们的rest服务中,需要暴露一个中间件的接口给用户,但是需要经过rest服务的认证,这是典型的网关使用场景。可以引入网关组件来搞定,但是引入zuul等中间件会增加系统复杂性,这里实现一个超轻量级的网关,只实现请求转发,认证等由rest服务的spring security来搞定。

如何进行请求转发呢? 熟悉网络请求的同学应该很清楚,请求无非就是请求方式、HTTP header,以及请求body,我们将这些信息取出来,透传给转发的url即可。

举例:

/graphdb/** 转发到 Graph_Server/**

获取转发目的地址:

private String createRedictUrl(HttpServletRequest request, String routeUrl, String prefix) {
  String queryString = request.getQueryString();
  return routeUrl + request.getRequestURI().replace(prefix, "") +
    (queryString != null ? "?" + queryString : "");
 }

解析请求头和内容

然后从request中提取出header、body等内容,构造一个RequestEntity,后续可以用RestTemplate来请求。

private RequestEntity createRequestEntity(HttpServletRequest request, String url) throws URISyntaxException, IOException {
  String method = request.getMethod();
  HttpMethod httpMethod = HttpMethod.resolve(method);
  MultiValueMap<String, String> headers = parseRequestHeader(request);
  byte[] body = parseRequestBody(request);
  return new RequestEntity<>(body, headers, httpMethod, new URI(url));
 }

 private byte[] parseRequestBody(HttpServletRequest request) throws IOException {
  InputStream inputStream = request.getInputStream();
  return StreamUtils.copyToByteArray(inputStream);
 }

 private MultiValueMap<String, String> parseRequestHeader(HttpServletRequest request) {
  HttpHeaders headers = new HttpHeaders();
  List<String> headerNames = Collections.list(request.getHeaderNames());
  for (String headerName : headerNames) {
   List<String> headerValues = Collections.list(request.getHeaders(headerName));
   for (String headerValue : headerValues) {
    headers.add(headerName, headerValue);
   }
  }
  return headers;
 }

透明转发

最后用RestTemplate来实现请求:

 private ResponseEntity<String> route(RequestEntity requestEntity) {
  RestTemplate restTemplate = new RestTemplate();
  return restTemplate.exchange(requestEntity, String.class);
 }

全部代码

以下是轻量级转发全部代码:

import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;

@Service
public class RoutingDelegate {

 public ResponseEntity<String> redirect(HttpServletRequest request, HttpServletResponse response,String routeUrl, String prefix) {
  try {
   // build up the redirect URL
   String redirectUrl = createRedictUrl(request,routeUrl, prefix);
   RequestEntity requestEntity = createRequestEntity(request, redirectUrl);
   return route(requestEntity);
  } catch (Exception e) {
   return new ResponseEntity("REDIRECT ERROR", HttpStatus.INTERNAL_SERVER_ERROR);
  }
 }

 private String createRedictUrl(HttpServletRequest request, String routeUrl, String prefix) {
  String queryString = request.getQueryString();
  return routeUrl + request.getRequestURI().replace(prefix, "") +
    (queryString != null ? "?" + queryString : "");
 }

 private RequestEntity createRequestEntity(HttpServletRequest request, String url) throws URISyntaxException, IOException {
  String method = request.getMethod();
  HttpMethod httpMethod = HttpMethod.resolve(method);
  MultiValueMap<String, String> headers = parseRequestHeader(request);
  byte[] body = parseRequestBody(request);
  return new RequestEntity<>(body, headers, httpMethod, new URI(url));
 }

 private ResponseEntity<String> route(RequestEntity requestEntity) {
  RestTemplate restTemplate = new RestTemplate();
  return restTemplate.exchange(requestEntity, String.class);
 }

 private byte[] parseRequestBody(HttpServletRequest request) throws IOException {
  InputStream inputStream = request.getInputStream();
  return StreamUtils.copyToByteArray(inputStream);
 }

 private MultiValueMap<String, String> parseRequestHeader(HttpServletRequest request) {
  HttpHeaders headers = new HttpHeaders();
  List<String> headerNames = Collections.list(request.getHeaderNames());
  for (String headerName : headerNames) {
   List<String> headerValues = Collections.list(request.getHeaders(headerName));
   for (String headerValue : headerValues) {
    headers.add(headerName, headerValue);
   }
  }
  return headers;
 }
}

Spring 集成

Spring Controller,RequestMapping里把GET \ POST\PUT\DELETE 支持的请求带上,就能实现转发了。

@RestController
@RequestMapping(GraphDBController.DELEGATE_PREFIX)
@Api(value = "GraphDB", tags = {
  "graphdb-Api"
})
public class GraphDBController {

 @Autowired
 GraphProperties graphProperties;

 public final static String DELEGATE_PREFIX = "/graphdb";

 @Autowired
 private RoutingDelegate routingDelegate;

 @RequestMapping(value = "/**", method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE}, produces = MediaType.TEXT_PLAIN_VALUE)
 public ResponseEntity catchAll(HttpServletRequest request, HttpServletResponse response) {
  return routingDelegate.redirect(request, response, graphProperties.getGraphServer(), DELEGATE_PREFIX);
 }
}

以上就是spring boot实现超轻量级网关(反向代理、转发)的示例的详细内容,更多关于spring boot实现网关的资料请关注我们其它相关文章!

(0)

相关推荐

  • SpringBoot + Spring Security 基本使用及个性化登录配置详解

    Spring Security 基本介绍 这里就不对Spring Security进行过多的介绍了,具体的可以参考官方文档 我就只说下SpringSecurity核心功能: 认证(你是谁) 授权(你能干什么) 攻击防护(防止伪造身份) 基本环境搭建 这里我们以SpringBoot作为项目的基本框架,我这里使用的是maven的方式来进行的包管理,所以这里先给出集成Spring Security的方式 <dependencies> ... <dependency> <groupI

  • Spring Boot 日志配置方法(超详细)

    默认日志 Logback : 默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台.在运行应用程序和其他例子时,你应该已经看到很多INFO级别的日志了. 从上图可以看到,日志输出内容元素具体如下: 时间日期:精确到毫秒 日志级别:ERROR, WARN, INFO, DEBUG or TRACE 进程ID 分隔符:- 标识实际日志的开始 线程名:方括号括起来(可能会截断控制台输出) Logger名:通常使用源代码的类名 日志内容 添加日志依赖 假如mave

  • Springboot转发重定向实现方式解析

    1.转发 方式一:使用 "forword" 关键字(不是指java关键字),注意:类的注解不能使用@RestController 要用@Controller @RequestMapping(value="/test/test01/{name}" , method = RequestMethod.GET) public String test(@PathVariable String name) { return "forword:/ceng/hello.h

  • spring boot配置多个请求服务代理的完整步骤

    springboot 配置服务代理 有时候,我们可能有下边这样的需求: 即,针对于分布式服务,我们会有多种业务接口服务,但是服务器上可能只要求开放一个服务的端口,比如上图的restA项目端口是对外开放的,但是restB项目端口并未对外开放,这样带来的问题就是,用户无法直接请求restB项目. 那就想到了可以通过访问restA ,请求路径符合一定规范的时候,比如http://ip:port/test ,当请求中以rest 开头时,可以再转发请求到restB 项目中即可. 当然代理转发 ,有很多的解

  • Spring boot2X负载均衡和反向代理实现过程解析

    这篇文章主要介绍了Spring boot2X负载均衡和反向代理实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 zuul 是netflix开源的一个API Gateway 服务器 所有从设备或网站来的请求都会经过Zuul到达后端的Netflix应用程序. 作为一个边界性质的应用程序,Zuul提供了动态路由.监控.弹性负载和安全功能. 实现反向代理 1.服务注册发现中心Consul 启动 consul agent -dev 2.服务端

  • springboot与mybatis整合实例详解(完美融合)

    简介 从 Spring Boot 项目名称中的 Boot 可以看出来,Spring Boot 的作用在于创建和启动新的基于 Spring 框架的项目.它的目的是帮助开发人员很容易的创建出独立运行和产品级别的基于 Spring 框架的应用.Spring Boot 会选择最适合的 Spring 子项目和第三方开源库进行整合.大部分 Spring Boot 应用只需要非常少的配置就可以快速运行起来. Spring Boot 包含的特性如下: 创建可以独立运行的 Spring 应用. 直接嵌入 Tomc

  • Nginx反向代理springboot的jar包过程解析

    springboot项目部署到服务器常见的方式就是打成war包部署Tomcat或者打成jar包直接使用内置容易运行,很多人现在都打成war包部署到tomcat,这种方式虽然没问题 但是后期维护比较麻烦.从官方的说明中 打成jar部署是最好的方式,但是这样又有个问题 如果同时部署多个spring-boot项目 端口不一样 怎么通过域名来访问呢,接下来就需要Nginx出手了,Nginx 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.很适合部署springboot

  • 详解eclipse下创建第一个spring boot项目

    spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者.也就是说,Spring Boot是为了简化Spring开发而生,主要思想是降低spring的入门,使得新手可以以最快的速度让程序在spring框架下跑起来. 今天我们就来创建

  • springboot zuul实现网关的代码

    网关在微服务里的角色 在微服务架构体系里,网关是非常重要的一个环节,它主要实现了一些功能的统一处理,包括了: 统一授权 统一异常处理 路由导向 跨域处理 限流 实践一下 1 添加依赖 dependencies { implementation('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client') implementation('org.springframework.cloud:spring-cloud-s

  • spring boot实现超轻量级网关(反向代理、转发)

    在我们的rest服务中,需要暴露一个中间件的接口给用户,但是需要经过rest服务的认证,这是典型的网关使用场景.可以引入网关组件来搞定,但是引入zuul等中间件会增加系统复杂性,这里实现一个超轻量级的网关,只实现请求转发,认证等由rest服务的spring security来搞定. 如何进行请求转发呢? 熟悉网络请求的同学应该很清楚,请求无非就是请求方式.HTTP header,以及请求body,我们将这些信息取出来,透传给转发的url即可. 举例: /graphdb/** 转发到 Graph_

  • spring boot实现超轻量级网关的方法(反向代理、转发)

    在我们的rest服务中,需要暴露一个中间件的接口给用户,但是需要经过rest服务的认证,这是典型的网关使用场景.可以引入网关组件来搞定,但是引入zuul等中间件会增加系统复杂性,这里实现一个超轻量级的网关,只实现请求转发,认证等由rest服务的spring security来搞定. 如何进行请求转发呢? 熟悉网络请求的同学应该很清楚,请求无非就是请求方式.HTTP header,以及请求body,我们将这些信息取出来,透传给转发的url即可. 举例: /graphdb/** 转发到 Graph_

  • spring boot实现超轻量级网关(反向代理、转发)的示例

    作者: JadePeng 出处:https://www.cnblogs.com/xiaoqi/p/spring-boot-route.html 在我们的rest服务中,需要暴露一个中间件的接口给用户,但是需要经过rest服务的认证,这是典型的网关使用场景.可以引入网关组件来搞定,但是引入zuul等中间件会增加系统复杂性,这里实现一个超轻量级的网关,只实现请求转发,认证等由rest服务的spring security来搞定. 如何进行请求转发呢? 熟悉网络请求的同学应该很清楚,请求无非就是请求方式

  • spring boot整合CAS Client实现单点登陆验证的示例

    本文介绍了spring boot整合CAS Client实现单点登陆验证的示例,分享给大家,也给自己留个笔记,具体如下: 单点登录( Single Sign-On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要 登录一次 就可以访问所有相互信任的应用系统. CAS Client 负责处理对客户端受保护资源的访问请求,需要对请求方进行身份认证时,重定向到 CAS Server 进行认证.(原则上,客户端应用不再接受任何的用户名密码等

  • 在Spring Boot中从类路径加载文件的示例

    资源加载器 使用Java,您可以使用当前线程的classLoader并尝试加载文件,但是Spring Framework为您提供了更为优雅的解决方案,例如ResourceLoader. 您只需要自动连接ResourceLoader,然后调用getResource(„somePath")方法即可. 在Spring Boot(WAR)中从资源目录/类路径加载文件的示例 在以下示例中,我们从类路径中加载名为GeoLite2-Country.mmdb的文件作为资源,然后将其作为File对象检索. @Se

  • Spring Boot项目中实现文件上传功能的示例

    在实际项目中,文件上传是很多项目必不可少的一个功能.那么在 Spring Boot 项目中又是如何来实现文件上传功能的呢?一般来说,上传的文件可以保存到项目根目录下的某一文件夹中,但这样做显然是不太合适的.因此我们选择将文件上传到专门的文件服务器中.很多云计算厂商都提供文件存储服务.这里我选择的是阿里云的对象存储(OSS). 一.配置OSS 1. 导入SDK 首先,你需要注册阿里云的账号并开通对象存储服务.在准备工作完成之后,需要导入 JAVA 版本的 SDK,这里使用 maven 进行导入 <

  • Nginx反向代理转发tomcat的实现

    刚刚接触Nginx,记录下学习过程 先说正向代理,比如要访问youtube,但是不能直接访问,只能先找个翻墙软件,通过翻墙软件才能访问youtube. 翻墙软件就叫做正向代理. 所谓的反向代理,指的是用户要访问youtube,但是youtube悄悄地把这个请求交给bilibili来做,那么bilibili就是反向代理了. 在当前教程指的就是访问nginx,但是nginx把请求交给tomcat来做. 安装tomcat 参考文章:https://www.jb51.net/article/137839

  • 详解Nginx 利用代理转发请求示例

    我们米扑科技的业务遍布全球,有时国外的客户无法访问我们搭建在国内的服务,这就要求我们在国外服务器上搭建一个代理转发服务,用户请求国外服务器的域名,然后代理转发到国内,处理请求后返回结果给国外的客户.Nginx 不仅可以实现负载均衡,还可以实现反向代理转发,非常适合我们的使用场景,因此我们米扑科技采用 Nginx 利用代理转发请求实例. Nginx 利用代理转发请求实例 nginx 作为目前最流行的web服务器之一,可以很方便地实现反向代理. nginx 反向代理官方文档: NGINX REVER

  • Spring Boot腾讯云短信申请与使用示例

    1.在pom.xml文件中添加依赖 <dependency> <groupId>com.tencentcloudapi</groupId> <artifactId>tencentcloud-sdk-java</artifactId> <version>3.1.270</version> </dependency> 2.新建SmsConstant常量类保存需要用到的常量 public class SmsConst

随机推荐