HttpURLConnection是java的标准类,什么都没封装。

HTTPClient是个开源框架,封装了访问http的请求头,参数,内容体,响应等等。

简单来说,HTTPClient就是一个增强版的HttpURLConnection,HttpURLConnection可以做的事情HTTPClient全部可以做;HttpURLConnection没有提供的有些功能,HTTPClient也提供了,但它只是关注于如何发送请求、接收响应,以及管理HTTP连接。

实例:

    package com.cn.common.controller;  
      
    import java.io.BufferedReader;  
    import java.io.IOException;  
    import java.io.InputStream;  
    import java.io.InputStreamReader;  
    import java.net.HttpURLConnection;  
    import java.net.URL;  
      
    import javax.servlet.http.HttpServletRequest;  
    import javax.servlet.http.HttpServletResponse;  
      
    import org.apache.commons.httpclient.HttpClient;  
    import org.apache.commons.httpclient.HttpStatus;  
    import org.apache.commons.httpclient.methods.PostMethod;  
    import org.apache.commons.httpclient.params.HttpMethodParams;  
    import org.springframework.stereotype.Controller;  
    import org.springframework.web.bind.annotation.RequestMapping;  
    @Controller  
    @RequestMapping("/http")  
    public class HttpClientAndURLConnectionController {  
      
        @RequestMapping("/testHttp")  
        public void testHttp(HttpServletRequest req,HttpServletResponse resp) {  
            try {  
                long s1 = System.currentTimeMillis();  
                testHttpClient();  
                long s2 = System.currentTimeMillis();  
                testHttpURlConnection();  
                long s3 = System.currentTimeMillis();  
                System.out.println((s2-s1)+" "+(s3-s2));  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
        public void testHttpClient() throws IOException{  
            System.out.println("testHttpClient");  
            //请求方法  
            String result="";  
            String url = "http://192.168.2.111:8088/era/user/getUserById";  
            HttpClient client =new HttpClient();  
            //设置连接时间  
            client.getHttpConnectionManager().getParams().setConnectionTimeout(30000);  
            //解决乱码问题  
            client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"UTF-8");  
            PostMethod method =new PostMethod(url);  
            //传参  
            method.addParameter("userId", "100");  
            int status = client.executeMethod(method);  
            if(status == HttpStatus.SC_OK){  
                result = method.getResponseBodyAsString();  
            }  
            System.out.println(result);  
            method.releaseConnection();  
        }  
        public void testHttpURlConnection() throws IOException{  
            System.out.println("testHttpURlConnection");  
            String result = "";  
            URL url = new URL("http://192.168.2.111:8088/era/user/getUserById");  
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
            conn.setConnectTimeout(30000);//设置连接主机超时(单位:毫秒)  
            conn.setReadTimeout(30000);//设置从主机读取数据超时(单位:毫秒)  
            conn.setRequestMethod("POST");//设定请求的方法为"POST",默认是GET  
            conn.setDoInput(true);//设置是否从httpUrlConnection读入,默认情况下是true  
            conn.setDoOutput(true);//设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在http正文内,因此需要设为true, 默认情况下是false  
            conn.setUseCaches(false);//Post请求不能使用缓存  
            conn.setInstanceFollowRedirects(false);  
            conn.setRequestProperty("Content-Type", "text/html; charset=utf-8");  
            conn.connect();  
            int responsecode = conn.getResponseCode();  
            if(responsecode == HttpURLConnection.HTTP_OK){ //对应HTTP响应中状态行的响应码  
                //操作请求流,这里对应HTTP响应中的响应正文   
                InputStream urlStream = conn.getInputStream();  
                BufferedReader reader = new BufferedReader(new InputStreamReader(urlStream,"utf-8"));  
                String s = "";  
                while ((s = reader.readLine()) != null) {  
                    result += s;  
                }  
                reader.close();  
                urlStream.close();  
            }  
            System.out.println(result);  
            if(conn != null){  
                conn.disconnect();  
            }  
        }  
    }  

调用的url方法:

    @RequestMapping("/getUserById")  
    public void getUserById(HttpServletRequest req,HttpServletResponse resp) throws IOException{  
        resp.setContentType("text/html;charset=utf-8");  
        resp.setCharacterEncoding("UTF-8");  
        int userId;  
        if(null == req.getParameter("userId")){  
            userId = 100;  
        }else{  
            userId = Integer.parseInt(req.getParameter("userId"));  
        }  
        User user = this.userService.selectByPrimaryKey(userId);  
        ObjectMapper mapper = new ObjectMapper();  
        String result = mapper.writeValueAsString(user);  
        resp.getWriter().print(result);  
    }  

项目启动后,第一次执行testHttp方法后控制台信息:

    testHttpClient  
    2016-07-31 00:24:46,513 DEBUG [org.apache.commons.httpclient.HttpClient] - Java version: 1.7.0_75  
    2016-07-31 00:24:46,515 DEBUG [org.apache.commons.httpclient.HttpClient] - Java vendor: Oracle Corporation  
    2016-07-31 00:24:46,515 DEBUG [org.apache.commons.httpclient.HttpClient] - Java class path: D:\apache-tomcat-8.0.33/bin/bootstrap.jar;D:\apache-tomcat-8.0.33/bin/tomcat-juli.jar;D:\Program Files\Java\jdk1.7.0_75/lib/tools.jar  
    2016-07-31 00:24:46,515 DEBUG [org.apache.commons.httpclient.HttpClient] - Operating system name: Windows 8.1  
    2016-07-31 00:24:46,515 DEBUG [org.apache.commons.httpclient.HttpClient] - Operating system architecture: amd64  
    2016-07-31 00:24:46,515 DEBUG [org.apache.commons.httpclient.HttpClient] - Operating system version: 6.3  
    2016-07-31 00:24:46,516 DEBUG [org.apache.commons.httpclient.HttpClient] - SUN 1.7: SUN (DSA key/parameter generation; DSA signing; SHA-1, MD5 digests; SecureRandom; X.509 certificates; JKS keystore; PKIX CertPathValidator; PKIX CertPathBuilder; LDAP, Collection CertStores, JavaPolicy Policy; JavaLoginConfig Configuration)  
    2016-07-31 00:24:46,517 DEBUG [org.apache.commons.httpclient.HttpClient] - SunRsaSign 1.7: Sun RSA signature provider  
    2016-07-31 00:24:46,517 DEBUG [org.apache.commons.httpclient.HttpClient] - SunEC 1.7: Sun Elliptic Curve provider (EC, ECDSA, ECDH)  
    2016-07-31 00:24:46,517 DEBUG [org.apache.commons.httpclient.HttpClient] - SunJSSE 1.7: Sun JSSE provider(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)  
    2016-07-31 00:24:46,517 DEBUG [org.apache.commons.httpclient.HttpClient] - SunJCE 1.7: SunJCE Provider (implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, Diffie-Hellman, HMAC)  
    2016-07-31 00:24:46,517 DEBUG [org.apache.commons.httpclient.HttpClient] - SunJGSS 1.7: Sun (Kerberos v5, SPNEGO)  
    2016-07-31 00:24:46,517 DEBUG [org.apache.commons.httpclient.HttpClient] - SunSASL 1.7: Sun SASL provider(implements client mechanisms for: DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5, NTLM; server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5, NTLM)  
    2016-07-31 00:24:46,518 DEBUG [org.apache.commons.httpclient.HttpClient] - XMLDSig 1.0: XMLDSig (DOM XMLSignatureFactory; DOM KeyInfoFactory)  
    2016-07-31 00:24:46,518 DEBUG [org.apache.commons.httpclient.HttpClient] - SunPCSC 1.7: Sun PC/SC provider  
    2016-07-31 00:24:46,518 DEBUG [org.apache.commons.httpclient.HttpClient] - SunMSCAPI 1.7: Sun's Microsoft Crypto API provider  
    2016-07-31 00:24:46,535 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.useragent = Jakarta Commons-HttpClient/3.1  
    2016-07-31 00:24:46,549 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.protocol.version = HTTP/1.1  
    2016-07-31 00:24:46,556 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.connection-manager.class = class org.apache.commons.httpclient.SimpleHttpConnectionManager  
    2016-07-31 00:24:46,556 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.protocol.cookie-policy = default  
    2016-07-31 00:24:46,557 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.protocol.element-charset = US-ASCII  
    2016-07-31 00:24:46,557 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.protocol.content-charset = ISO-8859-1  
    2016-07-31 00:24:46,562 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.method.retry-handler = org.apache.commons.httpclient.DefaultHttpMethodRetryHandler@a9d5438  
    2016-07-31 00:24:46,563 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.dateparser.patterns = [EEE, dd MMM yyyy HH:mm:ss zzz, EEEE, dd-MMM-yy HH:mm:ss zzz, EEE MMM d HH:mm:ss yyyy, EEE, dd-MMM-yyyy HH:mm:ss z, EEE, dd-MMM-yyyy HH-mm-ss z, EEE, dd MMM yy HH:mm:ss z, EEE dd-MMM-yyyy HH:mm:ss z, EEE dd MMM yyyy HH:mm:ss z, EEE dd-MMM-yyyy HH-mm-ss z, EEE dd-MMM-yy HH:mm:ss z, EEE dd MMM yy HH:mm:ss z, EEE,dd-MMM-yy HH:mm:ss z, EEE,dd-MMM-yyyy HH:mm:ss z, EEE, dd-MM-yyyy HH:mm:ss z]  
    2016-07-31 00:24:46,588 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.connection.timeout = 30000  
    2016-07-31 00:24:46,588 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.protocol.content-charset = UTF-8  
    2016-07-31 00:24:46,727 DEBUG [org.apache.commons.httpclient.HttpConnection] - Open connection to 192.168.2.111:8088  
    2016-07-31 00:24:46,744 DEBUG [httpclient.wire.header] - >> "POST /era/user/getUserById HTTP/1.1[\r][\n]"  
    2016-07-31 00:24:46,747 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Adding Host request header  
    2016-07-31 00:24:46,871 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Default charset used: UTF-8  
    2016-07-31 00:24:46,900 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Default charset used: UTF-8  
    2016-07-31 00:24:46,902 DEBUG [httpclient.wire.header] - >> "User-Agent: Jakarta Commons-HttpClient/3.1[\r][\n]"  
    2016-07-31 00:24:46,903 DEBUG [httpclient.wire.header] - >> "Host: 192.168.2.111:8088[\r][\n]"  
    2016-07-31 00:24:46,903 DEBUG [httpclient.wire.header] - >> "Content-Length: 10[\r][\n]"  
    2016-07-31 00:24:46,903 DEBUG [httpclient.wire.header] - >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"  
    2016-07-31 00:24:46,907 DEBUG [httpclient.wire.header] - >> "[\r][\n]"  
    2016-07-31 00:24:46,911 DEBUG [httpclient.wire.content] - >> "userId=100"  
    2016-07-31 00:24:46,913 DEBUG [org.apache.commons.httpclient.methods.EntityEnclosingMethod] - Request body sent  
    2016-07-31 00:24:47,041 DEBUG [org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession  
    2016-07-31 00:24:47,074 DEBUG [org.mybatis.spring.SqlSessionUtils] - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@631e7edd] was not registered for synchronization because synchronization is not active  
    2016-07-31 00:24:47,168 DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@155b4677] will not be managed by Spring  
    2016-07-31 00:24:47,197 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - ==>  Preparing: select id, user_name, password, age from user where id = ?   
    2016-07-31 00:24:47,756 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - ==> Parameters: 100(Integer)  
    2016-07-31 00:24:47,848 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - <==      Total: 1  
    2016-07-31 00:24:47,852 DEBUG [com.alibaba.druid.pool.PreparedStatementPool] - {conn-10001, pstmt-20000} enter cache  
    2016-07-31 00:24:47,854 DEBUG [org.mybatis.spring.SqlSessionUtils] - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@631e7edd]  
    2016-07-31 00:24:48,085 DEBUG [httpclient.wire.header] - << "HTTP/1.1 200 OK[\r][\n]"  
    2016-07-31 00:24:48,086 DEBUG [httpclient.wire.header] - << "HTTP/1.1 200 OK[\r][\n]"  
    2016-07-31 00:24:48,089 DEBUG [httpclient.wire.header] - << "Server: Apache-Coyote/1.1[\r][\n]"  
    2016-07-31 00:24:48,090 DEBUG [httpclient.wire.header] - << "Content-Type: text/html;charset=UTF-8[\r][\n]"  
    2016-07-31 00:24:48,090 DEBUG [httpclient.wire.header] - << "Content-Length: 67[\r][\n]"  
    2016-07-31 00:24:48,090 DEBUG [httpclient.wire.header] - << "Date: Sat, 30 Jul 2016 16:24:48 GMT[\r][\n]"  
    2016-07-31 00:24:48,091 DEBUG [httpclient.wire.header] - << "[\r][\n]"  
    2016-07-31 00:24:48,095 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Buffering response body  
    2016-07-31 00:24:48,095 DEBUG [httpclient.wire.content] - << "{"id":100,"userName":"admin[0xe7][0xae][0xa1][0xe7][0x90][0x86][0xe5][0x91][0x98]","password":"123456","age":25}"  
    2016-07-31 00:24:48,097 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Resorting to protocol version default close connection policy  
    2016-07-31 00:24:48,097 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Should NOT close connection, using HTTP/1.1  
    2016-07-31 00:24:48,098 DEBUG [org.apache.commons.httpclient.HttpConnection] - Releasing connection back to connection manager.  
    {"id":100,"userName":"admin管理员","password":"123456","age":25}  
    testHttpURlConnection  
    2016-07-31 00:24:48,127 DEBUG [org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession  
    2016-07-31 00:24:48,129 DEBUG [org.mybatis.spring.SqlSessionUtils] - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ee42c08] was not registered for synchronization because synchronization is not active  
    2016-07-31 00:24:48,129 DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@155b4677] will not be managed by Spring  
    2016-07-31 00:24:48,130 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - ==>  Preparing: select id, user_name, password, age from user where id = ?   
    2016-07-31 00:24:48,131 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - ==> Parameters: 100(Integer)  
    2016-07-31 00:24:48,137 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - <==      Total: 1  
    2016-07-31 00:24:48,138 DEBUG [org.mybatis.spring.SqlSessionUtils] - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ee42c08]  
    {"id":100,"userName":"admin管理员","password":"123456","age":25}  
    1598 58  

