您当前的位置: 首页 >  http

梁云亮

暂无认证

  • 2浏览

    0关注

    1211博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

使用HttpClient访问WEB资源

梁云亮 发布时间:2019-10-21 23:10:31 ,浏览量:2

虽然在 JDK 的 java.net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 本身提供的功能还不够丰富和灵活。HttpClient 是Apache Jakarta Common下的子项目,它是一个实现了 HTTP 协议的客户端编程工具。HttpClient 已经应用在很多的企业项目中,比如Apache Jakarta上很著名的开源项目Cactus和HTMLUnit 都使用到了HttpClient技术。      简单地说,HttpClient就是一个增强版的HttpURLConnection。HttpURLConnection可以做的事情HttpClient都可以做。HttpClient只是关注于如何发送请求、接收响应、以及管理HTTP连接。以下列出的是HttpClient提供的主要的功能:

  • 实现了HTTP请求的所有的方法(GET、POST、PUT、HEAD 等)。
  • 支持自动转向。
  • 支持 HTTPS 协议。
  • 支持代理服务器等。

HttpClient是一个客户端的Http通信实现库,可以用于发送HTTP请求,接收HTTP响应。但它不会缓存服务器的响应,不能执行HTML页面中嵌入的JavaScript代码,也不会对页面内容进行任何解析、处理。 HttpClient会自动维护与服务器之间的Session状态。比如,只要程序第一次使用HttpClient登录系统后,接下来就可以使用同一个HttpClient访问被保护的资源了。这和浏览器自动维护客户端与服务器之间的Session的功能类似。

使用 HttpClient 的基本步骤如下:

  1. 创建 HttpClient 的对象。
  2. 如果需要发送GET请求,则创建HttpGet对象;如果需要发送POST请求,则创建HttpPost对象。
  3. 如果需要发送请求参数,可以调用HttpGet、HttpPost都有的setParams()方法来添加请求参数。对于HttpPost对象而言,也可以调用setEntity()方法来设置请求参数。
  4. 调用HttpClient对象的execute()方法发送请求,该方法执行后会返回一个HttpResponse对象。
  5. 调用HttpResponse的getAllHeaders()、getHeaders()等方法可获得服务器的响应头;调用HttpResponse的getEntitiy()方法可以获得一个HttpEntity对象,该对象包装了服务器的响应内容,程序可以通过该对象获取服务器的响应内容。
  6. 释放连接,无论执行方法是否成功,都必须释放连接
示例:演示如何使用HttpClient访问被保护的资源。

第一步:创建一个JSP项目zghc,在它根目录下分别提供两个名为login.jsp和secret.jsp文件,其中login.jsp文件的源代码为:



secret.jsp的源代码为:



在上面的secret.jsp中我们先判断用户是否登录成功,如果没有登录成功是不能访问受保护的资源的。 第二步:创建一个Android项目,然后按照下图7.8所示设计主布局文件,其中上面表示用户名与密码的EditText的id值分别为name和pass,中间两个Button的onClick属性的值分别为directAccess和loginAccess,最下面的TextView的id为textView。 在这里插入图片描述 第三步:提供一个用来借助类HttpClient实现GET请求和POST请求的工具类,具体代码及说明如下:

public class HttpClientUtil {
	// 创建DefaultHttpClient对象
	public static HttpClient httpClient = new DefaultHttpClient();
	public static final String BASE_URL = "http://10.0.2.2:8080/zghc/";
	// 发送GET请求,返回服务器响应的字符串
	public static String getRequest(String url) throws Exception {
		HttpGet get = new HttpGet(url);// 创建一个HttpGet对象
		HttpResponse httpResponse = httpClient.execute(get);// 发送GET请求,返回响应
		// 如果服务器成功地返回响应
		if (httpResponse.getStatusLine().getStatusCode() == 200) {
			// 获取服务器响应字符串
			String result = EntityUtils.toString(httpResponse.getEntity());
			return result;
		}
		return null;
	}
	// 发送POST请求,返回服务器响应的字符串,其中params表示请求参数
	public static String postRequest(String url, Map rawParams)
			throws Exception {
		HttpPost post = new HttpPost(url); // 创建HttpPost对象
		// 对传递的参数进行封装
		List params = new ArrayList();
		for (String key : rawParams.keySet())// 封装请求参数
			params.add(new BasicNameValuePair(key, rawParams.get(key)));
// 设置请求参数及URL编码
		post.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); 
		HttpResponse httpResponse = httpClient.execute(post); // 发送POST请求
		// 如果服务器成功地返回响应
		if (httpResponse.getStatusLine().getStatusCode() == 200) {
			// 获取服务器响应字符串
			String result = EntityUtils.toString(httpResponse.getEntity());
			return result;
		}
		return null;
	}
}

当使用HttpClient执行HTTP POST调用时,通常将编码到URL中的键值对参数作为HTTP 请求的一部分传递。要通过HttpClient实现此功能,必须创建一个包含NameValuePair对象实例的列表,然后使用UrlEncodedFormEntity对象包装该列表。NameValuePair包装了一个键值组合,UrlEncodedFormEntity类知道如何编写适合HTTP调用(通常为POST调用)的NameValuePair对象列表。创建UrlEncodedFormEntity之后,可以将HttpPost的实体类型设置为UrlEncodedFormEntity,然后执行该请求了。

