HttpClient服务器模拟浏览器发送请求

前言:
学习第三方登陆的时候,发现开头的知识就用到了HttpClient,也就是服务器模拟浏览器发起的请求,而我不会,于是就先花时间学习了下。
内容包括:GET、POST请求,以及各种零散的知识点。

maven 依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>login</groupId>
    <artifactId>wechat</artifactId>
    <packaging>war</packaging>
    <version>1.0</version>
    <name>wechat Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <!-- maven默认是1.5版本,不写这段话会有警告,资源已过时 -->
    <profiles>
        <profile>
            <id>jdk-1.8</id>
            <activation>
                <activeByDefault>true</activeByDefault>
                <jdk>1.8</jdk>
            </activation>
            <properties>
                <maven.compiler.source>1.8</maven.compiler.source>
                <maven.compiler.target>1.8</maven.compiler.target>
                <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
            </properties>
        </profile>
    </profiles>
    <dependencies>
        <!--tomcat中有servlet,因此scope应该声明为provided -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <scope>provided</scope>
            <version>3.0-alpha-1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib -->
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.5.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <!-- 封装了对http传输中文件相关操作 -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.json/json -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20160810</version>
        </dependency>

    </dependencies>
    <build>
        <finalName>wechat</finalName>
    </build>
</project>