第一次执行后:

  testHttpClient()用时:1598

  testHttpURlConnection()用时:58

第二次执行testHttp方法后控制台信息:


    testHttpClient  
    2016-07-31 00:28:09,582 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.connection.timeout = 30000  
    2016-07-31 00:28:09,582 DEBUG [org.apache.commons.httpclient.params.DefaultHttpParams] - Set parameter http.protocol.content-charset = UTF-8  
    2016-07-31 00:28:09,583 DEBUG [org.apache.commons.httpclient.HttpConnection] - Open connection to 192.168.2.111:8088  
    2016-07-31 00:28:09,586 DEBUG [httpclient.wire.header] - >> "POST /era/user/getUserById HTTP/1.1[\r][\n]"  
    2016-07-31 00:28:09,587 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Adding Host request header  
    2016-07-31 00:28:09,587 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Default charset used: UTF-8  
    2016-07-31 00:28:09,590 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Default charset used: UTF-8  
    2016-07-31 00:28:09,591 DEBUG [httpclient.wire.header] - >> "User-Agent: Jakarta Commons-HttpClient/3.1[\r][\n]"  
    2016-07-31 00:28:09,592 DEBUG [httpclient.wire.header] - >> "Host: 192.168.2.111:8088[\r][\n]"  
    2016-07-31 00:28:09,592 DEBUG [httpclient.wire.header] - >> "Content-Length: 10[\r][\n]"  
    2016-07-31 00:28:09,593 DEBUG [httpclient.wire.header] - >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"  
    2016-07-31 00:28:09,593 DEBUG [httpclient.wire.header] - >> "[\r][\n]"  
    2016-07-31 00:28:09,593 DEBUG [httpclient.wire.content] - >> "userId=100"  
    2016-07-31 00:28:09,594 DEBUG [org.apache.commons.httpclient.methods.EntityEnclosingMethod] - Request body sent  
    2016-07-31 00:28:09,601 DEBUG [org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession  
    2016-07-31 00:28:09,602 DEBUG [org.mybatis.spring.SqlSessionUtils] - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@240543cf] was not registered for synchronization because synchronization is not active  
    2016-07-31 00:28:09,603 DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@155b4677] will not be managed by Spring  
    2016-07-31 00:28:09,605 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - ==>  Preparing: select id, user_name, password, age from user where id = ?   
    2016-07-31 00:28:09,606 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - ==> Parameters: 100(Integer)  
    2016-07-31 00:28:09,611 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - <==      Total: 1  
    2016-07-31 00:28:09,612 DEBUG [org.mybatis.spring.SqlSessionUtils] - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@240543cf]  
    2016-07-31 00:28:09,616 DEBUG [httpclient.wire.header] - << "HTTP/1.1 200 OK[\r][\n]"  
    2016-07-31 00:28:09,617 DEBUG [httpclient.wire.header] - << "HTTP/1.1 200 OK[\r][\n]"  
    2016-07-31 00:28:09,617 DEBUG [httpclient.wire.header] - << "Server: Apache-Coyote/1.1[\r][\n]"  
    2016-07-31 00:28:09,617 DEBUG [httpclient.wire.header] - << "Content-Type: text/html;charset=UTF-8[\r][\n]"  
    2016-07-31 00:28:09,618 DEBUG [httpclient.wire.header] - << "Content-Length: 67[\r][\n]"  
    2016-07-31 00:28:09,618 DEBUG [httpclient.wire.header] - << "Date: Sat, 30 Jul 2016 16:28:09 GMT[\r][\n]"  
    2016-07-31 00:28:09,618 DEBUG [httpclient.wire.header] - << "[\r][\n]"  
    2016-07-31 00:28:09,618 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Buffering response body  
    2016-07-31 00:28:09,619 DEBUG [httpclient.wire.content] - << "{"id":100,"userName":"admin[0xe7][0xae][0xa1][0xe7][0x90][0x86][0xe5][0x91][0x98]","password":"123456","age":25}"  
    2016-07-31 00:28:09,619 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Resorting to protocol version default close connection policy  
    2016-07-31 00:28:09,619 DEBUG [org.apache.commons.httpclient.HttpMethodBase] - Should NOT close connection, using HTTP/1.1  
    2016-07-31 00:28:09,620 DEBUG [org.apache.commons.httpclient.HttpConnection] - Releasing connection back to connection manager.  
    {"id":100,"userName":"admin管理员","password":"123456","age":25}  
    testHttpURlConnection  
    2016-07-31 00:28:09,629 DEBUG [org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession  
    2016-07-31 00:28:09,630 DEBUG [org.mybatis.spring.SqlSessionUtils] - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4636317d] was not registered for synchronization because synchronization is not active  
    2016-07-31 00:28:09,631 DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@155b4677] will not be managed by Spring  
    2016-07-31 00:28:09,631 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - ==>  Preparing: select id, user_name, password, age from user where id = ?   
    2016-07-31 00:28:09,632 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - ==> Parameters: 100(Integer)  
    2016-07-31 00:28:09,637 DEBUG [com.cn.eagle.dao.UserMapper.selectByPrimaryKey] - <==      Total: 1  
    2016-07-31 00:28:09,640 DEBUG [org.mybatis.spring.SqlSessionUtils] - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4636317d]  
    {"id":100,"userName":"admin管理员","password":"123456","age":25}  
    39 25  


第二次执行后:

  testHttpClient()用时:39

  testHttpURlConnection()用时:25

总的来说,在大压力或者连续不断发请求的情况下,HttpClient不会比HttpURLConnection慢多少,因为保持了底层的Socket连接,不用每次都重新连接。

博文转自:http://blog.csdn.net/aqsunkai/article/details/52076137

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