springboot 在controller层获取Post请求中request.getInputStream的值的坑

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_36005199/article/details/84562057
         <!--一个博主专栏付费入口结束-->
        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d284373521.css">
                                    <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d284373521.css">
            <div class="htmledit_views" id="content_views">
                                        <h3>&nbsp; 这个有点坑,首先request的流的获取每个请求只能获取一次,之后再通过getInputStream获取流的时候就获取不到数据了,还有getInputStream和getReader和getParameter都可以获取输入流数据,但是存在冲突,也就是三者只要有一个对request获取了输入流信息,那么其他的方法之后就获取不到数据了。这就是springboot埋的一个小坑,那么怎么通过request获得Post请求的body值呢?</h3>

首先直接在controller层直接写肯定是获取不到的,即使你自己觉得你是第一次获取输入流,其实不然,在springboot启动的时候拦截器中也通过getParameter获取过输入流,导致后面没办法获取输入流

下面解决办法:重写HiddenHttpMethodFilter拦截器

我们先看下这个拦截器里面的方法

 
 

 
 
  1. @Override
  2. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
  3. throws ServletException, IOException {
  4. HttpServletRequest requestToUse = request;
  5. if ( "POST".equals( request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
  6. String paramValue = request.getParameter(this.methodParam);
  7. if (StringUtils.hasLength(paramValue)) {
  8. requestToUse = new HttpMethodRequestWrapper( request, paramValue);
  9. }
  10. }
  11. filterChain.doFilter(requestToUse, response);
  12. }

这个request.getParameter()看到了吧,就是它影响了后面获取输入流,我们自己重写这个方法就好了,我自己是在这个重写的方法里将request的输入流获取然后直接用的,我贴下代码


 
 
  1. import com.alibaba.fastjson.JSON;
  2. import lombok.extern.slf4j.Slf4j;
  3. import net.sf.json.JSONObject;
  4. import org.springframework.boot.web.filter.OrderedHiddenHttpMethodFilter;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.web.filter.HiddenHttpMethodFilter;
  8. import javax.servlet.FilterChain;
  9. import javax.servlet.ServletException;
  10. import javax.servlet.ServletInputStream;
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpServletResponse;
  13. import java.io.BufferedReader;
  14. import java.io.IOException;
  15. import java.io.InputStreamReader;
  16. @ Slf4j
  17. @ Configuration
  18. public class WebConfig {
  19. @ Bean
  20. public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
  21. return new OrderedHiddenHttpMethodFilter() {
  22. @ Override
  23. protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
  24. throws ServletException, IOException {
  25. BufferedReader reader = new BufferedReader(
  26. new InputStreamReader(request.getInputStream(), "UTF-8"));
  27. String line;
  28. String result = "";
  29. while ((line = reader. readLine()) != null) {
  30. result += line;
  31. }
  32. log.info( "业务验证提示信息! URL={} 参数:{}", request.getRequestURL(). toString(), JSON.toJSON(result));
  33. filterChain.doFilter(request, response);
  34. }
  35. };
  36. }
  37. }

然后我说一下这个坑:

一:即使重写的方法我们不用输入流,再controller也没办法获取post的输入流,我自己测了好多次都是这样,具体情况不清楚

二:即使将获取的输入流装入session中,在controller中获取session也会出错,获取不到值

三:关注我关注我

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

经过我的测试,我们发现这样虽然能够取到post输入流,但是这样之后cotroller用于接参的对象将取不到数据,会报request body is missing.那么大家就别用这种方式取输入流吧,通过aop去获取输入参数也应该行,我没试过,但思路是对的!!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot拦截器获取参数并进行反设的方法有多种。根据引用\[2\]的内容,如果是接口地址后面问号拼接的参数或表单参数,可以使用`request.getParameter("参数名")`来获取。而对于POST请求的body参数,可以通过调用`request.getInputStream()`获取流,然后从流读取参数。但是需要注意的是,经过拦截器后,参数经过`@RequestBody`注解赋controller的方法时,可能会抛出`org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing`异常。这可能是因为在拦截器已经读取了一次流,导致controller无法再次读取。解决这个问题的方法是在拦截器将流进行包装,以便在controller能够正常读取参数。具体的实现方式可以根据具体的需求和场景进行调整。 #### 引用[.reference_title] - *1* *3* [SpringBoot拦截器如何获取http请求参数](https://blog.csdn.net/weixin_29331015/article/details/111948704)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [springboot拦截器获取http请求参数](https://blog.csdn.net/z17806289513/article/details/124454000)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值