java实现HTTP请求的三种方式
目前JAVA实现HTTP请求的方法用的最多的有两种:一种是通过HTTPClient这种第三方的开源框架去实现。HTTPClient对HTTP的封装性比较不错,通过它基本上能够满足我们大部分的需求,HttpClient3.1 是 org.apache.commons.httpclient下操作远程 url的工具包,虽然已不再更新,但实现工作中使用httpClient3.1的代码还是很多,HttpClient4.5是org.apache.http.client下操作远程 url的工具包,最新的;另一种则是通过HttpURLConnection去实现,HttpURLConnection是JAVA的标准类,是JAVA比较原生的一种实现方式。 自己在工作中三种方式都用到过,总结一下分享给大家,也方便自己以后使用,话不多说上代码。 第一种方式:java原生HttpURLConnection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
package com.powerX.httpClient; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class HttpClient { public static String doGet(String httpurl) { HttpURLConnection connection = null; InputStream is = null; BufferedReader br = null; String result = null;// 返回结果字符串 try { // 创建远程url连接对象 URL url = new URL(httpurl); // 通过远程url连接对象打开一个连接,强转成httpURLConnection类 connection = (HttpURLConnection) url.openConnection(); // 设置连接方式:get connection.setRequestMethod("GET"); // 设置连接主机服务器的超时时间:15000毫秒 connection.setConnectTimeout(15000); // 设置读取远程返回的数据时间:60000毫秒 connection.setReadTimeout(60000); // 发送请求 connection.connect(); // 通过connection连接,获取输入流 if (connection.getResponseCode() == 200) { is = connection.getInputStream(); // 封装输入流is,并指定字符集 br = new BufferedReader(new InputStreamReader(is, "UTF-8")); // 存放数据 StringBuffer sbf = new StringBuffer(); String temp = null; while ((temp = br.readLine()) != null) { sbf.append(temp); sbf.append("\r\n"); } result = sbf.toString(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (null != br) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } connection.disconnect();// 关闭远程连接 } return result; } public static String doPost(String httpUrl, String param) { HttpURLConnection connection = null; InputStream is = null; OutputStream os = null; BufferedReader br = null; String result = null; try { URL url = new URL(httpUrl); // 通过远程url连接对象打开连接 connection = (HttpURLConnection) url.openConnection(); // 设置连接请求方式 connection.setRequestMethod("POST"); // 设置连接主机服务器超时时间:15000毫秒 connection.setConnectTimeout(15000); // 设置读取主机服务器返回数据超时时间:60000毫秒 connection.setReadTimeout(60000); // 默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true connection.setDoOutput(true); // 默认值为:true,当前向远程服务读取数据时,设置为true,该参数可有可无 connection.setDoInput(true); // 设置传入参数的格式:请求参数应该是 name1=value1&name2=value2 的形式。 connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // 设置鉴权信息:Authorization: Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0 connection.setRequestProperty("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0"); // 通过连接对象获取一个输出流 os = connection.getOutputStream(); // 通过输出流对象将参数写出去/传输出去,它是通过字节数组写出的 os.write(param.getBytes()); // 通过连接对象获取一个输入流,向远程读取 if (connection.getResponseCode() == 200) { is = connection.getInputStream(); // 对输入流对象进行包装:charset根据工作项目组的要求来设置 br = new BufferedReader(new InputStreamReader(is, "UTF-8")); StringBuffer sbf = new StringBuffer(); String temp = null; // 循环遍历一行一行读取数据 while ((temp = br.readLine()) != null) { sbf.append(temp); sbf.append("\r\n"); } result = sbf.toString(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (null != br) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != os) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } // 断开与远程地址url的连接 connection.disconnect(); } return result; } } |
第二种方式:apache HttpClient3.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
package com.powerX.httpClient; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.params.HttpMethodParams; public class HttpClient3 { public static String doGet(String url) { // 输入流 InputStream is = null; BufferedReader br = null; String result = null; // 创建httpClient实例 HttpClient httpClient = new HttpClient(); // 设置http连接主机服务超时时间:15000毫秒 // 先获取连接管理器对象,再获取参数对象,再进行参数的赋值 httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(15000); // 创建一个Get方法实例对象 GetMethod getMethod = new GetMethod(url); // 设置get请求超时为60000毫秒 getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 60000); // 设置请求重试机制,默认重试次数:3次,参数设置为true,重试机制可用,false相反 getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, true)); try { // 执行Get方法 int statusCode = httpClient.executeMethod(getMethod); // 判断返回码 if (statusCode != HttpStatus.SC_OK) { // 如果状态码返回的不是ok,说明失败了,打印错误信息 System.err.println("Method faild: " + getMethod.getStatusLine()); } else { // 通过getMethod实例,获取远程的一个输入流 is = getMethod.getResponseBodyAsStream(); // 包装输入流 br = new BufferedReader(new InputStreamReader(is, "UTF-8")); StringBuffer sbf = new StringBuffer(); // 读取封装的输入流 String temp = null; while ((temp = br.readLine()) != null) { sbf.append(temp).append("\r\n"); } result = sbf.toString(); } } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (null != br) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } // 释放连接 getMethod.releaseConnection(); } return result; } public static String doPost(String url, Map<String, Object> paramMap) { // 获取输入流 InputStream is = null; BufferedReader br = null; String result = null; // 创建httpClient实例对象 HttpClient httpClient = new HttpClient(); // 设置httpClient连接主机服务器超时时间:15000毫秒 httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(15000); // 创建post请求方法实例对象 PostMethod postMethod = new PostMethod(url); // 设置post请求超时时间 postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 60000); NameValuePair[] nvp = null; // 判断参数map集合paramMap是否为空 if (null != paramMap && paramMap.size() > 0) {// 不为空 // 创建键值参数对象数组,大小为参数的个数 nvp = new NameValuePair[paramMap.size()]; // 循环遍历参数集合map Set<Entry<String, Object>> entrySet = paramMap.entrySet(); // 获取迭代器 Iterator<Entry<String, Object>> iterator = entrySet.iterator(); int index = 0; while (iterator.hasNext()) { Entry<String, Object> mapEntry = iterator.next(); // 从mapEntry中获取key和value创建键值对象存放到数组中 try { nvp[index] = new NameValuePair(mapEntry.getKey(), new String(mapEntry.getValue().toString().getBytes("UTF-8"), "UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } index++; } } // 判断nvp数组是否为空 if (null != nvp && nvp.length > 0) { // 将参数存放到requestBody对象中 postMethod.setRequestBody(nvp); } // 执行POST方法 try { int statusCode = httpClient.executeMethod(postMethod); // 判断是否成功 if (statusCode != HttpStatus.SC_OK) { System.err.println("Method faild: " + postMethod.getStatusLine()); } // 获取远程返回的数据 is = postMethod.getResponseBodyAsStream(); // 封装输入流 br = new BufferedReader(new InputStreamReader(is, "UTF-8")); StringBuffer sbf = new StringBuffer(); String temp = null; while ((temp = br.readLine()) != null) { sbf.append(temp).append("\r\n"); } result = sbf.toString(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (null != br) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } // 释放连接 postMethod.releaseConnection(); } return result; } } |
第三种方式:apache httpClient4.5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
package com.powerX.httpClient; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; public class HttpClient4 { public static String doGet(String url) { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; String result = ""; try { // 通过址默认配置创建一个httpClient实例 httpClient = HttpClients.createDefault(); // 创建httpGet远程连接实例 HttpGet httpGet = new HttpGet(url); // 设置请求头信息,鉴权 httpGet.setHeader("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0"); // 设置配置请求参数 RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 连接主机服务超时时间 .setConnectionRequestTimeout(35000)// 请求超时时间 .setSocketTimeout(60000)// 数据读取超时时间 .build(); // 为httpGet实例设置配置 httpGet.setConfig(requestConfig); // 执行get请求得到返回对象 response = httpClient.execute(httpGet); // 通过返回对象获取返回数据 HttpEntity entity = response.getEntity(); // 通过EntityUtils中的toString方法将结果转换为字符串 result = EntityUtils.toString(entity); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (null != response) { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != httpClient) { try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } public static String doPost(String url, Map<String, Object> paramMap) { CloseableHttpClient httpClient = null; CloseableHttpResponse httpResponse = null; String result = ""; // 创建httpClient实例 httpClient = HttpClients.createDefault(); // 创建httpPost远程连接实例 HttpPost httpPost = new HttpPost(url); // 配置请求参数实例 RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 设置连接主机服务超时时间 .setConnectionRequestTimeout(35000)// 设置连接请求超时时间 .setSocketTimeout(60000)// 设置读取数据连接超时时间 .build(); // 为httpPost实例设置配置 httpPost.setConfig(requestConfig); // 设置请求头 httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded"); // 封装post请求参数 if (null != paramMap && paramMap.size() > 0) { List<NameValuePair> nvps = new ArrayList<NameValuePair>(); // 通过map集成entrySet方法获取entity Set<Entry<String, Object>> entrySet = paramMap.entrySet(); // 循环遍历,获取迭代器 Iterator<Entry<String, Object>> iterator = entrySet.iterator(); while (iterator.hasNext()) { Entry<String, Object> mapEntry = iterator.next(); nvps.add(new BasicNameValuePair(mapEntry.getKey(), mapEntry.getValue().toString())); } // 为httpPost设置封装好的请求参数 try { httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } try { // httpClient对象执行post请求,并返回响应参数对象 httpResponse = httpClient.execute(httpPost); // 从响应对象中获取响应内容 HttpEntity entity = httpResponse.getEntity(); result = EntityUtils.toString(entity); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (null != httpResponse) { try { httpResponse.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != httpClient) { try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } } |
有时候我们在使用post请求时,可能传入的参数是json或者其他格式,此时我们则需要更改请求头及参数的设置信息,以httpClient4.5为例,更改下面两列配置:httpPost.setEntity(new StringEntity("你的json串")); httpPost.addHeader("Content-Type", "application/json")。 from:https://www.cnblogs.com/hhhshct/p/8523697.html
View DetailsSpringboot HTTP Get/Post 请求讲解,Springboot几行代码完成Http请求
本文来自:https://www.sojson.com/blog/350.html 以前我们创建一个Http请求,很复杂,要写很多代码,而且请求还有各种兼容问题。而用 RestTemplate 的话优雅的几行代码就可以解决,并且是可以直接返回对象。 RestTemplate 是 Spring 用于同步请求client端的核心类,简化了与 HTTP 的通信,并满足RestFul原则,RestTemplate默认依赖 JDK 的HTTP连接工具。当然你也可以 通过setRequestFactory属性切换到不同的HTTP 数据源,比如Apache HttpComponents、Netty和OkHttp,都是支持的。 HTTP Get 请求 我们先做一个普通的Http请求,直接上源码。
1 2 3 4 5 6 7 8 9 10 11 12 |
try { HttpClient client = new HttpClient(); //创建一个Get请求 GetMethod method = new GetMethod("http://t.weather.sojson.com/api/weather/city/"+101010100); client.executeMethod(method); //获取String类型的返回值 String res = method.getResponseBodyAsString(); //使用gson转换为对象 WeatherDto dto = new Gson().fromJson(res,WeatherDto.class); } catch (IOException e) { e.printStackTrace(); } |
这是一个最简单的Http请求,把返回值使用 Gson 来转换成对象。 使用RestTemplate HTTP Get 请求
1 2 |
RestTemplate restTemplate = new RestTemplate(); WeatherDto dto = restTemplate.getForObject("http://t.weather.sojson.com/api/weather/city/"+101010100 , WeatherDto.class); |
上面其实是一个简单的带参数请求,用“{1}”、“{2}”、“{3}”… 方式传参,如果是地址拼接的方式,可以N个。 上一篇博客采用这个方式,模拟的Http请求,请求天气接口数据:https://www.sojson.com/blog/349.html 。 2.RestTemplate 多个参数请求 因为是Get请求,其实就是问号的方式带参数请求
1 2 3 4 |
Map<String,String> map = new HashMap(); map.put("id",101010100); RestTemplate restTemplate = new RestTemplate(); Details detail = restTemplate.getForObject("http://example.sojson.com/detail.html" , Details.class,map); |
3.RestTemplate getForEntity 请求 其实上面的1和2算是简单的请求,就是直接返回了Object 实例对象。而我们要获取详细的详细,如返回status、Header信息等。那就得用 getForEntity 。 看看源码里的参数描述,其实是和 getForObject 一致,我这里网络不行没下载下来源码包,凑合看看。
1 2 3 4 5 |
<T> ResponseEntity<T> getForEntity(String var1, Class<T> var2, Object... var3) throws RestClientException; <T> ResponseEntity<T> getForEntity(String var1, Class<T> var2, Map<String, ?> var3) throws RestClientException; <T> ResponseEntity<T> getForEntity(URI var1, Class<T> var2) throws RestClientException; |
HTTP 实例讲解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
RestTemplate restTemplate = new RestTemplate(); String url = "http://example.sojson.com/detail.html"; //添加请求头 HttpHeaders headers = new HttpHeaders(); //form表单提交 application/x-www-form-urlencoded headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); //组装参数 MultiValueMap<String, String> map= new LinkedMultiValueMap<>(); map.add("id", "101010100"); HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers); ResponseEntity<WeatherDto> response = restTemplate.postForEntity( url, request , WeatherDto.class ); //返回对象 WeatherDto dto = response.getBody(); //HTTP状态 int status = response.getStatusCodeValue(); //Spring 封装的 HttpStatus statusCode = response.getStatusCode(); //封装的对应状态请求,返回来都是 Boolean 类型 statusCode.is2xxSuccessful();//2开头的成功状态 statusCode.is3xxRedirection();//3开头重定向 statusCode.is4xxClientError();//4开头客户端错误 statusCode.is5xxServerError();//5开头服务端异常 |
具体可以自行测试下。 我们看源码知道还有 Post请求 方法。
1 2 |
restTemplate.postForEntity( ... ) restTemplate.postForObject(... ) |
方法传参是和上面讲解的 Get请求 的使用方式一模一样。 有兴趣的可以测试下我们的在线 HTTP模拟请求 工具 ,就是采用 restTemplate 实现的。 HTTP在线模拟请求 from:https://cloud.tencent.com/developer/article/1554561
View DetailsSpringBoot使用token简单鉴权
1.用户登录请求登录接口时,验证用户名密码等,验证成功会返回给前端一个token,这个token就是之后鉴权的唯一凭证。
2.后台可能将token存储在redis或者数据库中。
3.之后前端的请求,需要在header中携带token,后端取出token去redis或者数据库中进行验证,如果验证通过则放行,如果不通过则拒绝操作。
docker安装kafka
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
文本摘自此文章 1、kafka需要zookeeper管理,所以需要先安装zookeeper。 下载zookeeper镜像 $ docker pull wurstmeister/zookeeper 2、启动镜像生成容器 ## docker run -d --name zookeeper -p 2181:2181 -v /etc/localtime:/etc/localtime wurstmeister/zookeeper $ docker run -d --restart=always --log-driver json-file --log-opt max-size=100m --log-opt max-file=2 --name zookeeper -p 2181:2181 -v /etc/localtime:/etc/localtime wurstmeister/zookeeper 3、下载kafka镜像 $ docker pull wurstmeister/kafka 4、启动kafka镜像生成容器 ## docker run -d --name kafka -p 9092:9092 -e KAFKA_BROKER_ID=0 -e KAFKA_ZOOKEEPER_CONNECT=172.16.0.13:2181/kafka -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://172.16.0.13:9092 -e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 -v /etc/localtime:/etc/localtime wurstmeister/kafka $ docker run -d --restart=always --log-driver json-file --log-opt max-size=100m --log-opt max-file=2 --name kafka -p 9092:9092 -e KAFKA_BROKER_ID=0 -e KAFKA_ZOOKEEPER_CONNECT=172.16.0.13:2181/kafka -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://172.16.0.13:9092 -e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 -v /etc/localtime:/etc/localtime wurstmeister/kafka 参数说明: -e KAFKA_BROKER_ID=0 在kafka集群中,每个kafka都有一个BROKER_ID来区分自己 -e KAFKA_ZOOKEEPER_CONNECT=172.16.0.13:2181/kafka 配置zookeeper管理kafka的路径172.16.0.13:2181/kafka -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://172.16.0.13:9092 把kafka的地址端口注册给zookeeper,如果是远程访问要改成外网IP,类如Java程序访问出现无法连接。 -e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 配置kafka的监听端口 -v /etc/localtime:/etc/localtime 容器时间同步虚拟机的时间 5、验证kafka是否可以使用 5.1、进入容器 $ docker exec -it kafka bash 5.2、进入 /opt/kafka_2.12-2.3.0/bin/ 目录下 $ cd /opt/kafka_2.12-2.3.0/bin/ 5.3、运行kafka生产者发送消息 $ ./kafka-console-producer.sh --broker-list localhost:9092 --topic sun 发送消息 > {"datas":[{"channel":"","metric":"temperature","producer":"ijinus","sn":"IJA0101-00002245","time":"1543207156000","value":"80"}],"ver":"1.0"} 5.4、运行kafka消费者接收消息 $ ./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic sun --from-beginning |
from:https://www.cnblogs.com/linjiqin/p/11891776.html
View Details将VirtualBox里安装的虚拟机在后台运行方法(在状态栏隐藏窗口)
由于工作和学习需要,经常要开一个虚拟机开测试和开发,虚拟机我选择Oracle公司的VirtualBox(用了几年了,感觉不错的一款产品),经常开着这个窗口感觉有些浪费资源,这样隐藏窗口就在需求了。 将VirtualBox里安装的虚拟机在后台运行方法(在状态栏隐藏窗口) 开始=>运行=>cmd进入DOS窗口
1 2 3 |
d: cd D:\Program Files\VirtualBox D:\Program Files\VirtualBox> .\VBoxManage.exe startvm master --type headless |
这在Linux系统和MAC上同样适用,只要替换成相应的命令即可 解释:其中 master 是这个虚拟机的名称 Headless模式是系统的一种配置模式。在该模式下,系统缺少了显示设备、键盘或鼠标。<br>Headless模式针对在该模式下工作,尤其是服务器端程序开发者。因为服务器(如提供Web服务的主机)往往可能缺少前述设备,但又需要使用他们提供的功能,生成相应的数据,以提供给客户端(如浏览器所在的配有相关的显示设备、键盘和鼠标的主机)。 from:https://www.cnblogs.com/foonsun/p/5709784.html
View DetailsDocker入门 第三课 --Docker几个常用命令
平时使用Docker,主要是用客户端 Kitematic,但 Kitematic 只实现了基本的使用功能,如果想更深入的使用Docker,命令行还是必不可少的。 前两课中,已经介绍过几个Docker命令:
1 2 3 4 5 6 7 8 |
docker pull:从镜像仓库中拉取镜像 。 docker run:通过镜像创建一个新的容器,并运行。需要注意的是,如果本地没有指定的镜像,会直接去镜像库下载,一定要保证拼写正确。 docker stop:停止一个容器 。 docker start:启动一个容器 。 docker restart:重启一个容器 。 docker ps:列出当前运行的容器机器状态 。 docker images 或 docker image ls:列出本地镜像。 docker build:使用Dockerfile创建自己的镜像。 |
这里记录几个Docker使用过程中,最容易用的的基础命令,包括镜像构建,镜像操作,容器使用。 镜像构建: docker build [OPTIONS] PATH | URL | – -t name:tag 表示给镜像命名,并指定标签(相当于版本号) -f Dockerfile 指定Dockerfile文件,默认为’PATH/Dockerfile’,即当前目录下的Dockerfile-t name:tag 表示给镜像命名,并指定标签(相当于版本号) PATH 表示本地工作目录(也就是命令最后的 . ,我这里是项目文件夹) 示例:(注意命令的执行目录和工作目录) docker build -t slide-verify:1.0 . 镜像操作命令: 查看本机镜像:docker images 移除指定镜像: docker image rm 镜像ID docker rmi 镜像ID 清除无效镜像:docker image prune(清除没有名称且未被使用的镜像) 查看镜像信息:docker inspect 镜像ID 容器操作命令: 运行容器:docker run -it -p 5000:80 --name slide-verify10 slide-verify:1.0 查看运行中的容器: docker ps docker container ls 查看全部容器:docker ps -a 移除容器:docker container rm 容器ID 启动容器:docker start 容器ID 关闭容器:docker stop 容器ID 重启容器:docker restart 容器ID 进入容器:docker exec -it 容器ID /bin/bash (相当于远程登录虚拟机) 退出容器:exit […]
View DetailsDocker入门 第二课 --镜像构建,Dockerfile解读
今天聊一聊Dockerfile,docker build,希望通过这篇文章,能让你对docker镜像构建过程有一个认识。 事情还得从一次Docker镜像创建失败说起。 问题背景: 环境VS2017,dotnet 2.1 版本 ,使用默认生成的Dockerfile文件,当我使用docker build命令创建镜像的时候,竟然报错了
1 2 |
Step 6/16 : ...... COPY failed: stat /mnt/sda1/var/lib/docker/tmp/docker-builder802544848/EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj: no such file or directory |
错误信息是,第6步,找不到指定的文件或文件夹,由于我执行docker build命令的路径与 项目文件(xxx.csproj)在同一目录下,所以,这个文件找不到也很正常,那到底是哪里出问题了呢?我们来捋一捋。 执行docker build命令的路径与项目文件(xxx.csproj)在同一路径。 docker build 命令如下:
1 |
docker build -t slide-verify:1.0 . |
Dockerfile内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base WORKDIR /app EXPOSE 80 FROM microsoft/dotnet:2.1-sdk AS build WORKDIR /src COPY ["EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj", "EasySlideVerificationDemoServer/"] RUN dotnet restore "EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj" COPY . . WORKDIR "/src/EasySlideVerificationDemoServer" RUN dotnet build "EasySlideVerificationDemoServer.csproj" -c Release -o /app FROM build AS publish RUN dotnet publish "EasySlideVerificationDemoServer.csproj" -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . ENTRYPOINT ["dotnet", "EasySlideVerificationDemoServer.dll"] |
Docker镜像生成原理: Docker镜像与操作系统镜像本质上是一样的,首先需要一个基础镜像,然后在基础镜像上搭建所需环境,安装软件,最后生成一个新的镜像,新的镜像就可以在Docker中进行部署,生成容器实例,从而开始运行服务。 Dockerfile中的命令: 从上面Dockerfile中,我们可以看到有这几个命令:FROM,WORKDIR,EXPOSE,COPY,RUN,ENTRYPOINT,大概了解一下这几个命令的意思。 FROM: 指定一个基础镜像 WORKDIR: 在镜像内指定一个目录,作为当前工作目录 EXPOSE: 指定端口号 COPY: 从一个目录(这个目录可以是本地目录或中间镜像的目录)中复制文件或者目录到容器里指定路径 RUN: 在镜像内执行相应命令 ENTRYPOINT: 入口点,与RUN类似,同样是执行程序命令,表示容器启动时需要执行的命令。 Dockerfile文件解读: 我们来解读一下这个Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
将镜像 microsoft/dotnet:2.1-aspnetcore-runtime 作为基础镜像 (base) 指定镜像内工作目录为:/app 指定端口号为:80 将镜像 microsoft/dotnet:2.1-sdk 作为系统构建中间镜像(build) 指定镜像内工作目录为: /src 复制项目文件 "EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj" 到镜像目录 "EasySlideVerificationDemoServer/" 执行dotnet restore命令: dotnet restore "EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj" 复制当前目录下所有文件到镜像的工作目录(/src)下:COPY . . 指定新的工作目录: "/src/EasySlideVerificationDemoServer" 执行dotnet build命令: dotnet build "EasySlideVerificationDemoServer.csproj" -c Release -o /app 将构建好的中间镜像(build) 作为发布中间镜像(publish) 执行dotnet publish命令: dotnet publish "EasySlideVerificationDemoServer.csproj" -c Release -o /app 将基础镜像(base)作为最终镜像(final) 指定工作目录: /app 复制发布中间镜像(publish)中的/app目录到工作目录:COPY --from=publish /app . 指定入口点命令:ENTRYPOINT ["dotnet", "EasySlideVerificationDemoServer.dll"] |
解读完之后,我们了解了这个Dockerfile究竟做了哪些事情。 镜像构建命令: 然后看一下Docker镜像构建命令:docker build。 命令行输入:docker build --help,可查看完整使用方式,此处省略。 Usage: docker build [OPTIONS] PATH | URL | – 下面是我使用的构建命令:
1 |
docker build -t slide-verify:1.0 . |
-t name:tag 表示给镜像命名,并指定标签(相当于版本号) -f Dockerfile 指定Dockerfile文件,默认为’PATH/Dockerfile’,即当前目录下的Dockerfile PATH 表示本地工作目录(也就是命令最后的 . ,我这里是项目文件夹) 发现问题: 到这里不难发现,由于镜像构建命令的执行目录与项目文件所在目录一致,并且命令中PATH指定的是当前目录(.),也就是项目文件所在目录,而Dockerfile中文件复制命令明显是在项目文件的上一级,即解决方案文件夹目录, 这样问题似乎就容易解决了,将构建命令改成下面的格式,果不其然,构建成功。
1 |
docker build -t slide-verify:1.3 -f Dockerfile .. |
然后执行docker run命令,运行构建好的镜像,启动成功,浏览器访问:http://192.168.99.100:5008/ ,项目成功运行。
1 |
docker run -it -p 5008:80 --name slide-verify13 slide-verify:1.3 |
使用进阶: 我们回头再看一下Dockerfile文件,文件中的5到14行命令,包含了源码复制,项目还原(restore),构建(build),发布(publish)几个步骤。
1 2 3 4 5 6 7 8 9 10 |
FROM microsoft/dotnet:2.1-sdk AS build WORKDIR /src COPY ["EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj", "EasySlideVerificationDemoServer/"] RUN dotnet restore "EasySlideVerificationDemoServer/EasySlideVerificationDemoServer.csproj" COPY . . WORKDIR "/src/EasySlideVerificationDemoServer" RUN dotnet build "EasySlideVerificationDemoServer.csproj" -c Release -o /app FROM build AS publish RUN dotnet publish "EasySlideVerificationDemoServer.csproj" -c Release -o /app |
[…]
View DetailsDocker run 命令
docker run :创建一个新的容器并运行一个命令 语法
1 |
docker run [OPTIONS] IMAGE [COMMAND] [ARG...] |
OPTIONS说明: -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项; -d: 后台运行容器,并返回容器ID; -i: 以交互模式运行容器,通常与 -t 同时使用; -P: 随机端口映射,容器内部端口随机映射到主机的端口 -p: 指定端口映射,格式为:主机(宿主)端口:容器端口 -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用; --name="nginx-lb": 为容器指定一个名称; --dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致; --dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致; -h "mars": 指定容器的hostname; -e username="ritchie": 设置环境变量; --env-file=[]: 从指定文件读入环境变量; --cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行; -m :设置容器使用内存最大值; --net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container:<name|id> 四种类型; --link=[]: 添加链接到另一个容器; --expose=[]: 开放一个端口或一组端口; --volume , -v: 绑定一个卷 实例 使用docker镜像nginx:latest以后台模式启动一个容器,并将容器命名为mynginx。
1 |
docker run --name mynginx -d nginx:latest |
使用镜像nginx:latest以后台模式启动一个容器,并将容器的80端口映射到主机随机端口。
1 |
docker run -P -d nginx:latest |
使用镜像 nginx:latest,以后台模式启动一个容器,将容器的 80 端口映射到主机的 80 端口,主机的目录 /data 映射到容器的 /data。
1 |
docker run -p 80:80 -v /data:/data -d nginx:latest |
绑定容器的 8080 端口,并将其映射到本地主机 127.0.0.1 的 80 端口上。
1 |
$ docker run -p 127.0.0.1:80:8080/tcp ubuntu bash |
使用镜像nginx:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。
1 2 |
runoob@runoob:~$ docker run -it nginx:latest /bin/bash root@b8573233d675:/# |
from:https://www.runoob.com/docker/docker-run-command.html
View Details如何在已停止/未启动的Docker容器中编辑文件
有两种可能性。 1) 直接在主机上编辑文件系统 。这有些危险,并且有可能完全破坏容器,并可能根据发生的问题而破坏其他数据。 2) 将启动脚本更改为 永不失败的内容,例如启动bash,进行修复/编辑,然后将启动程序再次更改为所需的程序(例如节点或之前的版本)。 更多细节: 1)使用
1 2 |
docker ps |
查找正在运行的容器或
1 2 |
docker ps -a |
查找所有容器(包括停止的容器)并
1 2 |
docker inspect (containername) |
查找“ Id”,第一个值之一。 这是包含实现细节的部分,可能会更改,请注意,这样可能会丢失容器。 去
1 2 |
/var/lib/docker/aufs/diff/9bc343a9..(long container id)/ |
在那里您将找到所有更改为容器所基于的图像的文件。您可以覆盖文件,添加或编辑文件。 同样,我不建议这样做。 2)您可以在以下路径找到配置jsonconfig.json
1 2 |
/var/lib/docker/containers/9bc343a99..(long container id)/config.json |
在那里,您可以将参数从“ nodejs app.js”更改为“ / bin / bash”。现在重新启动docker服务并启动容器(您应该看到它现在已正确启动)。你应该用
1 2 |
docker start -i (containername) |
确保它不会立即退出。您现在可以使用容器和/或以后再附加
1 2 |
docker exec -ti (containername) /bin/bash |
另外,docker cp对于复制在容器外部编辑的文件非常有用。 同样,如果容器无论如何或多或少地“丢失”,则应该只使用那些措施,因此任何更改都是一种改进。 参考:http://codingdict.com/questions/53248
View Detailsredis 连接字符串,设置密码
<add name="Abp.Redis.Cache" connectionString="127.0.0.1:6379,password=123456"/> 参考:https://github.com/StackExchange/StackExchange.Redis/blob/master/Docs/Configuration.md from:https://www.cnblogs.com/lishidefengchen/p/10656327.html
View Details