HttpClient模拟Post实现登录辽大教务处

HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议,JAVA可以使用HttpClient的Jar包实现模拟登陆。今天尝试登陆一下辽宁大学的选课系统。

这里写图片描述

通过页面分析得知登陆采用Post方式,表单发送到http://jwgl.lnu.edu.cn/pls/wwwbks/bks_login2.login
参数名分别是stuidpwd
下面开始编写工具类

一、实现思路

创建HttpClient默认实例

CloseableHttpClient httpClient = HttpClients.createDefault();

创建HttpPost实例

HttpPost httpPost = new HttpPost(URL);

如果是Get方法则创建HttpGet实例,二者构造函数参数都可以为目标地址。

创建HttpEntity实例:

StringEntity stringEntity = new StringEntity(param, "UTF-8");
stringEntity.setContentType("application/x-www-form-urlencoded");

Http消息(请求或者响应)会携有Http实体,Http实体可以解析为文本形式,也可以将文本转换为Http实体,无论解析还是转换都要约定字符编码。

Post请求的参数也可以被写入Http实体中,其格式为:

key1=value1&key2=value2

ContentType内容类型,用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件,通常Post表单内容类型默认为application/x-www-form-urlencoded

更多内容类型参照:

HTTP Content-type 对照表
http://tool.oschina.net/commons

创建RequstConfig实例:

RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(15000)
                    .setConnectTimeout(15000)
                    .setConnectionRequestTimeout(15000)
                    .build();

通常利用requestConfig设置超时时间。

将配置好的HttpEntity与RequestConfig实例设置到HttpPost

httpPost.setEntity(stringEntity);
httpPost.setConfig(requestConfig);

用HttpClient实例执行HttpPost,返回Response。

CloseableHttpResponse response = httpClient.execute(httpPost);

httpClient.execute()方法也适用于HttpGet,会返回一个CloseableHttpResponse对象,里面封装有HttpEntity

从Response获取Entity,得到访问信息

我们可以通过response实例中的getEntity()方法获得httpEntity

HttpEntity httpEntity = response.getEntity();

如果想得到网页源文件,则利用EntityUtils.toString()将实体解析成字符串。

String responseContent = EntityUtils.toString(httpEntity , "UTF-8");

关闭资源

response.close();
httpClient.close();

完整源码

package test;

import java.io.IOException;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.util.EntityUtils;

public class FunctionClass {
    /**
     * sendPost 发送post请求
     * @param url
     * @param param
     * @return
     * @throws IOException
     */
    public String sendPost(String url, String param) throws IOException {
        String result = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;

        try {
            HttpPost hp = new HttpPost(url);

            //配置ResquestConfig
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(15000)
                    .setConnectTimeout(15000)
                    .setConnectionRequestTimeout(15000)
                    .build();

            //配置StringEntity
            StringEntity stringEntity = new StringEntity(param, "UTF-8");
            stringEntity.setContentType("application/x-www-form-urlencoded");

            //将Entity和Config设置到HttpPost
            hp.setEntity(stringEntity);
            hp.setConfig(requestConfig);

            //获取页面
            response = httpClient.execute(hp);
            result = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();// TODO: handle exception
        }finally{
            httpClient.close();
            response.close();
        }
        return result;
    }
}

二、测试一下

编写测试类

package test;

import java.io.IOException;

public class TestClass {

    public static void main(String[] args) {
        //http://jwgl.lnu.edu.cn/pls/wwwbks/bks_login2.login?stuid=161407212&pwd=058512
        FunctionClass fc = new FunctionClass();
        try {
            String result = fc.sendPost("http://jwgl.lnu.edu.cn/pls/wwwbks/bks_login2.login", "stuid=XXXXXX&pwd=YYYYY");
            System.out.println("返回的结果是:");
            System.out.println(result);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

运行调试

运行发现出现了问题

这里写图片描述

并没有返回正确的页面信息,而仅仅返回一个换行符,让我们来通过response的getStatusLine()方法看一下问题出在哪里。

System.out.println(response.getStatusLine());

这里写图片描述

原来这里出现了302 Found错误。

三、302 Found

关于302 Found:

302 Found 是HTTP协议中的一个状态码(Status Code),可以简单的理解为该资源原本确实存在,但已经被临时改变了位置;或者换个说法,就是临时的存在于某个临时URL下。

也就是说Servlet可能发生了重定向,通常Get或者Head会自动转向重定向的网页,但是Post和Push方法是被禁止的。

解决方案

其中一个办法是采用Get方法代替Post,但是Get和Post本身就是两个东西,不是所有网页都可以这样。
第二个方法是改变HttpClient的重定向策略

CloseableHttpClient httpClient = HttpClients.createDefault();

改为

CloseableHttpClient httpClient = HttpClients.custom()
                .setRedirectStrategy(new LaxRedirectStrategy())
                .build();

LaxRedirectStrategy可实现HEAD, GET, POST, 和DELETE方法自动重定向,可以借此解除HTTP规定的对POST方法自动重定向的限制

第二次运行调试

这里写图片描述

已经可以登录成功,并且争取获取页面源文件了,初步战略目标达成。

三、总结与反思

HttpClient完善且强大,模拟登录还不算彻底成功,需要学习的还有很多,同时编写代码还不够规范,没有养成良好的习惯。希望可以通过写博文彻底治愈懒癌,使自己每天进步一点点!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值