SpringBoot 拦截器获取 @RequestBody 参数

您所在的位置:网站首页 spring拦截器获取json SpringBoot 拦截器获取 @RequestBody 参数

SpringBoot 拦截器获取 @RequestBody 参数

2024-07-01 11:22| 来源: 网络整理| 查看: 265

前言

接手了一个 SpringBoot 项目,原本是用的 form-data 的格式来请求接口,但后来由于客户端那边说无法使用 form-data 格式请求接口,只好由我来修改原后端项目将请求格式一律改为 json 请求。

我看到该项目中写了拦截器,所以我就在拦截器中使用 getInputStream 来读取请求的 json 数据。

但是该方式只能读取一次,所以当使用拦截器时,controller 已经不能获取 body 中的参数。所以需要增加一个过滤器来解决,使流可以重复读取。

实现方案分为两个文件,代码如下:

HttpContextUtils package com.chuangyou.config; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; /** * HttpContextUtils * * @author itdragons */ public class HttpContextUtils { /** * 获取query参数 * * @param request * @return */ public static Map getParameterMapAll(HttpServletRequest request) { Enumeration parameters = request.getParameterNames(); Map params = new HashMap(); while (parameters.hasMoreElements()) { String parameter = parameters.nextElement(); String value = request.getParameter(parameter); params.put(parameter, value); } return params; } /** * 获取请求Body * * @param request * @return */ public static String getBodyString(ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = request.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } } HttpServletRequest 过滤器:流可重复读 package com.chuangyou.config; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; 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; /*** * HttpServletRequest 过滤器 * 解决: request.getInputStream()只能读取一次的问题 * 目标: 流可重复读 */ @Component @WebFilter(filterName = "HttpServletRequestFilter", urlPatterns = "/") @Order(10000) public class HttpServletRequestFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { ServletRequest requestWrapper = null; if (servletRequest instanceof HttpServletRequest) { requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest); } //获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中 // 在chain.doFiler方法中传递新的request对象 if (null == requestWrapper) { filterChain.doFilter(servletRequest, servletResponse); } else { filterChain.doFilter(requestWrapper, servletResponse); } } @Override public void destroy() { } /*** * HttpServletRequest 包装器 * 解决: request.getInputStream()只能读取一次的问题 * 目标: 流可重复读 */ public class RequestWrapper extends HttpServletRequestWrapper { /** * 请求体 */ private String mBody; public RequestWrapper(HttpServletRequest request) { super(request); // 将body数据存储起来 mBody = getBody(request); } /** * 获取请求体 * * @param request 请求 * @return 请求体 */ private String getBody(HttpServletRequest request) { return HttpContextUtils.getBodyString(request); } /** * 获取请求体 * * @return 请求体 */ public String getBody() { return mBody; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { // 创建字节数组输入流 final ByteArrayInputStream bais = new ByteArrayInputStream(mBody.getBytes(StandardCharsets.UTF_8)); return new ServletInputStream() { @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } @Override public int read() throws IOException { return bais.read(); } }; } } } 使用

上面两个文件放到合适的位置后,就可以在拦截器中使用 HttpContextUtils 获取 body 体了。

String requestStr = HttpContextUtils.getBodyString(request); JSONObject requestObj = JSON.parseObject(requestStr);

SpringBoot 拦截器获取 @RequestBody 参数

参考文章

java 实现 HttpServletRequest raw 和 params 的方式 请求 和获取 加requestMapping 设置UTF-8Springboot拦截器获取@RequestBody参数

本作品采用《CC 协议》,转载必须注明作者和本文链接


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3