【请求代理】springboot单机服务基于过滤器Filter实现第三方服务器接口请求代理功能
springboot单机服务基于过滤器Filter实现第三方服务器接口请求代理功能
- 一、前言
 - 二、解决思路
 - 三、基于gateway实现
 - 四、基于过滤器Filter实现
 - 五、问题总结
 
**注:本文源码获取或者更多资料,关注公众号:技术闲人**
 
一、前言
在项目开发时会遇到web端/接口请求第三方服务接口的场景,对web请求来说最后请求的服务地址是一个,避免跨域问题,在微服务场景经常使用gateway等网关服务实现,或者使用nginx代理组件实现,但是不同三方服务有不同的鉴权要求,但是后端服务最好有相同的鉴权;
 
二、解决思路
在非微服务架构和三方不同鉴权接口的服务场景下,通过过滤器Filter实现请求转发,并使用适配器设计模式,兼容不同的三方服务请求(鉴权),减少重复代码开发,也能监控所有的服务请求,并对所有请求做限流、统计等操作;
三、基于gateway实现
在没有spring-boot-starter-web依赖的场景下可以使用gateway,Spring MVC(基于Servlet的Web应用程序)和Spring Cloud Gateway(基于反应式编程的API网关),但是这两个组件是不兼容的。Spring Cloud Gateway是专为反应式编程设计的,使用Spring WebFlux作为底层框架,而Spring MVC则基于Servlet API。
gateway实现代码:
package com.sk.proxytest;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;@SpringBootApplication
public class ProxyTestApplication {public static void main(String[] args) {SpringApplication.run(ProxyTestApplication.class, args);}@Beanpublic RouteLocator myRoutes(RouteLocatorBuilder builder) {return builder.routes().route(p -> p.path("/test/**").uri("http://127.0.0.1:8089/api")).build();}}
 
四、基于过滤器Filter实现
本文主要使用过滤器Filter实现,既能控制代理请求,又能最少开发量;
GET请求结果
 
 POST请求结果
 
 实现源码:
ProxyFilter.java
package com.sk.proxytest.proxy;import com.sk.proxytest.proxy.bean.ProxyParam;
import com.sk.proxytest.proxy.bean.ProxyResult;
import com.sk.proxytest.proxy.strategy.ProxyHandleService;
import com.sk.proxytest.proxy.strategy.ProxyHandleStrategyFactory;
import com.sk.proxytest.proxy.strategy.ProxyStrategyContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;@Slf4j
@Configuration
@WebFilter(filterName = "ProxyFilter", urlPatterns = "/proxy/*")
public class ProxyFilter implements Filter {@Resourceprivate RestTemplate restTemplate;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;String proxyType = request.getHeader("proxy-type");ProxyStrategyContext proxyStrategyContext = new ProxyStrategyContext();ProxyHandleService proxyHandleService = ProxyHandleStrategyFactory.getProxyHandleStrategy(proxyType);proxyStrategyContext.setProxyHandleStrategy(proxyHandleService);ProxyResult proxyResult = proxyStrategyContext.handleProxy(new ProxyParam());boolean flag = true;if (null != proxyResult) {PrintWriter writer = null;try {String body = IOUtils.toString(request.getInputStream());HttpEntity<?> entity = new HttpEntity<>(body, proxyResult.getHeaders());String url = proxyResult.getProxyUrl() + getNewUrl(request);log.info("-----------new-url:{}", url);ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.resolve(request.getMethod()), entity, String.class);response.setStatus(responseEntity.getStatusCodeValue());writer = response.getWriter();writer.write(responseEntity.getBody());writer.flush();flag = false;} catch (Exception e) {log.error("------error:{}", e);} finally {if (writer != null) {writer.close();}}}if (flag) {chain.doFilter(request, response);}}@Overridepublic void destroy() {Filter.super.destroy();}//获取被代理的url和参数private String getNewUrl(HttpServletRequest request) {String proxyUrl = request.getRequestURI().replace("/proxy", "");Map<String, String[]> parameterMap = request.getParameterMap();int i = 0;for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {String key = entry.getKey();String value = entry.getValue()[0];if (i == 0) {proxyUrl = proxyUrl + "?" + key + "=" + value;} else {proxyUrl = proxyUrl + "&" + key + "=" + value;}}return proxyUrl;}
}
 
ProxyHandleService.java
package com.sk.proxytest.proxy.strategy;import com.sk.proxytest.proxy.bean.ProxyParam;
import com.sk.proxytest.proxy.bean.ProxyResult;public interface ProxyHandleService {ProxyResult proxyHandle(ProxyParam proxyParam);}
 
