Springboot修改post请求接口入参或重新赋值方式
目录
- 前言
- BodyReaderHttpServletRequestWrapper
- DefaultDataFillHandlerMethodArgumentResolver
- UserDefaultDataFill
- 总结
前言
很久之前写过一篇就是自动填充接口参数的,利用的 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 intJTHQOsrYey read() throws IOException { return baisandroid.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.BeanWrapphpperImpl; 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(); phpJSONObject jsonObject javascript= 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,就到这。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。
精彩评论