springboot统一请求参数修改
http请求对象HttpServletRequest中的数据要么通过流(json请求时)或者参数的形式(form表单)向后台传输数据,如果是通过流的方式向后端传输数据,那么在后端读取数据都是一次性的,如果在拦截器或者AOP中读取过,则不能映射到controller的参数。但可以通过在过滤器中定义可复制的request进行读取,而不影响controller参数的映射。本文主要介绍如何通过过滤器实现可复制流来解决实际业务中遇到的相关问题。
假设这种场景:我需要将请求参数中的用户名进行解密。下述内容可以解决这个问题。
定义body请求包装类
public class BodyRequestWrapper extends HttpServletRequestWrapper {
private String body;
public BodyRequestWrapper(HttpServletRequest request, String context) {
super(request);
body = context;
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes("UTF-8"));
ServletInputStream servletInputStream = new ServletInputStream() {
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
定义form表单请求包装类
public class ParameterRequestWrapper extends HttpServletRequestWrapper {
private Map<String, String[]> params = new HashMap<String, String[]>();
public ParameterRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
this.params.putAll(request.getParameterMap());
}
/**
* 重载一个构造方法
*
* @param request
* @param extendParams
*/
public ParameterRequestWrapper(HttpServletRequest request, Map<String, String[]> extendParams) throws IOException {
this(request);
addAllParameters(extendParams);
}
@Override
public Enumeration<String> getParameterNames() {
return Collections.enumeration(params.keySet());
}
@Override
public String getParameter(String name) {
String[] values = params.get(name);
if (values == null || values.length == 0) {
return null;
}
return values[0];
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
public void addAllParameters(Map<String, String[]> otherParams) {
for (Map.Entry<String, String[]> entry : otherParams.entrySet()) {
addParameter(entry.getKey(), entry.getValue());
}
}
public void addParameter(String name, Object value) {
if (value != null) {
if (value instanceof String[]) {
params.put(name, (String[]) value);
} else if (value instanceof String) {
params.put(name, new String[]{(String) value});
} else {
params.put(name, new String[]{String.valueOf(value)});
}
}
}
@Override
public Map<String, String[]> getParameterMap() {
return this.params;
}
}
定义过滤器
@Component
@WebFilter(filterName = "myFilter", urlPatterns = "/")
@Order(10000)
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if(req instanceof HttpServletRequest){
HttpServletRequest request = (HttpServletRequest) req;
String contentType = request.getContentType();
//body形式(json)
if (contentType.equals(MediaType.APPLICATION_JSON_UTF8_VALUE)
|| contentType.equals(MediaType.APPLICATION_JSON_VALUE)) {
//获取request的body参数
String postContent = getBody(request);
//如果body中存在数据放入HttpServletRequest
if (StringUtils.isNotEmpty(postContent)) {
//修改、新增、删除参数
JSONObject jsStr = JSONObject.parseObject(postContent);
if(jsStr.containsKey("userName")){
jsStr.put("userName", "对用户名进行解密");
}
postContent = jsStr.toJSONString();
//将参数放入重写的方法中
request = new BodyRequestWrapper(request, postContent);
}
}
//form表单形式
if ((contentType.equals(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|| contentType.contains(MediaType.MULTIPART_FORM_DATA_VALUE))
&& !request.getParameterMap().isEmpty()) {
//修改、新增、删除参数
Map<String, String[]> parameterMap = request.getParameterMap();
//对请求参数进行处理
if(parameterMap.containsKey("userName")){
parameterMap.put("userName", new String[]{"对用户名进行解密"});
}
//将参数放入重写的方法中
request = new ParameterRequestWrapper(request, parameterMap);
}
chain.doFilter(request, response);
}else{
filterChain.doFilter(req, response);
}
}
//获取Request的body数据
private String getBody(ServletRequest request) {
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
InputStream inputStream = null;
try {
inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return stringBuilder.toString();
}
@Override
public void destroy() {
}
}
测试controller
@RestController
@RequestMapping("/user")
@Slf4j
public class IccAuthCallBackController {
@PostMapping("test1")
public Response test1(@RequestBody User user){
Response response=null;
return response;
}
@PostMapping("test2")
public Response test2(@RequestParam("userName")String userName){
IccAuthResponse response = null;
return response;
}
}