AlibabaProxyHandleStrategy.java
package com.sk.proxytest.proxy.strategy;import com.sk.proxytest.proxy.bean.ProxyParam;
import com.sk.proxytest.proxy.bean.ProxyResult;
import org.springframework.http.HttpHeaders;public class AlibabaProxyHandleStrategy implements ProxyHandleService {@Overridepublic ProxyResult proxyHandle(ProxyParam proxyParam) {HttpHeaders headers = new HttpHeaders();//TODO 根据三方服务登录接口获取鉴权信息String token = "token--------";headers.add("token", token);headers.add("Content-Type","application/json");//三方服务ip和portString ip = "127.0.0.1";String port = "8080";String proxyUrl = "http://" + ip + ":" + port;return new ProxyResult(headers, proxyUrl);}
}
 
ProxyHandleStrategyFactory.java
package com.sk.proxytest.proxy.strategy;import java.util.HashMap;
import java.util.Map;public class ProxyHandleStrategyFactory {private static Map<String, ProxyHandleService> proxyHandleServiceMap;static {proxyHandleServiceMap = new HashMap<>();proxyHandleServiceMap.put("alibaba", new AlibabaProxyHandleStrategy());}public static ProxyHandleService getProxyHandleStrategy(String proxyType){return proxyHandleServiceMap.get(proxyType);}}
 
ProxyStrategyContext.java
package com.sk.proxytest.proxy.strategy;import com.sk.proxytest.proxy.bean.ProxyParam;
import com.sk.proxytest.proxy.bean.ProxyResult;public class ProxyStrategyContext {private ProxyHandleService proxyHandleService;public void setProxyHandleStrategy(ProxyHandleService proxyHandleService){this.proxyHandleService = proxyHandleService;}public ProxyResult handleProxy(ProxyParam proxyParam){if(proxyHandleService != null){return proxyHandleService.proxyHandle(proxyParam);}return null;}}
 
五、问题总结
在单机服务中,gateway过于重,并且与springMVC有冲突,nginx代理服务不能同一鉴权,或者同一鉴权太过于麻烦,过滤器Filter+适配器模式正好满足我们业务场景需求;
 功能实现的方式选择还是要考虑业务场景。
相关文章:
【请求代理】springboot单机服务基于过滤器Filter实现第三方服务器接口请求代理功能
springboot单机服务基于过滤器Filter实现第三方服务器接口请求代理功能 一、前言二、解决思路三、基于gateway实现四、基于过滤器Filter实现五、问题总结 **注:本文源码获取或者更多资料,关注公众号:技术闲人**一、前言 在项目开发时会遇到w…...
.NET Core异步编程与多线程解析:提升性能与响应能力的关键技术
在.NET Core中,异步编程和多线程是构建高性能应用程序的核心技能。理解这两个概念不仅可以提升应用程序的响应能力,还能优化资源使用。本文将深入剖析异步编程和多线程的关键知识点,提供代码示例,并附上步骤以帮助理解。 1. 异步…...
Photoshop(PS) 抠图简单教程
目录 快速选择 魔棒 钢笔 橡皮擦 蒙版 通道 小结 可以发现,ps逐渐成为必备基础的办公软件。本文让ps新手轻松学会抠图。 快速选择 在抠图之前,先了解下选区的概念。ps中大多数的抠图操作都是基于选区的,先选区再Ctrl J提取选区。而快…...
项目管理中的常用工件(二):可视化工件
项目管理中的常用工件(二):可视化工件 亲和图(affinity diagram)因果图(cause-and-effect diagram)直方图(histogram)流程图(flowchart)散点图&am…...
Git入门与实战:版本控制的艺术
🍁 作者:知识浅谈,CSDN签约讲师,CSDN博客专家,华为云云享专家,阿里云专家博主 📌 擅长领域:全栈工程师、爬虫、ACM算法 🔥 微信:zsqtcyw 联系我领取学习资料 …...
[Mysql-DML数据操作语句]
目录 数据增加:INSERT 全字段插入: 部分字段插入: 一次性添加多条: 数据修改:UPDATE 数据删除:DELECT delete truncate drop 区别 数据增加:INSERT 总体格式:insert into 表…...
Tableau入门|数据可视化与仪表盘搭建
原视频链接(up:戴戴戴师兄),文章为笔者的自学笔记,用于复习回顾,原视频下方有原up整理的笔记,更加直观便捷。因为视频中间涉及的细节较多,建议一边操作,一边学习。 整体介绍 可视化…...
API 技术开发分享:连接电商平台数据获取的桥梁
在当今数字化的时代,API(Application Programming Interface,应用程序编程接口)技术成为了实现不同系统之间通信和数据交换的关键。它就像是一座无形的桥梁,使得各种应用能够相互协作,共享资源,…...
区块链如何助力数字版权保护和内容创作者的权益?
区块链技术可以助力数字版权保护和内容创作者的权益,主要有以下几个方面: 去中心化的版权登记和溯源:区块链可作为一个可信的去中心化数据库,记录并验证数字内容的版权信息。内容创作者可以将自己的作品信息存储在区块链上&#x…...
记一次老旧项目的整体技术升级
最近给公司采购的老旧的 node8 vue2.6 webpack3 npm 项目做构建优化 背景:整个项目 build 一次 20 min ,本地冷启动和热更新也忒慢,依赖 npm i 一下也得装个 20 min 众所周知,Node 版本,依赖包管理工具 和 构建工…...
2024年最受欢迎的五大上网审计设备和软件
在2024年的市场上,上网行为审计设备和软件种类繁多,它们帮助企业监控和管理员工的网络活动,确保网络安全并提高工作效率。下面是一些受欢迎的上网行为审计设备和软件。 2024年最受欢迎的上网行为审计设备和软件如下 1.安企神软件:…...
sed利用脚本处理文件
一、sed是什么 sed 命令是利用脚本来处理文本文件。它可以依照脚本的指令来处理、编辑文本文件。主要用来自动编 辑一个或多个文件、简化对文件的反复操作、编写转换程序等。 二、sed的原理 读入新的一行内容到缓存空间; 从指定的操作指令中取出第一条指令&…...
泰山派RK3566开发板800x1280MIPI屏设备树补丁
泰山派RK3566开发板800x1280MIPI屏设备树补丁 泰山派下800 X 1280分辨率MIPI屏调试,设备树补丁如下: https://download.csdn.net/download/qq_45143522/89584066 用kernel.patch文件,在泰山派内核源码下打补丁即可完成更新,或者…...
informer中的indexer机制的实现分析与源码解读
1. 背景 client-go工具下的tools/cache.indexer为informer提供缓存与索引的能力。可以实现快速通过索引找到对应的对象(pod, deployment,secret,configmap等)。 indexer再informer机制中的使用图示: indexer包括2部分: 一部分是store用于实际数据的存储,…...
英特尔宣布针对对Llama 3.1进行优化 以提升所有产品的性能
日前Meta正式发布了Llama 3.1开源大模型,以其庞大的参数量和卓越性能,首次在多项基准测试中击败了GPT-4o等业界领先的闭源模型。允许开发者自由地进行微调、蒸馏,甚至在任何地方部署,这种开放性为AI技术的普及和创新提供了无限可能…...
Python3网络爬虫开发实战(1)爬虫基础
一、URL 基础 URL也就是网络资源地址,其满足如下格式规范 scheme://[username:password]hostname[:port][/path][;parameters][?query][#fragment] scheme:协议,常用的协议有 Http,https,ftp等等;usern…...
Redis的五种数据类型与命令
目录 引言 一 Redis的特性 二 Redis的安装 三 Redis的优点 四 Redis的五种数据类型与命令 五 Redis的配置文件 引言 Redis是什么? Remote Dictionary Service(远程字典服务器) Redis 是一个开源的(BSD许可)的,C语言编写的,高性能的数…...
RocketMQ的详细讲解(四种mq的对比(activeMq、rabbitmq、rocketmq、kafka))
20240729 RocketMQ1 mq的三大作用 异步、削峰限流、解耦合2. 四种mq的对比(activeMq、rabbitmq、rocketmq、kafka)3 rocketmq特点1. 平台无关2. 能提供什么样的功能 4 rocketMq4.1 broker中的标题,来约束读和写4.2 rocketmq的结构4.3 读和写的…...
除了GPT,还有哪些好用的AI工具?
最强AI视频生成:小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频百万播放量https://aitools.jurilu.com/ 多得很,这20个免费的国产AI工具,打工人必备,除了比chatGPT好用,甚至还可以用来变现…...
04 | 深入浅出索引(上)
此系列文章为极客时间课程《MySQL 实战 45 讲》的学习笔记! 索引的常见模型 可以提供查询效率的数据结构有很多,常见的有三种:哈希表、有序数组、搜索数。 哈希表是一种以 key-value 形式存储的数据结构。输入一个 key,通过固定…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
