【请求代理】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+适配器模式正好满足我们业务场景需求;
功能实现的方式选择还是要考虑业务场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/51035.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于yolov8的口罩检测模型

项目介绍 本项目基于yolov8对图像进行训练&#xff0c;可以检测戴口罩的人与没有带口罩的人的图片和视频&#xff0c;除此之外&#xff0c;还提供了数据分析界面&#xff0c;支持检测过的信息转化为excel&#xff0c;信息可视化等功能 配置过程 软件开发环境:python3.9 系统…

前端开发:HTML与CSS

文章目录 前言1.1、CS架构和BS架构1.2、网页构成 HTML1.web开发1.1、最简单的web应用程序1.2、HTTP协议1.2.1 、简介1.2.2、 http协议特性1.3.3、http请求协议与响应协议 2.HTML概述3.HTML标准结构4.标签的语法5.基本标签6.超链接标签6.1、超链接基本使用6.2、锚点 7.img标签8.…

Apollo:实时通信架构CyberRT入门, my writer

1. 简介 1.1 从 ROS 系统说起 Apollo 最初用的中间件是 ROS(机器人操作系统),在 v3.0 之前用的都是基于 ROS 框架进行开发。概括来说,ROS 系统主要包含三方面: 第一是通信系统,ROS 是个分布式的松耦合系统,算法模块是以独立的进程形式存在的,也就是我们常说的 Node。R…

单击和一些案例

一、单击 1、单击概念 除了定位鼠标之外&#xff0c;processing鼠标还捕捉鼠标是否被单击。mousePressed在鼠标单击和不单击的情况下有不同的值。mousePressed变量是一种bool变量&#xff0c;也就是说它只有两个可能的值&#xff0c;真和假。当鼠标按下的时候mousePressed的值…

apache2和httpd web服务器

apache2和httpd web服务器 apache2和httpd web服务器是啥apache是软件基金会apache2是一个web服务httpd和apache2是同一个东西&#xff0c;但是不同linux发行版中叫法不一样。就是同一个东西&#xff0c;但是看上去有一些不一样。 apache2和httpd web服务器是啥 apache是软件基…

Scikit-learn内置的数据集

数据集是我们学习和研究机器学习不可或缺的基础&#xff0c;Scikit-learn库内置了丰富的数据集资源&#xff0c;非常适合初学者用来练习和验证机器学习算法的效果。 一、鸢尾花数据集 鸢尾花数据集&#xff08;Iris Dataset&#xff09;是机器学习领域中最著名的数据集之一&am…

【每日一篇】使用图神经网络进行交通速度预测的上下文感知知识图谱框架【为了自己方便读论文】

Context-aware knowledge graph framework for traffic speed forecasting using graph neural network 论文链接&#xff1a; https://arxiv.org/abs/2407.17703 翻译&#xff1a; 摘要 人类流动在空间和时间上受到城市环境的密切影响&#xff0c;构成了理解交通系统的重…

MarkTool之UDP

UDP客户端&#xff0c;主要作用是与UDP服务端连接进行数据通讯 1、连接参数有4个&#xff0c;绑定IP和Port&#xff0c;服务端IP和Port 2、接收数据和发送数据的参数设置&#xff0c;有16进制&#xff0c;有字符&#xff0c;有原始数据&#xff0c;都可进行选择 3、定时发送&a…

理解常见开源协议的区别

本文将介绍几种常见的开源许可证&#xff0c;包括GPL、LGPL、MIT、Apache、BSD 和 木兰协议&#xff08;Mulan PSL&#xff09;&#xff0c;并详细解释它们的区别。 1. GPL (GNU General Public License) GPL 是最著名和最常用的开源许可证之一&#xff0c;由自由软件基金会 …

泰安网站建设有几大特点

泰安网站建设的特点可以分为以下几个方面&#xff1a; 一、突出地域特色。泰安是山东省的一个地级市&#xff0c;具有悠久的历史和深厚的文化底蕴。在网站建设过程中&#xff0c;泰安的特色文化和旅游资源应得到充分的展示。可以通过优美的图片、详细的介绍和生动的文字&#x…

