news 2026/4/4 18:04:34

SpEL表达式动态修改参数和请求体

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpEL表达式动态修改参数和请求体

在现代Web应用开发中,我们经常需要在请求到达最终处理器之前对请求数据进行动态修改。本文将介绍如何使用Spring的SpEL(Spring Expression Language)表达式来动态修改HTTP请求的参数和请求体,并通过一个完整的示例展示实现过程。

整体架构概述

整个解决方案的核心流程包括:

1. HandlerInterceptor拦截请求

使用Spring的HandlerInterceptor接口来拦截请求,在请求被实际处理前进行预处理:

publicclassSmartRouterInterceptorimplementsHandlerInterceptor{privatefinalSmartRouterManagersmartRouterManager;publicSmartRouterInterceptor(SmartRouterManagersmartRouterManager){this.smartRouterManager=smartRouterManager;}@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{returnsmartRouterManager.rule(request,response);}}

SmartRouterInterceptor作为拦截器,将请求交给SmartRouterManager进行规则处理,这是整个流程的入口点。

2. 重新封装HttpServletRequestWrapper以支持请求体反复读取

由于HTTP请求体只能被读取一次,我们需要创建一个可变的请求包装器来支持多次读取和修改:

publicclassMutableHttpServletRequestWrapperextendsHttpServletRequestWrapper{privateMap<String,String[]>modifiedParams=newHashMap<>();privatebyte[]modifiedBody;privateBufferedReaderbodyReader;publicMutableHttpServletRequestWrapper(HttpServletRequestrequest)throwsIOException{super(request);// 复制原始参数modifiedParams.putAll(request.getParameterMap());// 读取并缓存原始请求体if(isRequestBodySupported(request)){InputStreaminputStream=request.getInputStream();modifiedBody=StreamUtils.copyToByteArray(inputStream);bodyReader=newBufferedReader(newInputStreamReader(newByteArrayInputStream(modifiedBody),StandardCharsets.UTF_8));}}@OverridepublicServletInputStreamgetInputStream()throwsIOException{if(modifiedBody==null){returnsuper.getInputStream();}finalByteArrayInputStreambyteArrayInputStream=newByteArrayInputStream(modifiedBody);returnnewServletInputStream(){@OverridepublicbooleanisFinished(){returnbyteArrayInputStream.available()==0;}@OverridepublicbooleanisReady(){returntrue;}@OverridepublicvoidsetReadListener(ReadListenerreadListener){}@Overridepublicintread()throwsIOException{returnbyteArrayInputStream.read();}};}// 其他重写方法...}

这个包装器类解决了原生HttpServletRequest只能读取一次请求体的问题,通过缓存机制实现了请求体的重复读取。

3. 使用SpEL表达式修改参数和请求体

核心功能是使用SpEL表达式来动态修改请求数据:

@UtilityClasspublicclassSpelParamModifier{privatestaticfinalExpressionParserPARSER=newSpelExpressionParser();publicvoidmodifyParam(Map<String,String[]>params,StringspelExpression){StandardEvaluationContextcontext=newStandardEvaluationContext();context.setVariable("params",params);PARSER.parseExpression(spelExpression).getValue(context);}publicvoidmodifyJsonBody(Map<String,Object>params,StringspelExpression){StandardEvaluationContextcontext=newStandardEvaluationContext();context.setVariable("params",params);PARSER.parseExpression(spelExpression).getValue(context);}}

SmartRouterManager中集成这些组件:

if(StringUtils.hasText(mapRule)||StringUtils.hasText(bodyRule)){MutableHttpServletRequestWrappermutableRequest=newMutableHttpServletRequestWrapper(request);if(StringUtils.hasText(mapRule)){Map<String,String[]>modifiedMap=newHashMap<>(mutableRequest.getParameterMap());SpelParamModifier.modifyParam(modifiedMap,mapRule);modifiedMap.forEach(mutableRequest::setParameter);}if(StringUtils.hasText(bodyRule)){StringoriginalBody=StreamUtils.copyToString(mutableRequest.getInputStream(),StandardCharsets.UTF_8);Map<String,Object>bodyMap=OBJECT_MAPPER.readValue(originalBody,Map.class);SpelParamModifier.modifyJsonBody(bodyMap,bodyRule);StringmodifiedBody=OBJECT_MAPPER.writeValueAsString(bodyMap);mutableRequest.setJsonBody(modifiedBody);}request=mutableRequest;}

实际应用场景

这种设计模式特别适用于以下场景:

  • API网关:在请求转发前修改请求参数或请求体
  • 路由规则:根据不同条件动态修改请求内容
  • 参数验证和清理:在业务逻辑处理前统一修改请求数据
  • A/B测试:根据规则动态修改请求参数进行实验

总结

通过结合使用HandlerInterceptorHttpServletRequestWrapper和SpEL表达式,我们可以创建一个灵活的请求处理系统,能够在运行时动态修改HTTP请求的参数和请求体。这种方案提供了高度的灵活性和可扩展性,使得我们能够根据业务需求编写复杂的请求修改规则。


示例代码地址:

Gitee

Github

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/28 12:12:07

Python的PIL如何转Base64字符串:完整指南

在Web开发、图像处理或API交互中&#xff0c;我们经常需要将图像转换为Base64字符串以便传输或存储。本文将详细介绍如何使用Python的PIL&#xff08;Pillow&#xff09;库将图像转换为Base64编码字符串&#xff0c;并提供多种实用场景的示例代码。 一、Base64编码简介 Base64是…

作者头像 李华
网站建设 2026/3/30 8:22:32

前沿AI论文工具排行榜:10款支持降重与自动写作的AIGC应用

工具名称核心优势适用场景aicheck快速降AIGC率至个位数AIGC优化、重复率降低aibiye智能生成论文大纲论文结构与内容生成askpaper文献高效整合开题报告与文献综述秒篇降重效果显著重复率大幅降低一站式论文查重降重查重改写一站式完整论文优化深度AI降重深度改写保留原意文本结构…

作者头像 李华
网站建设 2026/4/3 7:37:42

互联网的神经网络:OSI七层分层模型深度讲解

本文深入探讨计算机网络体系结构的基础理论&#xff0c;通过详细分析OSI七层模型的每一层功能、协议、数据流向以及实际应用场景&#xff0c;帮助技术人员建立对网络通信的全面理解。 第一部分&#xff1a;从混乱到秩序——为什么需要分层 当人们第一次接触计算机网络时&#…

作者头像 李华