一、概述
http请求项目搭建:地址https://github.com/bjlhx15/common.git 中的spring-framework-core 的 spring-http-XX相关
主要针对post请求中的,form表单【application/x-www-form-urlcoded】提交,json【application/json】提交,文件【multipart/form-data】提交
1.1、客户端上传文件提交配置
pom
<!-- 文件提交--> <!-- commons-fileupload 包含 commons-io --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency>
spring bean xml配置【有时还需要修改tomcat nginx等配置文件】
<!-- 定义文件上传解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设定默认编码 --> <property name="defaultEncoding" value="UTF-8" /> <!-- 设定文件上传的最大值5MB,5*1024*1024 --> <property name="maxUploadSize" value="5242880" /> <property name="maxInMemorySize" value="4096" /> </bean>
代码开发
@RequestMapping("/upload") @ResponseBody public Object upload(@RequestParam("file") MultipartFile file) throws Exception { Map<String, Object> map = new HashMap<>(); map.put("code", "2000"); map.put("size", file.getBytes().length); return map; }
服务端接收文件的处理方式如下:推荐使用transferTo 速度比较快
/** * 1、获取 流 方式处理 * * @param file * @return * @throws Exception */ @RequestMapping("/uploadHandler1") @ResponseBody public Object uploadHandler1(@RequestParam("file") MultipartFile file) throws Exception { Map<String, Object> map = new HashMap<>(); map.put("code", "2000"); map.put("size", file.getBytes().length); //获取输入流 CommonsMultipartFile 中可以直接得到文件的流 InputStream is = file.getInputStream(); return map; } /** * 2、使用file.Transto 来保存上传的文件 * * @param file * @return * @throws Exception */ @RequestMapping("/uploadHandler2") @ResponseBody public Object uploadHandler2(@RequestParam("file") MultipartFile file) throws Exception { Map<String, Object> map = new HashMap<>(); map.put("code", "2000"); map.put("size", file.getBytes().length); File newFile = new File("path"); //通过CommonsMultipartFile的方法直接写文件(注意这个时候) file.transferTo(newFile); return map; } /** * 3、使用HttpServletRequest 自己写 * * @param file * @return * @throws Exception */ @RequestMapping("/uploadHandler3") @ResponseBody public Object uploadHandler3(HttpServletRequest request) throws Exception { Map<String, Object> map = new HashMap<>(); map.put("code", "2000"); //将当前上下文初始化给 CommonsMutipartResolver (多部分解析器) CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver( request.getSession().getServletContext()); //检查form中是否有enctype="multipart/form-data" if (multipartResolver.isMultipart(request)) { //将request变成多部分request MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; //获取multiRequest 中所有的文件名 Iterator iter = multiRequest.getFileNames(); while (iter.hasNext()) { //一次遍历所有文件 MultipartFile file = multiRequest.getFile(iter.next().toString()); if (file != null) { String path = "E:/springUpload" + file.getOriginalFilename(); //上传 file.transferTo(new File(path)); } } } return map; }
1.2、postman请求测试【可以导入以下json测试】
{ "id": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "name": "http", "description": "", "order": [], "folders": [ { "name": "form", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "order": [ "978d45f7-4673-4196-cacb-553699863f1d", "00d68b33-974d-78d2-27f0-09889b5a5a3c", "7060e912-d5d0-1731-9385-ce25fd0e88ff", "790f2d92-7482-de03-3fc1-56ae53635471", "bb8e21af-5acf-9f05-9c34-5f0425055e97", "f905ac7b-953a-88c7-00b2-d8b936be4207" ], "owner": 0, "folders_order": [], "id": "74f0c28e-dbc8-969d-f173-6864fb2acfa8" }, { "name": "json", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "order": [ "9f923f96-17e7-7a56-f044-f5962e47d046", "a3bd7e77-ada4-4842-e5e9-d9869b30d0ab", "c804a86e-a365-8b2a-6ceb-c548fc1d2f15", "308d4f4b-493e-ed41-5aec-97b4789fb12c", "317dfa64-1b31-e0b9-b9b0-50e7430455ee", "fb811f2b-03b1-23b3-3077-5c56edf8a030", "063968d2-c7af-59d4-c906-e0c38baf1184", "86bbfbce-1fb2-2c85-4036-f1d6605046af" ], "owner": 0, "folders_order": [], "id": "1759fa83-80ac-112b-d732-ef84cef8b692" }, { "name": "multipart", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "order": [ "e86731bb-9efb-0cb9-7df7-19cafbe581cd", "fc04a41c-6123-d2ce-81f1-96ec54989acc", "26cd6e2d-d115-d62b-6051-8db5b52e9299", "cecfce52-448e-1016-946d-b6e4e50561d2", "24b708d1-4f64-1700-2c84-c743bf689fc5", "e90f5a7b-e924-131e-0b2a-0dd6a467c222", "8654a7de-9249-0f63-4b78-243e2524f6a6", "687c99c6-75b5-6c17-b93a-da10735a14dc", "8dbe5329-7512-528d-61b2-df1f376ba48e", "c317bed2-1ab8-4ac0-1570-72de93f140cd" ], "owner": 0, "folders_order": [], "id": "70d362df-168c-a821-3b29-cac943e77301" } ], "folders_order": [ "74f0c28e-dbc8-969d-f173-6864fb2acfa8", "1759fa83-80ac-112b-d732-ef84cef8b692", "70d362df-168c-a821-3b29-cac943e77301" ], "timestamp": 1564578515435, "owner": 0, "public": false, "requests": [ { "id": "00d68b33-974d-78d2-27f0-09889b5a5a3c", "headers": "Content-Type: application/x-www-form-urlencoded ", "headerData": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded", "description": "", "enabled": true } ], "url": "http://localhost:8080/form/params?id=1", "folder": "74f0c28e-dbc8-969d-f173-6864fb2acfa8", "queryParams": [ { "key": "id", "value": "1", "equals": true, "description": "", "enabled": true } ], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [ { "key": "id", "value": "id", "description": "", "type": "text", "enabled": true }, { "key": "msg", "value": "msg好的", "description": "", "type": "text", "enabled": true } ], "dataMode": "urlencoded", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564582887199, "name": "/form/params-url-body ok", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "063968d2-c7af-59d4-c906-e0c38baf1184", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/json/paramsobject1?name=name&age=344", "folder": "1759fa83-80ac-112b-d732-ef84cef8b692", "queryParams": [ { "key": "name", "value": "name", "equals": true, "description": "", "enabled": true }, { "key": "age", "value": "344", "equals": true, "description": "", "enabled": true } ], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "raw", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564583900424, "name": "/paramsobject1-url no", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [], "rawModeData": "{}" }, { "id": "24b708d1-4f64-1700-2c84-c743bf689fc5", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/multipart/paramsobject?name=name&age=34", "folder": "70d362df-168c-a821-3b29-cac943e77301", "queryParams": [ { "key": "name", "value": "name", "equals": true, "description": "", "enabled": true }, { "key": "age", "value": "34", "equals": true, "description": "", "enabled": true } ], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "params", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564584125617, "name": "/paramsobject-url ok", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "26cd6e2d-d115-d62b-6051-8db5b52e9299", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/multipart/params1?id=1&msg=2", "folder": "1759fa83-80ac-112b-d732-ef84cef8b692", "queryParams": [ { "key": "id", "value": "1", "equals": true, "description": "", "enabled": true }, { "key": "msg", "value": "2", "equals": true, "description": "", "enabled": true } ], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "params", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564584050000, "name": "/params1-url ok", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "308d4f4b-493e-ed41-5aec-97b4789fb12c", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/json/params1", "folder": "1759fa83-80ac-112b-d732-ef84cef8b692", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "raw", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564583093792, "name": "/json/params1-body no", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [], "rawModeData": "{ "id":"test", "msg":"testmsg" }" }, { "id": "317dfa64-1b31-e0b9-b9b0-50e7430455ee", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/json/paramsobject?name=name&age=34", "folder": "1759fa83-80ac-112b-d732-ef84cef8b692", "queryParams": [ { "key": "name", "value": "name", "equals": true, "description": "", "enabled": true }, { "key": "age", "value": "34", "equals": true, "description": "", "enabled": true } ], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "raw", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564583810467, "name": "/paramsobject-url ok", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [], "rawModeData": "{ "name":"test", "age":11 }" }, { "id": "687c99c6-75b5-6c17-b93a-da10735a14dc", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/multipart/paramsobject1", "folder": "70d362df-168c-a821-3b29-cac943e77301", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [ { "key": "name", "value": "dd", "description": "", "type": "text", "enabled": true }, { "key": "age", "value": "444", "description": "", "type": "text", "enabled": true } ], "dataMode": "params", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564584249114, "name": "/paramsobject1-body no", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "7060e912-d5d0-1731-9385-ce25fd0e88ff", "headers": "Content-Type: application/x-www-form-urlencoded ", "headerData": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded", "description": "", "enabled": true } ], "url": "http://localhost:8080/form/paramsobject", "folder": "74f0c28e-dbc8-969d-f173-6864fb2acfa8", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [ { "key": "name", "value": "张三", "description": "", "type": "text", "enabled": true }, { "key": "age", "value": "14", "description": "", "type": "text", "enabled": true } ], "dataMode": "urlencoded", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564582834878, "name": "/form/paramsobject-body ok", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "790f2d92-7482-de03-3fc1-56ae53635471", "headers": "Content-Type: application/x-www-form-urlencoded ", "headerData": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded", "description": "", "enabled": true } ], "url": "http://localhost:8080/form/paramsobject?name=dddd&age=44", "folder": "74f0c28e-dbc8-969d-f173-6864fb2acfa8", "queryParams": [ { "key": "name", "value": "dddd", "equals": true, "description": "", "enabled": true }, { "key": "age", "value": "44", "equals": true, "description": "", "enabled": true } ], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "urlencoded", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564582826381, "name": "/form/paramsobject-url ok", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "8654a7de-9249-0f63-4b78-243e2524f6a6", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/multipart/paramsobject1?name=name&age=344", "folder": "1759fa83-80ac-112b-d732-ef84cef8b692", "queryParams": [ { "key": "name", "value": "name", "equals": true, "description": "", "enabled": true }, { "key": "age", "value": "344", "equals": true, "description": "", "enabled": true } ], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "params", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564584216952, "name": "/paramsobject1-url no", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "86bbfbce-1fb2-2c85-4036-f1d6605046af", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/json/paramsobject1", "folder": "1759fa83-80ac-112b-d732-ef84cef8b692", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "raw", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564583920864, "name": "/paramsobject1-body ok", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [], "rawModeData": "{ "name":"testbody", "age":34 }" }, { "id": "8dbe5329-7512-528d-61b2-df1f376ba48e", "headers": "", "headerData": [], "url": "http://localhost:8080/multipart/upload", "folder": "70d362df-168c-a821-3b29-cac943e77301", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [ { "key": "file", "value": "kv_chaincode.go", "description": "", "type": "file", "enabled": true } ], "dataMode": "params", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564623902014, "name": "/upload", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "978d45f7-4673-4196-cacb-553699863f1d", "headers": "Content-Type: application/x-www-form-urlencoded ", "headerData": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded", "description": "", "enabled": true } ], "url": "/form/noparam", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "urlencoded", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564582895759, "name": "http://localhost:8080/form/noparam", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "9f923f96-17e7-7a56-f044-f5962e47d046", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/json/noparam", "folder": "1759fa83-80ac-112b-d732-ef84cef8b692", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "raw", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564582948348, "name": "/json/noparam", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [], "rawModeData": "" }, { "id": "a3bd7e77-ada4-4842-e5e9-d9869b30d0ab", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/json/params", "folder": "74f0c28e-dbc8-969d-f173-6864fb2acfa8", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "raw", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564582971271, "name": "/json/params-url-body no", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [], "rawModeData": "{ "id":"test", "msg":"testmsg" }" }, { "id": "bb8e21af-5acf-9f05-9c34-5f0425055e97", "headers": "Content-Type: application/x-www-form-urlencoded ", "headerData": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded", "description": "", "enabled": true } ], "url": "http://localhost:8080/form/paramsobject1", "folder": "74f0c28e-dbc8-969d-f173-6864fb2acfa8", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [ { "key": "name", "value": "张三", "description": "", "type": "text", "enabled": true }, { "key": "age", "value": "14", "description": "", "type": "text", "enabled": true } ], "dataMode": "urlencoded", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564582811910, "name": "/form/paramsobject1-body no", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "c317bed2-1ab8-4ac0-1570-72de93f140cd", "headers": "", "headerData": [], "url": "http://localhost:8080/multipart/uploadFileParam", "folder": "70d362df-168c-a821-3b29-cac943e77301", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [ { "key": "file", "value": "kv_chaincode.go", "description": "", "type": "file", "enabled": true }, { "key": "msg", "value": "sss", "description": "", "type": "text", "enabled": true } ], "dataMode": "params", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564624976358, "name": "/uploadFileParam", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "c804a86e-a365-8b2a-6ceb-c548fc1d2f15", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/json/params1?id=1&msg=2", "folder": "1759fa83-80ac-112b-d732-ef84cef8b692", "queryParams": [ { "key": "id", "value": "1", "equals": true, "description": "", "enabled": true }, { "key": "msg", "value": "2", "equals": true, "description": "", "enabled": true } ], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "raw", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564583107550, "name": "/json/params1-url ok", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [], "rawModeData": "{ "id":"test", "msg":"testmsg" }" }, { "id": "cecfce52-448e-1016-946d-b6e4e50561d2", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/multipart/params1", "folder": "1759fa83-80ac-112b-d732-ef84cef8b692", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [ { "key": "id", "value": "sss", "description": "", "type": "text", "enabled": true }, { "key": "msg", "value": "ddd", "description": "", "type": "text", "enabled": true } ], "dataMode": "params", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564583767966, "name": "/params1-body no", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "e86731bb-9efb-0cb9-7df7-19cafbe581cd", "headers": "", "headerData": [], "url": "http://localhost:8080/multipart/params?id=1&msg=1", "folder": "1759fa83-80ac-112b-d732-ef84cef8b692", "queryParams": [ { "key": "id", "value": "1", "equals": true, "description": "", "enabled": true }, { "key": "msg", "value": "1", "equals": true, "description": "", "enabled": true } ], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "params", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564584016104, "name": "/params-url ok", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "e90f5a7b-e924-131e-0b2a-0dd6a467c222", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/multipart/paramsobject", "folder": "70d362df-168c-a821-3b29-cac943e77301", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [ { "key": "name", "value": "dd", "description": "", "type": "text", "enabled": true }, { "key": "age", "value": "11", "description": "", "type": "text", "enabled": true } ], "dataMode": "params", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564584163217, "name": "/paramsobject-body no", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "f905ac7b-953a-88c7-00b2-d8b936be4207", "headers": "Content-Type: application/x-www-form-urlencoded ", "headerData": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded", "description": "", "enabled": true } ], "url": "http://localhost:8080/form/paramsobject1?name=dddd&age=44", "folder": "74f0c28e-dbc8-969d-f173-6864fb2acfa8", "queryParams": [ { "key": "name", "value": "dddd", "equals": true, "description": "", "enabled": true }, { "key": "age", "value": "44", "equals": true, "description": "", "enabled": true } ], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "urlencoded", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564582819307, "name": "/form/paramsobject1-url no", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] }, { "id": "fb811f2b-03b1-23b3-3077-5c56edf8a030", "headers": "Content-Type: application/json ", "headerData": [ { "key": "Content-Type", "value": "application/json", "description": "", "enabled": true } ], "url": "http://localhost:8080/json/paramsobject", "folder": "1759fa83-80ac-112b-d732-ef84cef8b692", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [], "dataMode": "raw", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564583824765, "name": "/paramsobject-body no", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [], "rawModeData": "{ "name":"test", "age":11 }" }, { "id": "fc04a41c-6123-d2ce-81f1-96ec54989acc", "headers": "", "headerData": [], "url": "http://localhost:8080/multipart/params", "folder": "70d362df-168c-a821-3b29-cac943e77301", "queryParams": [], "preRequestScript": null, "pathVariables": {}, "pathVariableData": [], "method": "POST", "data": [ { "key": "id", "value": "sss", "description": "", "type": "text", "enabled": true }, { "key": "msg", "value": "ddd", "description": "", "type": "text", "enabled": true } ], "dataMode": "params", "tests": null, "currentHelper": "normal", "helperAttributes": {}, "time": 1564584036668, "name": "/params-body no", "description": "", "collectionId": "a8b343a0-434d-0f97-0757-65cc1e9591b7", "responses": [] } ] }
1.3、其他针对
spring的requestbody,requestparam等参看 012-Spring Boot web【一】web项目搭建、请求参数、RestController、使用jsp、freemarker,web容器tomcat和jetty
二、常用http client 介绍
spring常用客户端模板工具:RestTemplate
常用http客户端:jdk的HttpURLConnection【默认】、apache的httpClient、okhttp3等
2.1、连接模板RestTemplate
RestTemplate是spring的一个rest客户端,在spring-web这个包下.
RestTemplate只是对其它Rest客户端的一个封装,本身并没有自己的实现。只不过里面添加了默认实现
在ClientHttpRequestFactory的实现那张图中列出了RestTemplate的几种REST Client的封装。在没有第三方依赖的情况下其默认实现是URLConnection。
常用的有以下三种:
SimpleClientHttpRequestFactory(封装URLConnection)
HttpComponentsClientHttpRequestFactory(封装HttpClient)
OkHttp3ClientHttpRequestFactory(封装OKHttp)
2.2.1、SimpleClientHttpRequestFactory使用【模式实现】
@Test public void noparam() { RestTemplate restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory()); // new RestTemplate(); 等价于 new RestTemplate(new SimpleClientHttpRequestFactory()); String s = restTemplate.postForObject("http://localhost:8080/form/noparam", null, String.class); System.out.println(s); }
2.2.1、HttpComponentsClientHttpRequestFactory使用
pom依赖
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.6</version> </dependency>
如果没有pom导入apache httpclient使用下属会报错
@Test public void noparam2() { RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); String s = restTemplate.postForObject("http://localhost:8080/form/noparam", null, String.class); System.out.println(s); }
2.2.1、OkHttp3ClientHttpRequestFactory使用
pom依赖
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.0.0</version> </dependency>
代码
@Test public void noparam3() { RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory()); String s = restTemplate.postForObject("http://localhost:8080/form/noparam", null, String.class); System.out.println(s); }
由上述可见RestTemplate规避了底层实现。
一般选用一种httpclient实现即可
2.2、okhttp3使用
2.3、apache的httpclient使用
三、Http连接池
有限资源使用,就需要连接池
如果不复用连接池,会有多少发多少,浪费资源以及拖垮机器
3.1、RestTemplate配合实现端连接池
3.1.1、结合SimpleClientHttpRequestFactory
没有连接池实现,但是可以增加配置参数
@Test public void SimpleClientHttpRequestFactoryPool() { SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setReadTimeout(5000); requestFactory.setConnectTimeout(5000); // 添加转换器 List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(); messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8"))); messageConverters.add(new FormHttpMessageConverter()); // messageConverters.add(new MappingJackson2XmlHttpMessageConverter()); messageConverters.add(new MappingJackson2HttpMessageConverter()); RestTemplate restTemplate = new RestTemplate(messageConverters); restTemplate.setRequestFactory(requestFactory); restTemplate.setErrorHandler(new DefaultResponseErrorHandler()); String s = restTemplate.postForObject("http://localhost:8080/form/noparam", null, String.class); System.out.println(s); }
配置
3.1.2、结合Httpclient连接池的方式【推荐】
可以通过xml或者java类bean方式
spring xml
<!--使用httpclient的实现,带连接池--> <!--在httpclient4.3版本后才有--> <bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create"> <property name="connectionManager"> <bean class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager"> <!--整个连接池的并发--> <property name="maxTotal" value="50"/> <!--每个主机的并发--> <property name="defaultMaxPerRoute" value="50"/> </bean> </property> <!--开启重试--> <property name="retryHandler"> <bean class="org.apache.http.impl.client.DefaultHttpRequestRetryHandler"> <constructor-arg value="2"/> <constructor-arg value="true"/> </bean> </property> <property name="defaultHeaders"> <list> <bean class="org.apache.http.message.BasicHeader"> <constructor-arg value="Content-Type"/> <constructor-arg value="text/html;charset=UTF-8"/> </bean> <bean class="org.apache.http.message.BasicHeader"> <constructor-arg value="Accept-Encoding"/> <constructor-arg value="gzip,deflate"/> </bean> <bean class="org.apache.http.message.BasicHeader"> <constructor-arg value="Accept-Language"/> <constructor-arg value="zh-CN"/> </bean> </list> </property> </bean> <bean id="httpClient" factory-bean="httpClientBuilder" factory-method="build"/> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> <!-- <property name="messageConverters">--> <!-- <list value-type="org.springframework.http.converter.HttpMessageConverter">--> <!-- <bean class="org.springframework.http.converter.StringHttpMessageConverter">--> <!-- <property name="supportedMediaTypes">--> <!-- <value>text/html;charset=UTF-8</value>--> <!-- </property>--> <!-- </bean>--> <!-- <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">--> <!-- <property name="supportedMediaTypes">--> <!-- <value>application/json;charset=UTF-8</value>--> <!-- </property>--> <!-- </bean>--> <!-- <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>--> <!-- <bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>--> <!-- <bean class="org.springframework.http.converter.FormHttpMessageConverter"/>--> <!-- <bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter"/>--> <!-- </list>--> <!-- </property>--> <property name="requestFactory"> <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"> <constructor-arg ref="httpClient"/> <!--连接时间(毫秒)--> <property name="connectTimeout" value="20000"/> <!--读取时间(毫秒)--> <property name="readTimeout" value="20000"/> </bean> </property> </bean>
java代码
@Configuration public class RestTemplateUtil{ @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { RestTemplate restTemplate = builder.build(); restTemplate.setRequestFactory(clientHttpRequestFactory()); // 使用 utf-8 编码集的 conver 替换默认的 conver(默认的 string conver 的编码集为"ISO-8859-1") List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters(); Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator(); while (iterator.hasNext()) { HttpMessageConverter<?> converter = iterator.next(); if (converter instanceof StringHttpMessageConverter) { iterator.remove(); } } messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8"))); return restTemplate; } @Bean public HttpClientConnectionManager poolingConnectionManager() { PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(); poolingConnectionManager.setMaxTotal(1000); // 连接池最大连接数 poolingConnectionManager.setDefaultMaxPerRoute(100); // 每个主机的并发 return poolingConnectionManager; } @Bean public HttpClientBuilder httpClientBuilder() { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); //设置HTTP连接管理器 httpClientBuilder.setConnectionManager(poolingConnectionManager()); return httpClientBuilder; } @Bean public ClientHttpRequestFactory clientHttpRequestFactory() { HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(); clientHttpRequestFactory.setHttpClient(httpClientBuilder().build()); clientHttpRequestFactory.setConnectTimeout(6000); // 连接超时,毫秒 clientHttpRequestFactory.setReadTimeout(6000); // 读写超时,毫秒 return clientHttpRequestFactory; } }
其中注意
- maxTotal 是整个连接池的最大连接数
- defaultMaxPerRoute 是每个route默认的最大连接数【可以理解为每个url同时请求数】
- setMaxPerRoute(final HttpRoute route, final int max) route的最大连接数,优先于defaultMaxPerRoute。
//defaultMaxPerRoute默认为2,maxTotal默认为20
测试一
服务端处理逻辑 3s
http连接池:maxTotal=50,defaultMaxPerRoute=50
客户端 100个并发请求,分析:约6s执行完毕
@Autowired private RestTemplate restTemplate; @Test public void HttpComponentsClientHttpRequestFactoryPool() throws Exception { List<Future<String>> list=new ArrayList<Future<String>>(); long start = System.currentTimeMillis(); ExecutorService fixedThreadPool = Executors.newFixedThreadPool(100); for (int i = 0; i < 100; i++) { Future<String> submit = fixedThreadPool.submit(() -> { String s = restTemplate.postForObject("http://localhost:8080/form/noparam", null, String.class); return s; }); list.add(submit); } fixedThreadPool.shutdown(); System.out.println("装载耗时:" + (System.currentTimeMillis() - start) + "ms"); System.out.println("个数:" + list.size()); for (Future<String> future : list) { System.out.println(future.get()); } System.out.println("回调耗时:" + (System.currentTimeMillis() - start) + "ms"); }
输出:
装载耗时:17ms 个数:100 {"code":"2000"} //…… {"code":"2000"} 总计执行完毕耗时:6200ms
测试二
服务端处理逻辑 3s
http连接池:maxTotal=50,defaultMaxPerRoute=25
客户端 100个并发请求,,分析:约12s执行完毕
装载耗时:28ms 个数:100 {"code":"2000"} //…… {"code":"2000"} 总计执行完毕耗时:12236ms
3.1.3、结合okhttp3连接池的方式
研究中
3.2、小结
jdk:RestTemplate restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory()); 没有连接池,受服务端连接数限制【如tomcat默认200】,以及客户端请求限制
apache:RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); 不配置默认5个,需配置,但也受服务端连接数限制【如tomcat默认200】,以及客户端请求限制
okhttp3:RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory());没有配置连接池,受服务端连接数限制【如tomcat默认200】,以及客户端请求限制
对比
客户端 | 连接池 | 推荐 |
SimpleClientHttpRequestFactory | 无 | 不推荐 |
HttpComponentsClientHttpRequestFactory | 有 | 推荐 |
OkHttp3ClientHttpRequestFactory | 无 | 原来手机端常用 |