温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何解决SpringBoot读取不到request请求中的InputStream的问题

发布时间:2021-07-02 17:39:33 来源:亿速云 阅读:223 作者:chen 栏目:大数据

本篇内容主要讲解“如何解决SpringBoot读取不到request请求中的InputStream的问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何解决SpringBoot读取不到request请求中的InputStream的问题”吧!

现象

采用SpringBoot2.0版本开发项目,之前发现获取参数的时候,request.getParameter()获取不到参数,没有深究,采用

 @PostMapping("/mbr/detail")
    public Result mbrDetail(@RequestBody JSONObject jsonObject){

        MbrMember mbrMember = null;
        try {
            String mbrId = jsonObject.getString("mbrId");

            mbrMember = mbrMemberService.getMbrMemberById(mbrId);

        }catch (Exception e) {
            e.printStackTrace();
            return ResultGenerator.genExcepResult("服务器内部错误");
        }

        return ResultGenerator.genSuccessResult(mbrMember);
    }

@RequestBody JSONObject jsonObject的方式来获取请求中的参数。

今天对原来接口改造的时候,发现从request请求中总是获取不到参数,原接口(未采用Spring模式)采用JSP形式实现,如下:

try {
		System.out.println("!!进入回调!!");
		String postdata = AppServiceUtil.getPostData(request.getInputStream(), request.getContentLength(), Charsets.UTF_8.toString());
	BdNotifyApi notifyApi = new BdNotifyApi();
	result = notifyApi.bdNotify(postdata);
} catch (Exception e) {
    e.printStackTrace();
}finally {
	response.setCharacterEncoding("utf8");
	response.setHeader("content-type", "text/html;charset=UTF-8");
	response.getWriter().print(result);
}

getPostData方法如下:

public static String getPostData(InputStream in, int size, String charset) {
		if (in != null && size > 0) {
			byte[] buf = new byte[size];
			try {
				in.read(buf);
				if (charset == null || charset.length() == 0)
					return new String(buf);
				else {
					return new String(buf, charset);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
request采用流读取的方式获取不到参数

分析

出现这种情况,首先怀疑输入流已经被使用了,由于请求输入流是不带缓存的,使用一次后流就无效了,通常触发解析输入流就是调用了getParameter()等方法,经过检查代码确认没有做过相关处理,所以怀疑SpringBoot底层做了处理。 查了一下SpringBoot的自动装配配置,在WebMvcAutoConfiguration中初始化了一个OrderedHiddenHttpMethodFilter,默认这个过滤器是生效的,相关代码如下:

@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = true)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
    return new OrderedHiddenHttpMethodFilter();
}

OrderedHiddenHttpMethodFilter继承了OrderedHiddenHttpMethodFilter,而OrderedHiddenHttpMethodFilter又继承了HiddenHttpMethodFilter,在该类的doFilterInternal()方法中发现有对参数做处理,相关代码如下:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
    throws ServletException, IOException {
    HttpServletRequest requestToUse = request;

    if ("POST".equals(request.getMethod()) && 
    request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
        String paramValue = request.getParameter(this.methodParam);
        if (StringUtils.hasLength(paramValue)) {
            String method = paramValue.toUpperCase(Locale.ENGLISH);
            if (ALLOWED_METHODS.contains(method)) {
                requestToUse = new HttpMethodRequestWrapper(request, method);
            }
        }
    }
    filterChain.doFilter(requestToUse, response);
}

配置

在SpringMVC的配置文件中对过滤器重新配置

/**
 * Spring MVC 配置WebMvcConfigurer
 */
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {

过滤器代码如下:

@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
    return new OrderedHiddenHttpMethodFilter(){
        @Override
        protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
            filterChain.doFilter(request, response);
        }
    };
}

总结

搞明白流方式获取请求参数的原理以及SpringBoot默认的配置对这种情况的处理。

参考

https://blog.csdn.net/jianggujin/article/details/86644914

到此,相信大家对“如何解决SpringBoot读取不到request请求中的InputStream的问题”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI