博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
我们发送一个请求时,服务端的javax.servlet.http.HttpServletRequest帮我们做了什么?
阅读量:4079 次
发布时间:2019-05-25

本文共 17305 字,大约阅读时间需要 57 分钟。

在web应用程序中,后台仅仅获取请求参数是远远不够的。比如,spring的controller层,我们可以通过@RequestMapping注解一个方法使其成为web借口,我们可以通过方法参数来获取匹配获取请求的参数。 但是,如果我们想要获取更多的信息怎么办呢?

没错,用javax.servlet.http.HttpServletRequest,HttpServletRequest帮我们将请求解析封装好了已经,我们只需要拿来直接用即可。

举个例子

(HttpServletRequest在springMVC/springBoot Controller层的应用)

@RequestMapping(value = "/**")public ResponseEntity mockEntry(HttpServletRequest httpServletRequest) {    return new ResponseEntity("mock match!", HttpStatus.OK);}

在方法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 Map
headerNames; 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        Map
headersMap = 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/

你可能感兴趣的文章
我发觉不管是单片机,还是串口通信,还是传感器,最后根本都是配置寄存器。
查看>>
一个字节八位,左边是高位,右边是低位。
查看>>
SPI
查看>>
MPU6050里面还有一个温度传感器
查看>>
从UART到IIC到SPI我感觉是越来越好的
查看>>
ARM开发最大的难点就在于这个英文手册
查看>>
目前我觉得嵌入式应聘需要牢牢抓住两点,一个是各种串口通信协议,一个是freertos。
查看>>
我看有不少要求会USB的
查看>>
驱动的本质就是获取外设,或者传感器数据,也可以控制外设。
查看>>
linux驱动开发这块我觉得正点原子的视频讲得比华清的好
查看>>
我分析一下,其实linux的uart驱动写好了,所谓的ROS uart包应该是用户层app调用那个接口罢了。
查看>>
真正一个东西学深了是会喜欢上的 越学越有意思,学一个东西或者看书深入了也是到一个层面,不管那个东西找工作用不用的上,你都想深入学弄清楚弄透彻这样子。
查看>>
驱动开发分为一种如STM32的裸机驱动和linux驱动
查看>>
我现在明白什么叫总线了,就是一条线上挂了很多设备,比如IIC SPI就是这样的,通信之前要进行设备的选择。
查看>>
5种嵌入式经典总线协议精讲
查看>>
基于统一编址方案,我们就可以通过C语言的指针来寻址并修改存储器的地址,进而可以实现对相应外设寄存器的处理操作。
查看>>
还真有不少弄天猫精灵的,莫非天猫精灵真的可以做些嵌入式开发?
查看>>
FIFO就是 first in first out 先进先出
查看>>
我感觉嵌入式弄深了还是需要数电知识,这样可以理解得更为具体透彻。
查看>>
硬中断与软中断的区别
查看>>