Springboot修改post请求接口入参或重新赋值方式

 更新时间:2025年05月12日 09:17:11   作者:小目标青年  
这篇文章主要介绍了Springboot修改post请求接口入参或重新赋值方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

前言

很久之前写过一篇就是自动填充接口参数的,利用的 HandlerMethodArgumentResolver 自定义注解

Springboot Controller接口默认自动填充 业务实体参数值

现在这一篇也差不多,达到的目的就是重新去给post请求的参数赋值、修改啥的。

不多说,开始。

首先知道一点,post请求的参数,一旦取出来就没了,因为是流数据。

所以老样子,我们写多一个HttpServletRequestWrapper :

BodyReaderHttpServletRequestWrapper

import org.apache.commons.lang3.StringUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;

/**
 * @Author : JCccc
 * @CreateTime : 2020/3/27
 * @Description :
 **/
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {

    private final byte[] body;

    /**
     * 所有参数的集合
     */
    private Map<String, String[]> parameterMap;


    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        BufferedReader reader = request.getReader();
        body = readBytes(reader);
        parameterMap = request.getParameterMap();
    }


    @Override
    public BufferedReader getReader() throws IOException {

        ServletInputStream inputStream = getInputStream();

        if (null == inputStream) {
            return null;
        }

        return new BufferedReader(new InputStreamReader(inputStream));
    }

    @Override
    public Enumeration<String> getParameterNames() {
        Vector<String> vector = new Vector<>(parameterMap.keySet());
        return vector.elements();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {

        if (body == null) {
            return null;
        }

        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {

            }

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }

    /**
     * 通过BufferedReader和字符编码集转换成byte数组
     *
     * @param br
     * @return
     * @throws IOException
     */
    private byte[] readBytes(BufferedReader br) throws IOException {
        String str;
        StringBuilder retStr = new StringBuilder();
        while ((str = br.readLine()) != null) {
            retStr.append(str);
        }
        if (StringUtils.isNotBlank(retStr.toString())) {
            return retStr.toString().getBytes(StandardCharsets.UTF_8);
        }
        return null;
    }
}

然后是我们这一期的核心,

DefaultDataFillHandlerMethodArgumentResolver

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.speediance.admin.auth.ShiroUtils;
import com.speediance.admin.dto.req.UserDefaultDataFill;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.Date;
import java.util.Objects;

@Component
public class DefaultDataFillHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(UserDefaultDataFill.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = webRequest.getNativeRequest( HttpServletRequest.class );
        BodyReaderHttpServletRequestWrapper myRequestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);
        // 从Request的包装类中读取数据
        BufferedReader reader = myRequestWrapper.getReader();
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        reader.close();
        JSONObject jsonObject = JSON.parseObject(sb.toString());
        Object bean = BeanUtils.instantiateClass(parameter.getParameterType());
        BeanWrapper beanWrapper = new BeanWrapperImpl(bean);
        //重新赋值
        for (String key : jsonObject.keySet()) {
            beanWrapper.setPropertyValue(key,jsonObject.get(key));
        }
        Long userId = //比如从数据库查出来 或者从token解析出来;
   
 
        //举例子给如入参自动填充 更新操作人
        beanWrapper.setPropertyValue("updateUserId", userId);
      
        return bean;
    }


}

然后就是重写一个自定义注解 ,相当于需要填充数据或者进入到参数修改,我们采用它标注:

UserDefaultDataFill

import java.lang.annotation.*;


@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UserDefaultDataFill {

}

然后就OK了,看看怎么用:

比如说一个更新接口,我们想默认填充上入参里面的 修改用户ID (简单举例,其余业务要修改值,赋值自己套用就可以)

然后可以看到我们的参数解析器里面的代码 (其实就是复制流拿出参数,修改完变成当前接口的bean):

OK,就到这。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Mybatis如何实现@Select等注解动态组合SQL语句

    Mybatis如何实现@Select等注解动态组合SQL语句

    这篇文章主要介绍了Mybatis如何实现@Select等注解动态组合SQL语句,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • java 示例讲解循环语句的使用

    java 示例讲解循环语句的使用

    顺序结构的程序语句只能被执行一次。如果您想要同样的操作执行多次,就需要使用循环结构,循环结构就是在循环条件满足的情况下,反复执行特定代码
    2022-04-04
  • SpringCloud整合Netty集群实现WebSocket的示例代码

    SpringCloud整合Netty集群实现WebSocket的示例代码

    文章主要介绍了SpringCloud整合Netty集群实现WebSocket的相关内容,包括服务注册和发现中心的配置,如使用Nacos、CommandLineRunner启动Netty服务等,还介绍了通过Redis实现消息发布订阅的机制,需要的朋友可以参考下
    2024-11-11
  • SpringBoot+VUE实现数据表格的实战

    SpringBoot+VUE实现数据表格的实战

    本文将使用VUE+SpringBoot+MybatisPlus,以前后端分离的形式来实现数据表格在前端的渲染,具有一定的参考价值,感兴趣的可以了解一下
    2021-08-08
  • JDBC中Statement的Sql注入问题详解

    JDBC中Statement的Sql注入问题详解

    这篇文章主要介绍了JDBC中Statement的Sql注入问题详解,sql注入攻击指的是通过构建特殊的输入作为参数传入web应用程序,而这些输入大都是sql语法里的一些组合,通过执行sql语句进而执行攻击者所要做的操作,需要的朋友可以参考下
    2023-10-10
  • Java中的内存模型JMM详细解读

    Java中的内存模型JMM详细解读

    这篇文章主要介绍了Java中的内存模型JMM详细解读,Java 对内存的抽象模型如下,每个线程都有一块自己的私有内存(也称为工作内存),当线程使用变量时,会把主内存里面的变量复制到工作内存,线程读写变量时操作的是自己工作内存中的变量,需要的朋友可以参考下
    2023-12-12
  • Java数据存储的“双子星”对决(Map和Set的区别)

    Java数据存储的“双子星”对决(Map和Set的区别)

    文章主要介绍了Java中Map和Set两种数据结构的定义、实现、方法及应用场景,Map用于存储键值对,键唯一,值可重复;Set用于存储唯一元素,无序,两者都提供了丰富的操作方法,如添加、删除、查找等,感兴趣的朋友一起看看吧
    2025-02-02
  • Ubuntu16.04 64位下JDK1.7的安装教程

    Ubuntu16.04 64位下JDK1.7的安装教程

    这篇文章主要为大家详细介绍了Ubuntu16.04 64位下JDK1.7的安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-09-09
  • Java中xxl-job实现分片广播任务的示例

    Java中xxl-job实现分片广播任务的示例

    本文主要介绍了Java中xxl-job实现分片广播任务的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • 多线程(多窗口卖票实例讲解)

    多线程(多窗口卖票实例讲解)

    下面小编就为大家带来一篇多线程(多窗口卖票实例讲解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08

最新评论