拦截器获取请求参数post_spring boot拦截器中获取request post请求中的参数

最近有一个需要从拦截器中获取post请求的参数的需求,这里记录一下处理过程中出现的问题。

首先想到的就是request.getParameter(String )方法,但是这个方法只能在get请求中取到参数,post是不行的,后来想到了使用流的方式,调用request.getInputStream()获取流,然后从流中读取参数,如下代码所示:

String body = "";

StringBuilder stringBuilder= newStringBuilder();

BufferedReader bufferedReader= null;

InputStream inputStream= null;try{

inputStream=request.getInputStream();if (inputStream != null) {

bufferedReader= new BufferedReader(newInputStreamReader(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) {

e.printStackTrace();

}finally{if (inputStream != null) {try{

inputStream.close();

}catch(IOException e) {

e.printStackTrace();

}

}if (bufferedReader != null) {try{

bufferedReader.close();

}catch(IOException e) {

e.printStackTrace();

}

}

}

body= stringBuilder.toString();

代码中的body就是request中的参数,我这里传的是JSON数据:{"page": 1, "pageSize": 10},那么body就是:body = "{"page": 1, "pageSize": 10}",一个JSON字符串。这样是可以成功获取到post请求的body,但是,经过拦截器后,参数经过@RequestBody注解赋值给controller中的方法的时候,却抛出了一个这样的异常:

org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing

在网上查找资料后发现,request的输入流只能读取一次,那么这是为什么呢?下面是答案:

那是因为流对应的是数据,数据放在内存中,有的是部分放在内存中。read 一次标记一次当前位置(mark position),第二次read就从标记位置继续读(从内存中copy)数据。 所以这就是为什么读了一次第二次是空了。 怎么让它不为空呢?只要inputstream 中的pos 变成0就可以重写读取当前内存中的数据。javaAPI中有一个方法public void reset() 这个方法就是可以重置pos为起始位置,但是不是所有的IO读取流都可以调用该方法!ServletInputStream是不能调用reset方法,这就导致了只能调用一次getInputStream()。

那么有什么办法可以用户解决呢?上面这篇博客中提到了解决方案,就是重写HttpServletRequestWrapper把request保存下来,然后通过过滤器把保存下来的request再填充进去,这样就可以多次读取request了。步骤如下所示:

①写一个类,继承HttpServletRequestWrapper

importjavax.servlet.ReadListener;importjavax.servlet.ServletInputStream;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletRequestWrapper;import java.io.*;public class RequestWrapper extendsHttpServletRequestWrapper {private finalString body;publicRequestWrapper(HttpServletRequest request) {super(request);

StringBuilder stringBuilder= newStringBuilder();

BufferedReader bufferedReader= null;

InputStream inputStream= null;try{

inputStream=request.getInputStream();if (inputStream != null) {

bufferedReader= new BufferedReader(newInputStreamReader(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();

}

}

}

body=stringBuilder.toString();

}

@Overridepublic ServletInputStream getInputStream() throwsIOException {final ByteArrayInputStream byteArrayInputStream = newByteArrayInputStream(body.getBytes());

ServletInputStream servletInputStream= newServletInputStream() {

@Overridepublic booleanisFinished() {return false;

}

@Overridepublic booleanisReady() {return false;

}

@Overridepublic voidsetReadListener(ReadListener readListener) {

}

@Overridepublic int read() throwsIOException {returnbyteArrayInputStream.read();

}

};returnservletInputStream;

}

@Overridepublic BufferedReader getReader() throwsIOException {return new BufferedReader(new InputStreamReader(this.getInputStream()));

}publicString getBody() {return this.body;

}

}

②拦截器层面

importcom.alibaba.fastjson.JSON;importcom.miniprogram.api.douyin.user.req.DyuserReq;importcom.miniprogram.common.auth.VisitLimitCount;importcom.miniprogram.common.cache.RedisCache;importcom.miniprogram.common.config.InterceptorConfigMap;importcom.miniprogram.common.config.InterceptorUrlConfig;importcom.miniprogram.common.douyin.SearchEngineMapConstants;importcom.miniprogram.common.response.Response;import com.miniprogram.common.session.*;importcom.miniprogram.common.utils.DateUtil;importcom.miniprogram.dao.common.UserLoginEntity.Users;importcom.miniprogram.service.douyin.users.UsersService;importcom.miniprogram.web.douyin.config.RequestWrapper;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.BeanUtils;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importorg.springframework.web.servlet.ModelAndView;importorg.springframework.web.servlet.handler.HandlerInterceptorAdapter;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.BufferedReader;importjava.io.InputStreamReader;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;

@Component("authSecurityInterceptor")public class AuthSecurityInterceptor extendsHandlerInterceptorAdapter {private Logger logger = LoggerFactory.getLogger(AuthSecurityInterceptor.class);@AutowiredprivateRedisCache redisCache;

@AutowiredprivateVisitLimitCount visitLimitCount;

@Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throwsException {try{

RequestWrapper requestWrapper= newRequestWrapper(httpServletRequest);

String body=requestWrapper.getBody();

System.out.println(body);return true;

}catch(Exception e){

logger.error("权限判断出错",e);

}return false;

}

@Overridepublic void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throwsException {

}

@Overridepublic void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throwsException {

}

}

③过滤器Filter,用来把request传递下去

import javax.servlet.*;importjavax.servlet.annotation.WebFilter;importjavax.servlet.http.HttpServletRequest;importjava.io.IOException;

@WebFilter(urlPatterns= "/*",filterName = "channelFilter")public class ChannelFilter implementsFilter {

@Overridepublic void init(FilterConfig filterConfig) throwsServletException {

}

@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throwsIOException, ServletException {

ServletRequest requestWrapper= null;if(servletRequest instanceofHttpServletRequest) {

requestWrapper= newRequestWrapper((HttpServletRequest) servletRequest);

}if(requestWrapper == null) {

filterChain.doFilter(servletRequest, servletResponse);

}else{

filterChain.doFilter(requestWrapper, servletResponse);

}

}

@Overridepublic voiddestroy() {

}

}

④在启动类中注册拦截器

importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.web.servlet.MultipartConfigFactory;importorg.springframework.boot.web.servlet.ServletComponentScan;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;

@SpringBootApplication

// @ServletComponentScan//注册过滤器注解

@Configurationpublic classWebApplication {public static voidmain(String[] args) {

SpringApplication.run(WebApplication.class, args);

}

}

经测试,问题解决

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值