request.get Parameeter()、request.get Input Stream()とrequest.get Reader()は一回しか使用できない問題を解決します.
5466 ワード
問題:Spring MVCブロックを使ってPOST要求中のJSON情報を取得する場合、request.get Reader()を使ってJSON情報を取得した後、POST要求は下に進まない.
理由:
1.Readerオブジェクトは読み取りが完了した後、再び読み取りできなくなり、常に-1に戻ります.
2.POSTも一つの流れですので、Reader方法を使ってからPOSTがtrueに戻りたいと言っても下に進まないです.
ソリューション:HttpServletRequest Wrapperを使用して、HttpServletRequestを包装し、BodyReader HttpServletRequest WrapperでrequestのReaderデータを初期化し、byte[]形式でキャッシュし、Filterでrequestを包装されたRequestに変換します.コードは以下の通りです
理由:
1.Readerオブジェクトは読み取りが完了した後、再び読み取りできなくなり、常に-1に戻ります.
2.POSTも一つの流れですので、Reader方法を使ってからPOSTがtrueに戻りたいと言っても下に進まないです.
ソリューション:HttpServletRequest Wrapperを使用して、HttpServletRequestを包装し、BodyReader HttpServletRequest WrapperでrequestのReaderデータを初期化し、byte[]形式でキャッシュし、Filterでrequestを包装されたRequestに変換します.コードは以下の通りです
public class HttpServletRequestReplacedFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
System.out.println(httpServletRequest.getContentType());
System.out.println(httpServletRequest.getContextPath());
System.out.println(httpServletRequest.getRemoteHost());
System.out.println(httpServletRequest.getMethod());
if ("POST".equals(httpServletRequest.getMethod().toUpperCase())
) {
//&& httpServletRequest.getContentType().equalsIgnoreCase(
// "application/json")
requestWrapper = new BodyReaderHttpServletRequestWrapper(
(HttpServletRequest) request);
}
}
if (requestWrapper == null) {
chain.doFilter(request, response);
} else {
chain.doFilter(requestWrapper, response);
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
public class BodyReaderHttpServletRequestWrapper extends
HttpServletRequestWrapper {
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
Enumeration e = request.getHeaderNames() ;
while(e.hasMoreElements()){
String name = (String) e.nextElement();
String value = request.getHeader(name);
}
body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
}
@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 String getHeader(String name) {
return super.getHeader(name);
}
@Override
public Enumeration getHeaderNames() {
return super.getHeaderNames();
}
@Override
public Enumeration getHeaders(String name) {
return super.getHeaders(name);
}
}
public class HttpHelper {
/**
* Body
*
* @param request
* @return
*/
public static String getBodyString(ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
web.xmlプロファイル
HttpServletRequestReplacedFilter
com.xxx.xxx.xxx.xxx.util.HttpServletRequestReplacedFilter
HttpServletRequestReplacedFilter
/*
このように運転する時はまずFilterからスプリングmvcのブロックを歩いて、何度も読み取ることができます.