本文共 17305 字,大约阅读时间需要 57 分钟。
在web应用程序中,后台仅仅获取请求参数是远远不够的。比如,spring的controller层,我们可以通过
没错,用javax.servlet.http.HttpServletRequest,HttpServletRequest帮我们将请求解析封装好了已经,我们只需要拿来直接用即可。@RequestMapping
注解一个方法使其成为web借口,我们可以通过方法参数来获取匹配获取请求的参数。 但是,如果我们想要获取更多的信息怎么办呢?
(HttpServletRequest在springMVC/springBoot Controller层的应用)
@RequestMapping(value = "/**")public ResponseEntity
在方法mockEntry中,可以通过httpServletRequest
实例提供的方法获取到各种请求数据。
我们来看不同请求下,HttpServletRequest
将请求封装成什么样子了。 我们将验证一下请求:
1、 GET方法,不带queryParams;
curl 'http://localhost:8089/my/url'
2、GET方法,带queryParams;
curl 'http://localhost:8089/my/url?key1=value1&key2=vlaue2'
3、POST方法,bodyType为
application/x-www-form-urlencoded
,不带queryParams,不带bodyParams;
curl -H 'Content-Type:application/x-www-form-urlencoded' -d '' 'http://localhost:8089/my/url'
4、POST方法,bodyType为
application/x-www-form-urlencoded
,不带queryParams,带bodyParams;
curl -H 'Content-Type:application/x-www-form-urlencoded' -d 'key=value' 'http://localhost:8089/my/url'
5、POST方法,bodyType为
application/x-www-form-urlencoded
,带queryParams,不带bodyParams;
curl -H 'Content-Type:application/x-www-form-urlencoded' -d '' 'http://localhost:8089/my/url?key=value'
6、POST方法,bodyType为
application/x-www-form-urlencoded
,带queryParams,带bodyParams;
curl -H 'Content-Type:application/x-www-form-urlencoded' -d 'key1=value1' 'http://localhost:8089/my/url?key2=value2'
7、POST方法,bodyType为
application/json
,不带queryParams,不带bodyParams;
curl -H 'Content-Type:application/json' -d '' 'http://localhost:8089/my/url'
8、POST方法,bodyType为
application/json
,不带queryParams,带bodyParams;
curl -H 'Content-Type:application/json' -d '{"key": "value"}' 'http://localhost:8089/my/url'
9、POST方法,bodyType为
application/json
,带queryParams,不带bodyParams;
curl -H 'Content-Type:application/json' -d '' 'http://localhost:8089/my/url?key=value'
10、POST方法,bodyType为
application/json
,带queryParams,带bodyParams;
curl -H 'Content-Type:application/json' -d '{"key": "value"}' 'http://localhost:8089/my/url?key2=value2'
我们写一个Filter
,并且写一个RequestMetadata
作为数据承载类,为我们直观的输出HttpServletRequest
封装了什么。
import java.io.Serializable;import java.util.Map;public class RequestMetadata implements Serializable { private static final long serialVersionUID = 4756023942925621584L; private String protocol; private String scheme; private String serverName; private String serverPort; private String servletPath; private String method; private String uri; private String url; private String contentType; private int contentLength; private MapheaderNames; private String queryString; private Map parameterMap; private String body; public RequestMetadata() { } public String getProtocol() { return protocol; } public void setProtocol(String protocol) { this.protocol = protocol; } public String getScheme() { return scheme; } public void setScheme(String scheme) { this.scheme = scheme; } public String getServerName() { return serverName; } public void setServerName(String serverName) { this.serverName = serverName; } public String getServerPort() { return serverPort; } public void setServerPort(String serverPort) { this.serverPort = serverPort; } public String getServletPath() { return servletPath; } public void setServletPath(String servletPath) { this.servletPath = servletPath; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getContentType() { return contentType; } public void setContentType(String contentType) { this.contentType = contentType; } public int getContentLength() { return contentLength; } public void setContentLength(int contentLength) { this.contentLength = contentLength; } public Map getHeaderNames() { return headerNames; } public void setHeaderNames(Map headerNames) { this.headerNames = headerNames; } public String getQueryString() { return queryString; } public void setQueryString(String queryString) { this.queryString = queryString; } public Map getParameterMap() { return parameterMap; } public void setParameterMap(Map parameterMap) { this.parameterMap = parameterMap; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } @Override public String toString() { return "RequestMetadata{" + "protocol='" + protocol + '\'' + ", scheme='" + scheme + '\'' + ", serverName='" + serverName + '\'' + ", serverPort='" + serverPort + '\'' + ", servletPath='" + servletPath + '\'' + ", method='" + method + '\'' + ", uri='" + uri + '\'' + ", url='" + url + '\'' + ", contentType='" + contentType + '\'' + ", contentLength=" + contentLength + ", headerNames=" + headerNames + ", queryString='" + queryString + '\'' + ", parameterMap=" + parameterMap + ", body='" + body + '\'' + '}'; }}
import java.io.IOException;import java.util.Enumeration;import java.util.Iterator;import java.util.Map;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.filter.OncePerRequestFilter;import wiremock.com.google.common.collect.Maps;/** * Filter all requests. Extract useful information from the request (for example: method, parameter, uri, etc.) and * store it in a map. An http request will first go to this Filter, and then go to the Controller class, so this map is * stored in the ThreadLocal in order to obtain the details of the request at the Controller level. */@WebFilter(filterName = "requestFilter", urlPatterns = "/*")public class RequestFilter extends OncePerRequestFilter { private static final Logger logger = LoggerFactory.getLogger(RequestFilter.class); public static ThreadLocal threadLocal = new ThreadLocal(); @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { RequestMetadata requestMetadata = new RequestMetadata(); ServletRequest requestWrapper = null; requestMetadata.setProtocol(httpServletRequest.getProtocol()); requestMetadata.setScheme(httpServletRequest.getScheme()); requestMetadata.setServerName(httpServletRequest.getServerName()); requestMetadata.setServerPort(String.valueOf(httpServletRequest.getServerPort())); requestMetadata.setServletPath(httpServletRequest.getServletPath()); requestMetadata.setMethod(httpServletRequest.getMethod()); requestMetadata.setUri(httpServletRequest.getRequestURI()); requestMetadata.setUrl(httpServletRequest.getRequestURL().toString()); requestMetadata.setContentType(httpServletRequest.getContentType()); requestMetadata.setContentLength(httpServletRequest.getContentLength()); requestMetadata.setQueryString(httpServletRequest.getQueryString()); // headerNames MapheadersMap = Maps.newHashMap(); Enumeration headerNamesEnumeration = httpServletRequest.getHeaderNames(); while (headerNamesEnumeration.hasMoreElements()) { String key = headerNamesEnumeration.nextElement(); headersMap.put(key, httpServletRequest.getHeader(key)); } requestMetadata.setHeaderNames(headersMap); // parameterMap Map parameterMap = Maps.newHashMap(); Iterator iterator = httpServletRequest.getParameterMap().entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry ) iterator.next(); parameterMap.put(entry.getKey(), entry.getValue()[0]); } requestMetadata.setParameterMap(parameterMap); requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest); byte[] body = ((BodyReaderHttpServletRequestWrapper) requestWrapper).getBody(); requestMetadata.setBody(new String(body)); // Save the requestMetadata containing the request details in threadLocal threadLocal.set(requestMetadata); if (null == requestWrapper) { filterChain.doFilter(httpServletRequest, httpServletResponse); } else { filterChain.doFilter(requestWrapper, httpServletResponse); } }}
1、 GET方法,不带queryParams;
请求curl 'http://localhost:8089/my/url'
打印JSON.toJSONString(requestMetadata)
{ "body": "", "contentLength": -1, "headerNames": { "host": "localhost:8089", "user-agent": "curl/7.54.0", "accept": "*/*" }, "method": "GET", "parameterMap": { }, "protocol": "HTTP/1.1", "scheme": "http", "serverName": "localhost", "serverPort": "8089", "servletPath": "/my/url", "uri": "/my/url", "url": "http://localhost:8089/my/url"}
2、GET方法,带queryParams;
请求curl 'http://localhost:8089/my/url?key1=value1&key2=vlaue2'
打印JSON.toJSONString(requestMetadata)
{ "body": "", "contentLength": -1, "headerNames": { "host": "localhost:8089", "user-agent": "curl/7.54.0", "accept": "*/*" }, "method": "GET", "parameterMap": { "key1": "value1", "key2": "vlaue2" }, "protocol": "HTTP/1.1", "queryString": "key1=value1&key2=vlaue2", "scheme": "http", "serverName": "localhost", "serverPort": "8089", "servletPath": "/my/url", "uri": "/my/url", "url": "http://localhost:8089/my/url"}
注:GET方法的queryParams,存储到了以parameterMap
为key的JSONObject中。
3、POST方法,bodyType为application/x-www-form-urlencoded
,不带queryParams,不带bodyParams;
curl -H 'Content-Type:application/x-www-form-urlencoded' -d '' 'http://localhost:8089/my/url'
打印JSON.toJSONString(requestMetadata)
{ "body": "", "contentLength": 0, "contentType": "application/x-www-form-urlencoded", "headerNames": { "content-length": "0", "host": "localhost:8089", "content-type": "application/x-www-form-urlencoded", "user-agent": "curl/7.54.0", "accept": "*/*" }, "method": "POST", "parameterMap": { }, "protocol": "HTTP/1.1", "scheme": "http", "serverName": "localhost", "serverPort": "8089", "servletPath": "/my/url", "uri": "/my/url", "url": "http://localhost:8089/my/url"}
4、POST方法,bodyType为application/x-www-form-urlencoded
,不带queryParams,带bodyParams;
curl -H 'Content-Type:application/x-www-form-urlencoded' -d 'key=value' 'http://localhost:8089/my/url'
打印JSON.toJSONString(requestMetadata)
{ "body": "", "contentLength": 9, "contentType": "application/x-www-form-urlencoded", "headerNames": { "content-length": "9", "host": "localhost:8089", "content-type": "application/x-www-form-urlencoded", "user-agent": "curl/7.54.0", "accept": "*/*" }, "method": "POST", "parameterMap": { "key": "value" }, "protocol": "HTTP/1.1", "scheme": "http", "serverName": "localhost", "serverPort": "8089", "servletPath": "/my/url", "uri": "/my/url", "url": "http://localhost:8089/my/url"}
注意:bodyType为application/x-www-form-urlencoded
时,body中的key/value形式的参数,存到了以parameterMap
为 key 的 JSONObject中。
5、POST方法,bodyType为application/x-www-form-urlencoded
,带queryParams,不带bodyParams;
curl -H 'Content-Type:application/x-www-form-urlencoded' -d '' 'http://localhost:8089/my/url?key=value'
打印JSON.toJSONString(requestMetadata)
{ "body": "", "contentLength": 0, "contentType": "application/x-www-form-urlencoded", "headerNames": { "content-length": "0", "host": "localhost:8089", "content-type": "application/x-www-form-urlencoded", "user-agent": "curl/7.54.0", "accept": "*/*" }, "method": "POST", "parameterMap": { "key": "value" }, "protocol": "HTTP/1.1", "queryString": "key=value", "scheme": "http", "serverName": "localhost", "serverPort": "8089", "servletPath": "/my/url", "uri": "/my/url", "url": "http://localhost:8089/my/url"}
注意:bodyType为application/x-www-form-urlencoded
时,queryParams参数,也存到了以parameterMap
为 key 的 JSONObject中。
6、POST方法,bodyType为application/x-www-form-urlencoded
,带queryParams,带bodyParams;
curl -H 'Content-Type:application/x-www-form-urlencoded' -d 'key1=value1' 'http://localhost:8089/my/url?key2=value2'
打印JSON.toJSONString(requestMetadata)
{ "body": "", "contentLength": 11, "contentType": "application/x-www-form-urlencoded", "headerNames": { "content-length": "11", "host": "localhost:8089", "content-type": "application/x-www-form-urlencoded", "user-agent": "curl/7.54.0", "accept": "*/*" }, "method": "POST", "parameterMap": { "key1": "value1", "key2": "value2" }, "protocol": "HTTP/1.1", "queryString": "key2=value2", "scheme": "http", "serverName": "localhost", "serverPort": "8089", "servletPath": "/my/url", "uri": "/my/url", "url": "http://localhost:8089/my/url"}
注意:bodyType为application/x-www-form-urlencoded
时,queryParams参数 和 body中的key/value形式的参数,都存到了以parameterMap
为 key 的 JSONObject中。
7、POST方法,bodyType为application/json
,不带queryParams,不带bodyParams;
curl -H 'Content-Type:application/json' -d '' 'http://localhost:8089/my/url'
打印JSON.toJSONString(requestMetadata)
{ "body": "", "contentLength": 0, "contentType": "application/json", "headerNames": { "content-length": "0", "host": "localhost:8089", "content-type": "application/json", "user-agent": "curl/7.54.0", "accept": "*/*" }, "method": "POST", "parameterMap": { }, "protocol": "HTTP/1.1", "scheme": "http", "serverName": "localhost", "serverPort": "8089", "servletPath": "/my/url", "uri": "/my/url", "url": "http://localhost:8089/my/url"}
8、POST方法,bodyType为application/json
,不带queryParams,带bodyParams;
curl -H 'Content-Type:application/json' -d '{"key": "value"}' 'http://localhost:8089/my/url'
打印JSON.toJSONString(requestMetadata)
{ "body": "{\"key\": \"value\"}", "contentLength": 16, "contentType": "application/json", "headerNames": { "content-length": "16", "host": "localhost:8089", "content-type": "application/json", "user-agent": "curl/7.54.0", "accept": "*/*" }, "method": "POST", "parameterMap": { }, "protocol": "HTTP/1.1", "scheme": "http", "serverName": "localhost", "serverPort": "8089", "servletPath": "/my/url", "uri": "/my/url", "url": "http://localhost:8089/my/url"}
注意:bodyType为application/json
时,body中的key/value
形式的参数 或 json
形式的参数,以字符串的形式存到了body中。
9、POST方法,bodyType为application/json
,带queryParams,不带bodyParams;
curl -H 'Content-Type:application/json' -d '' 'http://localhost:8089/my/url?key=value'
打印JSON.toJSONString(requestMetadata)
{ "body": "", "contentLength": 0, "contentType": "application/json", "headerNames": { "content-length": "0", "host": "localhost:8089", "content-type": "application/json", "user-agent": "curl/7.54.0", "accept": "*/*" }, "method": "POST", "parameterMap": { "key": "value" }, "protocol": "HTTP/1.1", "queryString": "key=value", "scheme": "http", "serverName": "localhost", "serverPort": "8089", "servletPath": "/my/url", "uri": "/my/url", "url": "http://localhost:8089/my/url"}
注意:bodyType为application/json
时,queryParams中的key/value
形式的参数,存到了以parameterMap
为 key 的 JSONObject中。
10、POST方法,bodyType为application/json
,带queryParams,带bodyParams;
curl -H 'Content-Type:application/json' -d '{"key": "value"}' 'http://localhost:8089/my/url?key2=value2'
打印JSON.toJSONString(requestMetadata)
{ "body": "{\"key\": \"value\"}", "contentLength": 11, "contentType": "application/json", "headerNames": { "content-length": "11", "host": "localhost:8089", "content-type": "application/json", "user-agent": "curl/7.54.0", "accept": "*/*" }, "method": "POST", "parameterMap": { "key2": "value2" }, "protocol": "HTTP/1.1", "queryString": "key2=value2", "scheme": "http", "serverName": "localhost", "serverPort": "8089", "servletPath": "/my/url", "uri": "/my/url", "url": "http://localhost:8089/my/url"}
注意:bodyType为application/json
时,queryParams中的key/value
形式的参数,存到了以parameterMap
为 key 的 JSONObject中。而body中的key/value
形式的参数 或 json
形式的参数,以字符串的形式存到了body中。
通过这些实验,主要还是想了解 queryParams(无论GET方法还是POST方法)和bodyType为Content-Type:application/x-www-form-urlencoded
时的bodyParams会怎么存储,现在知道了,都会存到了以parameterMap
为 key 的 JSONObject中,这样我们就不用自己去区分解析了,做工具平台的时候非常方便。
转载地址:http://igini.baihongyu.com/