SpringMVC cannot obtain the request parameters to investigate and solve the problem (2). springmvc Parameters
Because once the Request getInputSteam () is obtained, it will no longer be available.
In actual projects, the following problems occur:
1. When multiple interceptors and filters need to retrieve data from InputStream, they cannot be processed;
2. InputStream is intercepted and the Filter is taken away. The Controller layer cannot getParameter () or use the @ RequestParam annotation to automatically match the set parameters.
After referring to several blog posts related to getInputStream (), we adopted the following solutions.
1. Create a custom Request object by inheriting HttpServletRequestWrapper,
In this object, the Stream content of the Request is retained for a long time in the form of byte arrays, and can be reused multiple times in the interceptor, Filter, and Controller;
At the same time, rewrite the getParameter ()-related methods to ensure that all parameters can be parsed from the retained Stream data, and custom decoding can be performed during the parsing process.
Package org. jiagushi. mobile. rule. filter; import java. io. bufferedInputStream; import java. io. bufferedReader; import java. io. byteArrayInputStream; import java. io. byteArrayOutputStream; import java. io. IOException; import java. io. inputStream; import java. io. inputStreamReader; import java. io. unsupportedEncodingException; import java.net. URLDecoder; import java. util. collections; import java. util. enumeration; import Java. util. hashMap; import java. util. map; import java. util. stringTokenizer; import javax. servlet. servletInputStream; import javax. servlet. http. httpServletRequest; import javax. servlet. http. httpServletRequestWrapper; import com. mtime. mobile. utils. encodes; public class MAPIHttpServletRequestWrapper extends HttpServletRequestWrapper {private Map <String, String []> paramsMap; @ Override public Map getParamete RMap () {return paramsMap;} @ Override public String getParameter (String name) {// Override getParameter, which indicates that the parameter obtains String [] values = paramsMap from the map in the current class. get (name); if (values = null | values. length = 0) {return null;} return values [0];} @ Override public String [] getParameterValues (String name) {// same as return paramsMap. get (name) ;}@ Override public Enumeration getParameterNames () {return Collections. enu Meration (paramsMap. keySet ();} private String getRequestBody (InputStream stream) {String line = ""; StringBuilder body = new StringBuilder (); int counter = 0; // read the data submitted by POST. BufferedReader reader = new BufferedReader (new InputStreamReader (stream); try {while (line = reader. readLine ())! = Null) {if (counter> 0) {body. append ("\ r \ n");} body. append (line); counter ++ ;}} catch (IOException e) {e. printStackTrace ();} return body. toString ();} private HashMap <String, String []> getParamMapFromPost (HttpServletRequest request) {String body = ""; try {body = getRequestBody (request. getInputStream ();} catch (IOException e) {e. printStackTrace ();} HashMap <String, String []> result = n Ew HashMap <String, String []> (); if (null = body | 0 = body. length () {return result;} return parseQueryString (body);} // custom decoding function private String decodeValue (String value) {if (value. contains ("% u") {return Encodes. decodeUnicode (value);} else {try {return URLDecoder. decode (value, "UTF-8");} catch (UnsupportedEncodingException e) {return ""; // non-UTF-8 encoding }}public HashMap <String, String []> ParseQueryString (String s) {String valArray [] = null; if (s = null) {throw new IllegalArgumentException ();} HashMap <String, string []> ht = new HashMap <String, String []> (); StringTokenizer st = new StringTokenizer (s, "&"); while (st. hasMoreTokens () {String pair = (String) st. nextToken (); int pos = pair. indexOf ('='); if (pos =-1) {continue;} String key = pair. substring (0, pos); String Val = pair. substring (pos + 1, pair. length (); if (ht. containsKey (key) {String oldVals [] = (String []) ht. get (key); valArray = new String [oldVals. length + 1]; for (int I = 0; I <oldVals. length; I ++) {valArray [I] = oldVals [I];} valArray [oldVals. length] = decodeValue (val);} else {valArray = new String [1]; valArray [0] = decodeValue (val);} ht. put (key, valArray);} return ht;} private Map <String, String []> getParamMapFromGet (HttpServletRequest request) {return parseQueryString (request. getQueryString ();} private final byte [] body; // message public MAPIHttpServletRequestWrapper (HttpServletRequest request) throws IOException {super (request); body = readBytes (request. getInputStream (); // first obtain data from POST if ("POST ". equals (request. getMethod (). toUpperCase () {paramsMap = getParamMapFromPost (thi S) ;}else {paramsMap = getParamMapFromGet (this) ;}@ 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 I OException {return bais. read () ;};} private static byte [] readBytes (InputStream in) throws IOException {BufferedInputStream bufin = new BufferedInputStream (in); int buffSize = 1024; byteArrayOutputStream out = new ByteArrayOutputStream (buffSize); byte [] temp = new byte [buffSize]; int size = 0; while (size = bufin. read (temp ))! =-1) {out. write (temp, 0, size);} bufin. close (); byte [] content = out. toByteArray (); return content ;}}
2. Define a Filter (the configuration position of this Filter is placed at the top) and replace the original Request object:
Filter is added at the top of web. xml.
... <Context-param> <param-name> contextConfigLocation </param-name> <param-value> classpath: the spring/api-spring.xml </param-value> </context-param> <listener-class> org. springframework. web. context. contextLoaderListener </listener-class> </listener> <! -- The following Filter replaces the original Request with a custom Request object to maintain POST data and customize decoding --> <! -- The following two problems can be solved: 1. The getParameter () method fails when the CheckUrl interceptor reads InputStream; 2. The POST data has custom Unicode encoding, during decoding, you also need to read InputSteam --> <filter-name> requestFilter </filter-name> <filter-class> org. jiagushi. mobile. rule. filter. httpServletRequestReplacedFilter </filter-class> </filter> <filter-mapping> <filter-name> requestFilter </filter-name> <url-pattern>/* </url-pattern> </filter-mapping>...
Filter code
Package org. jiagushi. mobile. rule. filter; import java. io. IOException; import javax. servlet. filter; import javax. servlet. filterChain; import javax. servlet. filterConfig; import javax. servlet. servletException; import javax. servlet. servletRequest; import javax. servlet. servletResponse; import javax. servlet. http. httpServletRequest; public class HttpServletRequestReplacedFilter implements Filter {@ Override public Void destroy () {}@ Override public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {ServletRequest failure = null; if (request instanceof HttpServletRequest) {HttpServletRequest httpServletRequest = (HttpServletRequest) request; if ("POST ". equals (httpServletRequest. getMethod (). toUpperCase () {requestWrapper = new MAP IHttpServletRequestWrapper (HttpServletRequest) request) ;}} if (requestWrapper = null) {chain. doFilter (request, response);} else {chain. doFilter (requestWrapper, response); // replace! }}@ Override public void init (FilterConfig arg0) throws ServletException {}}
---
References:
Http://ayaoxinchao.iteye.com/blog/2110902
Http://my.oschina.net/tmallMoney/blog/127225
Http://www.xuebuyuan.com/809435.html
Http://hw1287789687.iteye.com/blog/1923085