springboot中获取requestpost请求中的参数
最近有⼀个需要从中获取post请求的参数的需求,这⾥记录⼀下处理过程中出现的问题。
⾸先想到的就是Parameter(String )⽅法,但是这个⽅法只能在get请求中取到参数,post是不⾏的,后来想到了使⽤流的⽅式,调⽤InputStream()获取流,然后从流中读取参数,如下代码所⽰:
String body = "";
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
InputStream inputStream = null;
try {
inputStream = InputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = ad(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 = String();
代码中的body就是request中的参数,我这⾥传的是JSON数据:{"page": 1, "pageSize": 10},那么body就是:body = "{"page": 1, "pageSize": 10}",⼀个JSON字符串。这样是可以成功获取到post请求的body,但是,经过后,参数经过@RequestBody注解赋值给controller中的⽅法的时候,却抛出了⼀个这样的异常:
org.verter.HttpMessageNotReadableException: Required request body is missing
在⽹上查资料后发现,request的输⼊流只能读取⼀次,那么这是为什么呢?下⾯是答案:
那是因为流对应的是数据,数据放在内存中,有的是部分放在内存中。read ⼀次标记⼀次当前位置(mark position),第⼆次
read就从标记位置继续读(从内存中copy)数据。所以这就是为什么读了⼀次第⼆次是空了。怎么让它不为空呢?只要
inputstream 中的pos 变成0就可以重写读取当前内存中的数据。javaAPI中有⼀个⽅法public void reset() 这个⽅法就是可以重置
pos为起始位置,但是不是所有的IO读取流都可以调⽤该⽅法!ServletInputStream是不能调⽤reset⽅法,这就导致了只能调⽤⼀次getInputStream()。
摘⾃:
那么有什么办法可以⽤户解决呢?上⾯这篇博客中提到了解决⽅案,就是重写HttpServletRequestWrap
per把request保存下来,然后通过过滤器把保存下来的request再填充进去,这样就可以多次读取request了。步骤如下所⽰:
①写⼀个类,继承HttpServletRequestWrapper
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
public class RequestWrapper extends HttpServletRequestWrapper {
private final String body;
public RequestWrapper(HttpServletRequest request) {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
InputStream inputStream = null;
try {
inputStream = InputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = ad(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
springboot和过滤器}
} 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 = String();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new Bytes()); ServletInputStream servletInputStream = 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 {
ad();
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStream()));
}
public String getBody() {
return this.body;
}
}
②层⾯
import com.alibaba.fastjson.JSON;
import com.miniprogram.api.q.DyuserReq;
import com.miniprogrammon.auth.VisitLimitCount;
import com.miniprogrammon.cache.RedisCache;
import fig.InterceptorConfigMap;
import fig.InterceptorUrlConfig;
import com.miniprogrammon.douyin.SearchEngineMapConstants;
import sponse.Response;
import com.miniprogrammon.session.*;
import com.miniprogrammon.utils.DateUtil;
import com.miniprogram.daomon.UserLoginEntity.Users;
import com.miniprogram.service.douyin.users.UsersService;
import com.miniprogram.fig.RequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component("authSecurityInterceptor")
public class AuthSecurityInterceptor extends HandlerInterceptorAdapter {
private Logger logger = Logger(AuthSecurityInterceptor.class);
@Autowired
private RedisCache redisCache;
@Autowired
private VisitLimitCount visitLimitCount;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
try {
RequestWrapper requestWrapper = new RequestWrapper(httpServletRequest);
String body = Body();
System.out.println(body);
return true;
}catch (Exception e){
<("权限判断出错",e);
}
return false;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { }
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
③过滤器Filter,⽤来把request传递下去
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(urlPatterns = "/*",filterName = "channelFilter")
public class ChannelFilter 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);
}
if(requestWrapper == null) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
filterChain.doFilter(requestWrapper, servletResponse);
}
}
@Override
public void destroy() {
}
}
④在启动类中注册
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.MultipartConfigFactory; import org.springframework.boot.web.servlet.ServletComponentScan; import t.annotation.Bean;
import t.annotation.ComponentScan; import t.annotation.Configuration;
@SpringBootApplication
// @ServletComponentScan //注册过滤器注解
@Configuration
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
经测试,问题解决
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论