【Python 基础】字典和结构化数据 -1

字典和结构化数据 在本文中,我将介绍字典数据类型,它提供了一种灵活的访问和组织数据的方式。然后,结合字典与关于列表的知识,你将学习如何创建一个数据结构,对井字棋盘建模。 字典数据类型 像列表一样,“字典”是许多值的集合。但不像列表的下标,字典的索引可以使用…

【STM32】SysTick定时器

SysTick定时器 前言一、介绍最大计时时间 固件库函数体现用途 总结 前言 参考一下猫咪博主的文章&#xff0c;作为补充学习⇨【STM32】Systick滴答定时器 当然我主要还是跟着金善愚老师学的&#xff0c;我觉得他真的有种高中班主任的亲切感。那个1812的名号往那里一放&#x…

【vluhub】elasticsearch漏洞

Elasticsearch介绍 是Apache旗下的一个开源的、分布式、RESTful的搜索和分析引擎&#xff0c;适用于java语言项目 默认端口9200 kali中搭建ElasticHD, 即可未授权绕过ES可视化界面 直通车 https://github.com/360EntSecGroup-Skylar/ElasticHD/releases/download/1.4/elas…

Csrf复习(pikachu靶场和防御手段)

CSRF漏洞简介 CSRF又称跨站请求伪造&#xff0c;是指攻击者在用户登录的状态下&#xff08;浏览器保存了用户的cookie&#xff09;通过伪造恶意url诱导用户点击&#xff0c;借助用户的cookie网站权限&#xff08;冒充用户身份来进行非法操作&#xff0c;对于服务器来说是合法的…

视觉SLAM第二讲

SLAM分为定位和建图两个问题。 定位问题 定位问题是通过传感器观测数据直接或间接求解位置和姿态。 通常可以分为两类&#xff1a;基于已知地图的定位和基于未知地图的定位。 基于已知地图的定位 利用预先构建的地图&#xff0c;结合传感器数据进行全局定位。SLAM中的全局…

如何利用开源Bug管理系统提高团队效率

国内外主流的10款开源bug管理系统对比&#xff1a;PingCode、Worktile、Trac、WebIssues、MantisBT、Bugzilla 、Fossil、The Bug Genie、TestLink 、OpenProject。 在软件开发的复杂世界中&#xff0c;Bug管理可能是一个令人头疼的问题&#xff0c;尤其是当工具不足以捕捉和解…

这才是做项目的正确打开方式

基于大数据的推荐机制&#xff0c;对于没有接触到信息的人而言&#xff0c;会认为获取行业外的信息会很困难&#xff0c;对于已经接触到信息的人而言&#xff0c;又会出现选择困难症。当系统对你锁定标签后&#xff0c;就会频繁的给你推荐跟标签对应的信息&#xff0c;信息一多…

【传知代码】智慧医疗:纹理特征VS卷积特征(论文复现)

在这个无处不在的技术革新的时代&#xff0c;计算机视觉和机器学习成为了医疗领域中不可或缺的力量。在这篇文章中&#xff0c;我们将探讨两种突出的技术&#xff1a;纹理特征和卷积特征。它们如何在医学影像分析中竞争与协作&#xff0c;为医生提供更深入、更精确的诊断信息&a…

iOS基础---常用三方库:Masonry、SDWebImage

系列文章目录 iOS基础—多线程&#xff1a;GCD、NSThread、NSOperation iOS基础—Category vs Extension iOS基础—常用三方库&#xff1a;Masonry、SDWebImage 文章目录 系列文章目录一、Masonry1.Masonry简介2.使用示例3.源码剖析 二、SDWebImage1.SDWebImage简介2.主要功能…

不同WEB下的的ApplicationContext的选择

依赖 ApplicationContext类型选择 默认情况下&#xff0c;spring通过选择的web端的框架来选择使用哪个ApplicationContext子类&#xff0c;默认情况下我们一般使用spring mvc框架&#xff0c;这个时候AC的实现类为 org.springframework.boot.web.servlet.context.AnnotationC…