- 日常开发中,我们会遇到这样一个情况,需要通过拦截器对请求接口时传递过来的参数做一个处理,像加密什么的,通过拦截器获取请求参数又分两种情况。
- 接口使用
@RequestParam
接收参数 - 针对情况一,我们只需要在拦截器中通过
request.getParameterMap()
来获得全部 Parameter
参数就可以了
public static Map<String, String> getParameterMapAll(HttpServletRequest request)
{
Enumeration<String> parameters = request.getParameterNames();
Map<String, String> params = new HashMap<>();
while (parameters.hasMoreElements()) {
String parameter = parameters.nextElement();
String value = request.getParameter(parameter);
params.put(parameter, value);
}
return params;
}
- 当接口使用
@RequestBody
接收参数时,我们在拦截器中使用同样的方法获取参数,就会出现流已关闭的异常,也就导致参数读取失败了。 - 这是因为
Spring
已经对 @RequestBody
提前进行处理,而 HttpServletReqeust
获取输入流时仅允许读取一次,所以会报java.io.IOException: Stream closed
- 解决方案就是去构建 可重复读取
inputStream
的request
* Repeatable 过滤器
*
*/
public class RepeatableFilter implements Filter
{
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest
&& StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
{
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
}
if (null == requestWrapper)
{
chain.doFilter(request, response);
}
else
{
chain.doFilter(requestWrapper, response);
}
}
@Override
public void destroy()
{
}
}
* 构建可重复读取inputStream的request
* 解决: request.getInputStream()只能读取一次的问题
*/
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
{
private final byte[] body;
public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
{
super(request);
request.setCharacterEncoding(Constants.UTF8);
response.setCharacterEncoding(Constants.UTF8);
body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8);
}
@Override
public BufferedReader getReader() throws IOException
{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException
{
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream()
{
@Override
public int read() throws IOException
{
return bais.read();
}
@Override
public int available() throws IOException
{
return body.length;
}
@Override
public boolean isFinished()
{
return false;
}
@Override
public boolean isReady()
{
return false;
}
@Override
public void setReadListener(ReadListener readListener)
{
}
};
}
}
* 通用http工具封装
*
*/
public class HttpHelper
{
private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
* 获取body参数
* @param request
*/
public static String getBodyString(ServletRequest request)
{
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try (InputStream 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)
{
LOGGER.warn("getBodyString出现问题!");
}
finally
{
if (reader != null)
{
try
{
reader.close();
}
catch (IOException e)
{
LOGGER.error(ExceptionUtils.getMessage(e));
}
}
}
return sb.toString();
}
* 获取query参数
* @param request
*/
public static Map<String, String> getParameterMapAll(HttpServletRequest request) {
Enumeration<String> parameters = request.getParameterNames();
Map<String, String> params = new HashMap<>();
while (parameters.hasMoreElements()) {
String parameter = parameters.nextElement();
String value = request.getParameter(parameter);
params.put(parameter, value);
}
return params;
}
}
- 首先判断本次
request
请求对象是不是 RepeatedlyRequestWrapper
类的实例,如果是,则代表本次请求的接口是使用 @RequestBody
来接收的参数,那么我们就需要用 getBodyString()
方法获取参数;反之,则代表接口使用 @RequestParam
接收参数,我们直接用 request.getParameterMap()
来获得全部参数即可。
public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation)
{
String nowParams = "";
if (request instanceof RepeatedlyRequestWrapper)
{
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
nowParams = HttpHelper.getBodyString(repeatedlyRequest);
}
if (StringUtils.isEmpty(nowParams))
{
nowParams = JSON.toJSONString(request.getParameterMap());
}
return false;
}