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

在我们的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)

相关推荐

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

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

  • springboot zuul实现网关的代码

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

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

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

  • 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来搞定. 如何进行请求转发呢? 熟悉网络请求的同学应该很清楚,请求无非就是请求方式

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

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

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

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

  • Spring Boot超详细分析启动流程

    目录 一.Spring Boot 工程结构 二.Spring Boot 启动流程 三.Spring Boot 启动流程源码剖析 1.创建一个Spring Boot 工程 2.SpringBootApplication启动入口 3.Spring Boot 初始化分析 4.Spring Boot 启动深入分析 四.总结 一.Spring Boot 工程结构 下载Spring Boot工程源码, 下载地址 模块代码结构: 比较重要的是Spring-boot.Spring-boot-autoconfig

  • 利用Nginx反向代理与负载均衡搭建多人测试环境详解

    前言 假如我们使用 git 进行版本控制,在一个大型网站中,开发人员在不同的分支上开发不同的需求,当一个需求开发完成需要测试,我们会把这个分支告诉测试人员,然后测试人员在测试机的网站目录拉取这个分支进行测试. 设想这样一个场景:当只有一个分支提测的时候,在测试机上可以直接拉取这个分支的代码进行测试,但是如果同时有多个分支都要同时进行测试,那么就没办法在一台测试机上同时进行了. 因为这台测试机网站目录只有一个,我们无法同时拉取不同分支的代码,那么如何在一台测试机上同时支持多人测试不同的分支呢? 实

  • Nginx反向代理配置的全过程记录

    一.准备工作 Linux系统安装Tomcat,使用默认端口8080,启动Tomcat服务器 可以正常访问 接下来想要通过Nginx反向代理,转发请求到Tomcat服务器.对外暴露的是Nginx反向代理服务器的端口号,而Tomcat不对外暴露.浏览器不能直接访问到Tomcat,而是通过Nginx反向代理服务器才能访问到Tomcat 二.反向代理配置 在Windows系统的host文件进行域名和IP地址映射关系的配置 可以通过域名8080端口访问到Tomcat服务器 然后在Nginx进行请求转发的配

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

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

随机推荐