提示: 使用HttpClient不仅能够以字符串形式获取返回服务器端的内容,还可以以InputStream流的形式返回服务器端处理的结果,这是因为可以通过HttpEntity类的getContent ()方法得到一个InputStream,所以使用HttpClient类可以得到服务器端任何类型的数据。我们在浏览器客户端所执行的大多数操作HttpClient都能够模拟,例如:提交表单、查询数据、上传下载文档、页面跳转、Session存储等。 注意: HttpEntity中的内容只能读取一次,如果多次调用它的getContent()方法则会报如下异常:java.lang.IllegalStateException: Content has been consumed 提示: 在GET请求中的Uri也可以带有参数,不过出于安全考虑,在需要传递参数时一般情况下使用POST方式。带参数的URI有以下几种实现方法:

  • HttpGet get = new HttpGet(“http:// 10.0.2.2:8080/zghc/login.jsp?name=wx&pass=wx”);
  • 通过HttpClient程序包提供的URIUtils工具类:
URI uri = URIUtils.createURI("http", "10.0.2.2 ", 8080, "/zghc/login.jsp ", 
    "name=wx&pass=wx ", null);  
HttpUriRequest request = new HttpGet(uri);  
System.out.println(request.getURI());  

如果参数中含有中文,需将参数进行URLEncoding处理,如:

String param = "wx=" + URLEncoder.encode("张三", "UTF-8") + "&wx=wx";   
URI uri = URIUtils.createURI("http", "10.0.2.2 ", 8080, "/zghc/login.jsp ", param, null);    
System.out.println(uri);  
  • 对于参数的URLEncoding处理,我们还可以通过HttpClient程序包中的URLEncodedUtils工具类直观的生成URI,如:
List params = new ArrayList();   
params.add(new BasicNameValuePair("name", "张三"));    
params.add(new BasicNameValuePair("pass", "wx"));    
String param = URLEncodedUtils.format(params, "UTF-8");    
URI uri = URIUtils.createURI("http", "10.0.2.2 ", 8080, "/zghc/login.jsp ", param, null);
System.out.println(uri);  

在POST请求中,我们可以通过UrlEncodedFormEntity类创建的对象模拟传统的HTML表单传送POST请求中的参数。比如:

  
   	用户名:   
    密码:  
      

我们可以用下面的代码实现:

List formParams = new ArrayList();   
formParams.add(new BasicNameValuePair("name", "wx"));    
formParams.add(new BasicNameValuePair("pass", "wx"));           
HttpEntity entity = new UrlEncodedFormEntity(formParams, "UTF-8");    
HttpPost post = new HttpPost("http://10.0.2.2:8080/ zghc/login.jsp");    
post.setEntity(entity);  

当然,如果想查看HTTP数据格式,可以通过HttpEntity对象的各种方法取得。如:

List formParams = new ArrayList();   
formParams.add(new BasicNameValuePair("param1", "中国"));    
formParams.add(new BasicNameValuePair("param2", "value2"));           
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, "UTF-8");    
System.out.println(entity.getContentType());   
System.out.println(entity.getContentLength());   
System.out.println(EntityUtils.toString(entity));

对应的输出结果为:

Content-Type: application/x-www-form-urlencoded
15
name=wx&pass=pass

第四步:编写Activity类,代码如下:

public class MainActivity extends Activity {
	private TextView textView  =null;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		textView = (TextView) findViewById(R.id.textView);
	}
	public void loginAccess(View view) {	//先登录后访问受限制的资源
		String url = HttpClientUtil.BASE_URL + "login.jsp";
		EditText nameET = (EditText) findViewById(R.id.name);
		EditText passET = (EditText) findViewById(R.id.pass);
		String name = nameET.getText().toString().trim();
		String pass = passET.getText().toString().trim();
		Map map = new HashMap();
		map.put("name", name);
		map.put("pass", pass);
		try {
			String temp = HttpClientUtil.postRequest(url, map);
			if ("SUCCESS".equals(temp.trim())) {
				directAccess(view);
			} else {
				textView.setText("用户名或密码错误,请重新登录");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public void directAccess(View view){ //未登录直接访问受限制的资源
		String url = HttpClientUtil.BASE_URL + "secret.jsp";
		String res = null;
		try {
			res = HttpClientUtil.getRequest(url);
		} catch (Exception e) {
			e.printStackTrace();
		}
		textView.setText(res);
	}
}

第五步:在功能清单文件中添加网络访问权限:


运行程序:先将JSP项目部署到tomcat中,然后运行Android程序,结果如下图所示。 在这里插入图片描述 未登录直接访问 在这里插入图片描述 登录失败 在这里插入图片描述 成功登录后访问

使用HttpClient中文乱码问题:

  • 方案一:在用EntityUtils.toString()取得返回字符串的时候,默认编码为ISO-8859-1,需要指定toString的第二个参数为服务器端的编码格式。比如: 服务器端:response.setCharacterEncoding(“UTF-8”); 客户端:String result = EntityUtils.toString(httpResponse.getEntity(),“UTF-8”);
  • 方案二: String message = “我的测试消息”; HttpServer发送时:message=new String(message.getBytes(“UTF-8”),“ISO-8859-1”); Android接收时: message=new String(message.getBytes(“ISO-8859-1”),“UTF-8”);
示例:演示如何只向服务器端传送手机号码,就从服务器端获取对应的归属地。

第一步:首先在功能清单文件中添加网络访问权限,然后在主布局文件中提供一个让用户输入待查询的电话号码的id值为phoneNum的EditText、一个用来显示号码地址的id为result的TextView、一个onClick属性值为fun的Button控件。 第二步:修改MainActivity类的代码如下所示:

public class MainActivity extends Activity {
	private TextView result;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		result = (TextView) findViewById(R.id.result);
	}
	public void fun(View view) {
		EditText phoneNumET = (EditText) findViewById(R.id.phoneNum);
		String phoneNum = phoneNumET.getText().toString().trim(); // 手机号码
		// 简单判断用户输入的手机号码是否合法
		if ("".equals(phoneNum) || phoneNum.length()             
关注
打赏
1665409997
查看更多评论
0.0436s