Java替换RequstBody和RequestParam参数的属性

Java替换RequstBody和RequestParam参数的属性

本文主要讲解在Java环境中如何替换RequestBody和RequestParam参数中的属性
背景
近期由于接手的老项目中存在所有接口中新增一个加密串来给接口做一个加密效果(项目历史原因,不方便上Jwt授权这套),所以就研究了一下Http请求链路,发现可以通过 javax.servlet.Filter去实现

替换RequestParam参数
首先通过继续HttpServletRequestWrapper来达到获取和替换RequestParam中的参数信息,接下来我们通过javax.servlet.Filter去获取ServletRequest中参数的信息,并且定义对应规则,来实现替换参数
代码示例:

package com.simplemessage.cloudpayservice.infrastructure.config.http;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

/**

  • @CreateAt: 2023/10/24 12:13

  • @ModifyAt: 2023/10/24 12:13

  • @Version 1.0
    */
    public class MyRequestWrapper extends HttpServletRequestWrapper {

    private Map params = new HashMap<>();
    public MyRequestWrapper(HttpServletRequest request, Map newParams) {
    super(request);
    if(request.getParameterMap() != null){
    this.params.putAll(request.getParameterMap());
    }
    if(newParams != null){
    this.params.putAll(newParams);
    }
    }

    /**

    • 获取参数
    • @return
      */
      @Override
      public Map getParameterMap() {
      return params;
      }

    @Override
    public Enumeration getParameterNames() {
    Vector l = new Vector(params.keySet());
    return l.elements();
    }

    @Override
    public String[] getParameterValues(String name) {
    Object v = params.get(name);
    if (v == null) {
    return null;
    } else if (v instanceof String[]) {
    return (String[]) v;
    } else if (v instanceof String) {
    return new String[]{(String) v};
    } else {
    return new String[]{v.toString()};
    }
    }

    /**

    • 根据参数的key获取参数
    • @param name
    • @return
      */
      @Override
      public String getParameter(String name) {
      Object v = params.get(name);
      if (v == null) {
      return null;
      } else if (v instanceof String[]) {
      String[] strArr = (String[]) v;
      if (strArr.length > 0) {
      return strArr[0];
      } else {
      return null;
      }
      } else if (v instanceof String) {
      return (String) v;
      } else {
      return v.toString();
      }
      }
      }
      package com.simplemessage.cloudpayservice.infrastructure.config.http;

import com.fasterxml.jackson.core.io.JsonEOFException;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.RequestFacade;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.FilterConfig;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**

  • @CreateAt: 2023/10/24 12:16
  • @ModifyAt: 2023/10/24 12:16
  • @Version 1.0
    */
    @Slf4j

@WebFilter(filterName = "replaceGetRequestFilter", urlPatterns = {"/*"})
public class ReplaceGetRequestFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    long start = System.currentTimeMillis();
    //获取HttpServletRequest对象
    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    //判断当前是否为Get请求
    if ("GET".equalsIgnoreCase(httpServletRequest.getMethod())) {
    	// 获取参数信息
        String param= request.getParameter("param");
        //判断参数是否为空,为空则放行
        if (StringUtils.isEmpty(param)) {
            chain.doFilter(request, response);
            return;
        } else {
            Map<String, String[]> newParameterMap = new HashMap<>();
            // 替换参数(自定义规则)
            String newParama="test";
            newParameterMap.put("param", new String[]{newParama});
            // 实现参数替换
            MyRequestWrapper myRequestWrapper = new MyRequestWrapper(httpServletRequest, newParameterMap);
            chain.doFilter(myRequestWrapper, response);
        }

    } else {
        try {
            chain.doFilter(request, response);
        } catch (HttpMessageNotReadableException httpMessageNotReadableException) {
            log.error(((RequestFacade) request).getRequestURI() + ", " + httpMessageNotReadableException.getMessage());
        } catch (JsonEOFException jsonEOFException) {
            log.error(((RequestFacade) request).getRequestURI() + ", " + jsonEOFException.getMessage());
        }
    }
    long end = System.currentTimeMillis();
    log.info("{} 接口耗时:{} ms", httpServletRequest.getRequestURI(), (end - start));
}