预备知识

  • HttpClients

    Factory methods for CloseableHttpClient instances.

    HttpClients API

  • HttpEntity

    public interface HttpEntity
    An entity that can be sent or received with an HTTP message. Entities can be found in some requests and in responses, where they are optional.
    There are three distinct types of entities in HttpCore, depending on where their content originates:

    HttpEntity API

 public class Test{
 private RequestConfig requestConfig = RequestConfig.custom()
            .setSocketTimeout(15000)
            .setConnectTimeout(15000)
            .setConnectionRequestTimeout(15000)
            .build();

public void testHttpClientGet(String httpUrl) {
        HttpGet httpGet = new HttpGet(httpUrl);
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        HttpEntity httpEntity = null;
        String responseContent = null;
        try {
            //创建默认的httpClient实例
            httpClient = HttpClients.createDefault();
            httpGet.setConfig(requestConfig);
            httpResponse = httpClient.execute(httpGet);
            httpEntity = httpResponse.getEntity();
            responseContent = EntityUtils.toString(httpEntity, "utf-8");
            /*
            another encode method could refers to this blog
            "http://blog.sina.com.cn/s/blog_6d002146010130wv.html"
             */
            System.out.println(responseContent);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (httpResponse != null) {
                    httpResponse.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

/**
     * POST请求1
     * @param httpUrl eg:http://localhost:8080/testPost?username=cwy&password=123
     */
    public void sendHttpPost(String httpUrl) {
        HttpPost httpPost = new HttpPost(httpUrl);
        testHttpClietPost(httpPost);
    }

    /**
     * POST请求2
     * @param httpUrl 请求地址
     * @param params  key1=value1&key2=value2
     */
    public void sendHttpPost(String httpUrl, String params) {
        HttpPost httpPost = new HttpPost(httpUrl);
        try {

            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            /*
            *http://blog.csdn.net/blueheart20/article/details/45174399
             */
            stringEntity.setContentType("application/x-www-form-urlencoded");
            /*
            StringEntity implements httpEntity extends AbstractHttpEntity
            AbstractHttpEntity implements httpEntity
            httpEntity has get-Content/ContentEncoding/ContentLength/ContentType 
            method
            but only AbstractHttpEntity has set-xx method
            more information refers to  API     
            "http://hc.apache.org/httpcomponents-core
            ga/httpcore/apidocs/org/apache/http/HttpEntity.html"
             */
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
        testHttpClietPost(httpPost);
    }

     /**
     * 发送POST请求(带文件)
     * @param httpUrl 请求地址
     * @param maps  请求参数
     * @param fileLists 文件列表
     */
    public void sendHttpPost3(String httpUrl, Map<String,String> maps, List<File> fileLists){
        HttpPost httpPost=new HttpPost(httpUrl);
        MultipartEntityBuilder meBuilder=MultipartEntityBuilder.create();
        for(String key:maps.keySet()){
            meBuilder.addPart(key,new StringBody(maps.get(key),ContentType.TEXT_PLAIN));
        }
        for(File file:fileLists){
            FileBody fileBody=new FileBody(file);
            meBuilder.addPart("files",fileBody);
        }
        HttpEntity httpEntity=meBuilder.build();
        httpPost.setEntity(httpEntity);
        testHttpClietPost(httpPost);
    }
/*
//测试
public void testPost3(){
        Map<String,String> maps=new HashMap<>();
        maps.put("username","cwy");
        maps.put("password","123456");
        List<File> files=new ArrayList<>();
        files.add(new File("E:\\前端系列\\作业--完整网页\\images\\11.png"));
        sendHttpPost("http://localhost:8080/testPostFiles",maps,files);
    }
*/
public void testHttpClietPost(HttpPost httpPost) {
        CloseableHttpClient closeableHttpClient = null;
        CloseableHttpResponse closeableHttpResponse = null;
        HttpEntity httpEntity = null;
        String responseContent = null;
        try {
            closeableHttpClient = HttpClients.createDefault();
            httpPost.setConfig(requestConfig);
            closeableHttpResponse = closeableHttpClient.execute(httpPost);
            httpEntity = closeableHttpResponse.getEntity();
            responseContent = EntityUtils.toString(httpEntity, "UTF-8");
            System.out.println("responseContent=" + responseContent);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (closeableHttpResponse != null) {
                    closeableHttpResponse.close();
                }
                if (closeableHttpClient != null) {
                    closeableHttpClient.close();
                }
            } catch (Exception e) {
            }

        }
    }
 }

GET请求以及非文件POST请求servlet

 //非通用,仅为测试
 protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        System.out.println("QueryString"+request.getQueryString());
        System.out.println("CharacterEncoding"+request.getCharacterEncoding());
        System.out.println("ContentType"+request.getContentType());
        Map<String,String> map=new HashMap();
        String username=request.getParameter("username");
        String password=request.getParameter("password");
        map.put("username",username);
        map.put("password",password);
        map.put("requestContentType",request.getContentType());
        System.out.println("map="+map);
        response.setContentType("application/json; charset=utf-8");
        response.setCharacterEncoding("UTF-8");
        String jsonObject=JSONObject.valueToString(map);
        System.out.println("jsonObject="+jsonObject);
        OutputStream out = response.getOutputStream();
        out.write(jsonObject.getBytes("utf-8"));
        out.flush();
    }

文件请求抓包
写了简易的jsp页面对文件上传进行抓包测试

<form action="${pageContext.request.contextPath}/testPostFiles" enctype="multipart/form-data" method="post">
        上传用户: <input type="text" name="username"><br/>
        上传文件1: <input type="file" name="file1"><br/>
        上传文件2:<input type="file" name="file2"><br/>
        <input type="submit" value="submit">
</form>

写了简易的jsp页面对文件上传进行抓包测试

  • 注意,对于form/data这种形式,无法以key-value的形式获取值,只能以流的方式,
    如果选择手动实现,不使用第三方jar包(如我这儿使用的uploadfile),就要以分隔字符、判断、切割等复杂操作来实现流的转换。
    对于Content-Type,这儿有篇文章 点击链接

携带文件POST请求servlet

/*
这只是最简单的实现,还可以优化
1、文件上传能够设置缓冲区 
2、文件名应该有UUID或其他唯一名,避免文件覆盖
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String savePath=getServletContext().getRealPath("/WEB-INF/upload");
        File file=new File(savePath);
        if(!file.exists()&&!file.isDirectory()){
            System.out.println(savePath+"目录不存在,需要创建");
            file.mkdir();
        }
        String message="";
        /*
        使用Apache文件上传组件处理文件上传步骤
        1、创建一个DiskFileItemFactory工厂
        2、创建一个文件上传解析器
        3、判断提交上来的数据是否是上传表单的数据
        4、使用ServletFileUpload解析器解析上传数据,解析结果返回一个List<FileItem>
         */
        try{
            DiskFileItemFactory factory=new DiskFileItemFactory();
            ServletFileUpload upload=new ServletFileUpload(factory);
            //解决上传文件中的中文乱码
            upload.setHeaderEncoding("UTF-8");
            if(!ServletFileUpload.isMultipartContent(request)){
                //按照传统方式获取数据
                return;
            }
            List<FileItem> list=upload.parseRequest(request);
            for(FileItem item:list){
                //如果fileitem中封装的是普通输入项的数据
                if(item.isFormField()){
                    String name=item.getFieldName();
                    String value=item.getString("utf-8");
                    System.out.println("name="+name+" ;value="+value);
                }else{
                    //若封装的是上传文件
                    String filename=item.getName();
                    System.out.println("filename="+filename);
                    if(filename==null||filename.trim().equals("")){
                        continue;
                    }
                    //注意,不同的浏览器提交的文件名是不一样的,有些带路径,有些不带
                    //处理上传文件的路径,统一只保留文件名部分
                    filename=filename.substring(filename.lastIndexOf("\\")+1);
                    InputStream in=item.getInputStream();
                    FileOutputStream out=new FileOutputStream(savePath+"\\"+filename);
                    //创建一个缓冲区
                    byte buffer[]=new byte[1024];
                    //判断输入流中的数据是否已读完的标志
                    int len=0;
                    while((len=in.read(buffer))>0){
                        out.write(buffer,0,len);
                    }
                    in.close();
                    out.close();
                    //删除处理文件上传时生成的临时文件
                    item.delete();
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值