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)

相关推荐

  • Springboot实现VNC的反向代理功能

    背景 ​ 用户需要通过前端HTML页面的noVNC(noVNC是什么?)客户端连接底层VNC Server服务端,为了防止VNC Server的IP暴露,因此需要做一层代理.正常情况下使用Nginx.Apache等都可以搞定,但是由于项目架构的一些问题,暂时不能再加一台反向代理服务器,所以决定写一个单独的模块实现反向代理的功能. ​ 在网上和Github上找了一下,使用了HTTP-Proxy-Servlet,引入该依赖搭建一个Spring Boot项目. 搭建 引入代理的依赖 <dependen

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

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

  • 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实现超轻量级网关(反向代理、转发)的示例

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

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

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

  • Spring Boot集成MyBatis访问数据库的方法

    基于spring boot开发的微服务应用,与MyBatis如何集成? 集成方法 可行的方法有: 1.基于XML或者Java Config,构建必需的对象,配置MyBatis. 2.使用MyBatis官方提供的组件,实现MyBatis的集成. 方法一 建议参考如下文章,完成集成的验证. MyBatis学习 之 一.MyBatis简介与配置MyBatis+Spring+MySql 基于Spring + Spring MVC + Mybatis 高性能web构建 spring与mybatis三种整合

  • Spring Boot使用Druid和监控配置方法

    Spring Boot默认的数据源是:org.apache.tomcat.jdbc.pool.DataSource Druid是Java语言中最好的数据库连接池,并且能够提供强大的监控和扩展功能. 下面来说明如何在 Spring Boot 中配置使用Druid (1)添加Maven依赖 (或jar包)\ <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId&g

  • 移动开发Spring Boot外置tomcat教程及解决方法

    springboot微服务内置了tomcat,在工程目录下执行:mvn clean package,可以将项目打成jar,通过java -jar jar包名.jar启动项目. 有哪些场景需要将springboot打成war包去部署呢? 1.一个tomcat管理多个项目 2.springboot整合jsp等 解决方法: 1.<packaging>jar</packaging>中的jar改成war 2.引入依赖: <dependency> <groupid>or

  • Spring Boot中使用MongoDB数据库的方法

    MongoDB数据库简介 简介 MongoDB是一个高性能,开源,无模式的,基于分布式文件存储的文档型数据库,由C++语言编写,其名称来源取自"humongous",是一种开源的文档数据库──NoSql数据库的一种.NoSql,全称是 Not Only Sql,指的是非关系型的数据库. 特点 MongoDB数据库的特点是高性能.易部署.易使用,存储数据非常方便.主要功能特性有: * 面向集合存储,易存储对象类型的数据. * 模式自由. * 支持动态查询. * 支持完全索引,包含内部对象

  • Spring Boot 中使用cache缓存的方法

    一.什么是缓存 Cache Cache 一词最早来自于CPU设计 当CPU要读取一个数据时,首先从CPU缓存中查找,找到就立即读取并送给CPU处理:没有找到,就从速率相对较慢的内存中读取并送给CPU处理,同时把这个数据所在的数据块调入缓存中,可以使得以后对整块数据的读取都从缓存中进行,不必再调用内存.正是这样的读取机制使CPU读取缓存的命中率非常高(大多数CPU可达90%左右),也就是说CPU下一次要读取的数据90%都在CPU缓存中,只有大约10%需要从内存读取.这大大节省了CPU直接读取内存的

  • Spring Boot 2.0多数据源配置方法实例详解

    两个数据库实例,一个负责读,一个负责写. datasource-reader: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://192.168.43.61:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false username: icbc password: icbc driver-class-na

  • 在Spring Boot中实现HTTP缓存的方法

    缓存是HTTP协议的一个强大功能,但由于某些原因,它主要用于静态资源,如图像,CSS样式表或JavaScript文件,但是,HTTP缓存不仅限于这些,还可以将其用于动态计算的资源. 通过少量工作,您可以加快应用程序并改善整体用户体验.在本文中,您将学习 如何使用内置的HTTP响应缓存机制来实现缓存SpringBoot控制器的结果 . 1.如何以及何时使用HTTP响应缓存? 您可以在应用程序的多个层上进行缓存.数据库具有其缓存存储,Web客户端也在其需要重用的信息.HTTP协议负责网络通信.缓存机

随机推荐