@Override
public void destroy() {
}

}

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**

  • 注入bean
  • @CreateAt: 2023/10/30 9:57
  • @ModifyAt: 2023/10/30 9:57
  • @Version 1.0
    */

@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new ReplaceGetRequestFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}

替换RequestBody参数
主要思路就是通过获取Post中请求的输入流信息,解析输入流信息,按照对应的规则进行替换参数信息,最后将对应的流信息包装进行返回
代码示例:

package com.simplemessage.cloudpayservice.infrastructure.config.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.List;

/**

  • @version 1.0

  • @createAt: 2023/10/24 12:23:23

  • @modifyAt: 2023/10/24 12:23:23
    */
    @RestControllerAdvice
    @Slf4j
    public class DecryptRequestBodyHandler implements RequestBodyAdvice {

    /**

    • 该方法用于判断当前请求,是否要执行beforeBodyRead方法
    • methodParameter方法的参数对象
    • type方法的参数类型
    • aClass 将会使用到的Http消息转换器类类型
    • 注意:此判断方法,会在beforeBodyRead 和 afterBodyRead方法前都触发一次。
    • @return 返回true则会执行beforeBodyRead
      */

    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class> aClass) {
    return true;
    }
    //代码效果参考:http://www.intpipe.com/sitemap/post.xml
    /**

    • 在Http消息转换器执转换,之前执行

    • inputMessage 客户端请求的信息

    • parameter 参数信息

    • targetType 参数类型

    • converterType Http消息转换器类类型

    • @return 返回 一个自定义的HttpInputMessage
      */
      @Override
      public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) throws IOException {
      // 如果body是空内容直接返回原来的请求
      if (inputMessage.getBody().available() <= 0) {
      return inputMessage;
      }
      // 请求中的header信息
      HttpHeaders headers = inputMessage.getHeaders();

      // 将输入流读出来,注意 body 里面的流只能读一次
      ByteArrayOutputStream requestBodyDataByte = new ByteArrayOutputStream();
      try {
      //复制流信息
      IOUtils.copy(inputMessage.getBody(), requestBodyDataByte);
      } catch (Exception e) {
      log.error("参数流拷贝失败: ", e.toString());
      return inputMessage;
      }
      ByteArrayOutputStream requestBodyDataByteNew = null;
      try {
      JSONObject body = JSON.parseObject(requestBodyDataByte.toByteArray(), JSONObject.class);
      if (ObjectUtils.isEmpty(body)) {
      return inputMessage;
      }
      //自定义规则信息
      if (body.containsKey("param")) {
      String custId = body.getString("param");
      String newParam="";
      body.put("custId", newParam);
      requestBodyDataByteNew = new ByteArrayOutputStream();
      //拷贝流信息
      IOUtils.copy(new ByteArrayInputStream(body.toJSONString().getBytes()), requestBodyDataByteNew);
      }
      } catch (Throwable e) {
      log.error("流转换异常 ", e.toString());
      }
      // 如果上述发生异常,仍然使用原来的请求内容
      requestBodyDataByte = requestBodyDataByteNew != null ? requestBodyDataByteNew : requestBodyDataByte;
      InputStream rawInputStream = new ByteArrayInputStream(requestBodyDataByte.toByteArray());
      inputMessage.getHeaders().set(HttpHeaders.CONTENT_LENGTH, String.valueOf(rawInputStream.available()));
      return new HttpInputMessage() {
      @Override
      public HttpHeaders getHeaders() {
      return inputMessage.getHeaders();
      }

       @Override
       public InputStream getBody() throws IOException {
           return rawInputStream;
       }
      

      };
      }

    /**

    • 在Http消息转换器执转换,之后执行
    • body 转换后的对象
    • inputMessage 客户端的请求数据
    • parameter handler方法的参数类型
    • targetType handler方法的参数类型
    • converterType 使用的Http消息转换器类类型
    • @return 返回一个新的对象
      */
      @Override
      public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) {
      return body;
      }

    /**

    • 参数与afterBodyRead相同,不过这个方法body为空的情况
      */
      @Override
      public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) {
      return body;
      }
      }
posted @   vbcjnmkk  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示