`

Java网络技术整理(一)

阅读更多
做Java做了很多年,却总是把一些东西遗忘,过后再着急的找寻。最近,需要通过Java代码模拟一个表单提交,却怎么也想不起来如何封装数据了。在以前的代码里翻腾了好久,终于实验成功。索性,做一个了断! 放到博客中来!
本篇主要描述Java网络参数传递,主要分为get和post两种方式。
说句玩笑话,真有干了几年Java的朋友不知道get和post的差别,我就在这里唠叨几句。
1.Get方式
这种方式是最简单的参数传递方式。例如:http://www.zlex.org/get.do?a=3&b=5&c=7
这个url中,a、b和c是url参数,具体的说是参数名,与之用“=”隔开的是对应的参数值。也就是说参数a的值为3、参数b的值为5、参数c的值为7。get.do是请求地址,紧跟这个地址的参数a需要用“?”作为分隔符,其余参数用“&”做分隔符。
这种get请求发起后,服务器端可以通过request.getParameter()方法来获得参数值。如要获得参数a的值可以通过request.getParameter("a");
2.Post方式
相比get方式,post方式更为隐蔽。例如:http://www.zlex.org/post.do
在这个url中,你看不到任何参数,真正的参数隐藏在Http请求的数据体中。如果了解网络监听的话,就会对这一点深有体会。
我们举一个简单的例子:通过表单做登录操作。
我们简化一个登录表单:
<form action="login.do" method="post">
<ul>
	<li><label for="username">用户名</label><input id="username"
		name="username" type="text" /></li>
	<li><label for="password">密码</label><input id="password"
		type="password" /></li>
	<li><label><input type="submit" value="登录" /> <input
		type="reset" value="重置" /></label></li>
</ul>
</form>

表单中有2个字段,用户名(username)和密码(password)
注意form标签中的method参数值是post!
即便是表单,在服务器端仍然可以通过request.getParameter()方法来获得参数值。
Post方式,其实是将表单字段和经过编码的字段值经过组合以数据体的方式做了参数传递。
经过一番阐述,相信大家对两种网络参数传递方式都有所了解了。
Get方式比较简单,通过构建一个简单HttpURLConnection就可以获得,我们暂且不说。
我们主要来描述一下如何通过java代码构建一个表单提交。
仔细研究表单提交时所对应的http数据体,发现其表单字段是以如下方式构建的:
arg0=urlencode(value0)&arg1=urlencode(value1)

当然,尤其要注意字段名,参数名只不能使用中文这类字符。
作为表单,Content-Type也会有所不同,其值为application/x-www-form-urlencoded以下做一个代码展示,以后再需要我就不用翻“旧账”了
我常用的网络工具,其功能远不止模拟一个post请求
/**
 * 2008-12-26
 */
package org.zlex.commons.net;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Properties;

/**
 * 网络工具
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class NetUtils {
	public static final String CHARACTER_ENCODING = "UTF-8";
	public static final String PATH_SIGN = "/";
	public static final String METHOD_POST = "POST";
	public static final String METHOD_GET = "GET";
	public static final String CONTENT_TYPE = "Content-Type";

	/**
	 * 以POST方式向指定地址发送数据包请求,并取得返回的数据包
	 * 
	 * @param urlString
	 * @param requestData
	 * @return 返回数据包
	 * @throws Exception
	 */
	public static byte[] requestPost(String urlString, byte[] requestData)
			throws Exception {
		Properties requestProperties = new Properties();
		requestProperties.setProperty(CONTENT_TYPE,
				"application/octet-stream; charset=utf-8");

		return requestPost(urlString, requestData, requestProperties);
	}

	/**
	 * 以POST方式向指定地址发送数据包请求,并取得返回的数据包
	 * 
	 * @param urlString
	 * @param requestData
	 * @param requestProperties
	 * @return 返回数据包
	 * @throws Exception
	 */
	public static byte[] requestPost(String urlString, byte[] requestData,
			Properties requestProperties) throws Exception {
		byte[] responseData = null;

		HttpURLConnection con = null;

		try {
			URL url = new URL(urlString);
			con = (HttpURLConnection) url.openConnection();

			if ((requestProperties != null) && (requestProperties.size() > 0)) {
				for (Map.Entry<Object, Object> entry : requestProperties
						.entrySet()) {
					String key = String.valueOf(entry.getKey());
					String value = String.valueOf(entry.getValue());
					con.setRequestProperty(key, value);
				}
			}

			con.setRequestMethod(METHOD_POST); // 置为POST方法

			con.setDoInput(true); // 开启输入流
			con.setDoOutput(true); // 开启输出流

			// 如果请求数据不为空,输出该数据。
			if (requestData != null) {
				DataOutputStream dos = new DataOutputStream(con
						.getOutputStream());
				dos.write(requestData);
				dos.flush();
				dos.close();
			}

			int length = con.getContentLength();
			// 如果回复消息长度不为-1,读取该消息。
			if (length != -1) {
				DataInputStream dis = new DataInputStream(con.getInputStream());
				responseData = new byte[length];
				dis.readFully(responseData);
				dis.close();
			}
		} catch (Exception e) {
			throw e;
		} finally {
			if (con != null) {
				con.disconnect();
				con = null;
			}
		}

		return responseData;
	}

	/**
	 * 以POST方式向指定地址提交表单<br>
	 * arg0=urlencode(value0)&arg1=urlencode(value1)
	 * 
	 * @param urlString
	 * @param formProperties
	 * @return 返回数据包
	 * @throws Exception
	 */
	public static byte[] requestPostForm(String urlString,
			Properties formProperties) throws Exception {
		Properties requestProperties = new Properties();
		
		requestProperties.setProperty(CONTENT_TYPE,
				"application/x-www-form-urlencoded");
		
		return requestPostForm(urlString, formProperties, requestProperties);
	}

	/**
	 * 以POST方式向指定地址提交表单<br>
	 * arg0=urlencode(value0)&arg1=urlencode(value1)
	 * 
	 * @param urlString
	 * @param formProperties
	 * @param requestProperties
	 * @return 返回数据包
	 * @throws Exception
	 */
	public static byte[] requestPostForm(String urlString,
			Properties formProperties, Properties requestProperties)
			throws Exception {
		StringBuilder sb = new StringBuilder();

		if ((formProperties != null) && (formProperties.size() > 0)) {
			for (Map.Entry<Object, Object> entry : formProperties.entrySet()) {
				String key = String.valueOf(entry.getKey());
				String value = String.valueOf(entry.getValue());
				sb.append(key);
				sb.append("=");
				sb.append(encode(value));
				sb.append("&");
			}
		}

		String str = sb.toString();
		str = str.substring(0, (str.length() - 1)); // 截掉末尾字符&

		return requestPost(urlString, str.getBytes(CHARACTER_ENCODING),
				requestProperties);

	}

	/**
	 * url解码
	 * 
	 * @param str
	 * @return 解码后的字符串,当异常时返回原始字符串。
	 */
	public static String decode(String url) {
		try {
			return URLDecoder.decode(url, CHARACTER_ENCODING);
		} catch (UnsupportedEncodingException ex) {
			return url;
		}
	}

	/**
	 * url编码
	 * 
	 * @param str
	 * @return 编码后的字符串,当异常时返回原始字符串。
	 */
	public static String encode(String url) {
		try {
			return URLEncoder.encode(url, CHARACTER_ENCODING);
		} catch (UnsupportedEncodingException ex) {
			return url;
		}
	}
}

注意上述requestPostForm()方法,是用来提交表单的。
测试用例
/**
 * 2009-8-21
 */
package org.zlex.commons.net;

import static org.junit.Assert.*;

import java.util.Properties;

import org.junit.Test;

/**
 * 网络工具测试
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class NetUtilsTest {

	/**
	 * Test method for
	 * {@link org.zlex.commons.net.NetUtils#requestPost(java.lang.String, byte[])}
	 * .
	 */
	@Test
	public final void testRequestPostStringByteArray() throws Exception {
		Properties requestProperties = new Properties();

		// 模拟浏览器信息
		requestProperties
				.put(
						"User-Agent",
						"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; TencentTraveler ; .NET CLR 1.1.4322)");

		byte[] b = NetUtils.requestPost("http://localhost:8080/zlex/post.do",
				"XML".getBytes());
		System.err.println(new String(b, "utf-8"));
	}

	/**
	 * Test method for
	 * {@link org.zlex.commons.net.NetUtils#requestPostForm(java.lang.String, java.util.Properties)}
	 * .
	 */
	@Test
	public final void testRequestPostForm() throws Exception {
		Properties formProperties = new Properties();

		formProperties.put("j_username", "Admin");
		formProperties.put("j_password", "manage");

		byte[] b = NetUtils.requestPostForm(
				"http://localhost:8080/zlex/j_spring_security_check",
				formProperties);
		System.err.println(new String(b, "utf-8"));
	}
}


测试用例中的第二个方法是我用来测试SpringSecurity的登录操作,结果是可行的!
16
1
分享到:
评论
14 楼 wupuyuan 2011-09-06  
这里可以试试httpClient这个jar包看看,里面基本都有实现
13 楼 pufan 2009-09-02  
还不够底层,用tcp直接写http协议应该是java能做到的最底层。
12 楼 snowolf 2009-09-02  
minma_2009 写道
这个主要有什么作用啊?会用在什么地方?
我是初学者,请指教啊?

用Java代码模拟Post表单提交!
11 楼 minma_2009 2009-09-02  
这个主要有什么作用啊?会用在什么地方?
我是初学者,请指教啊?
10 楼 ywlqi 2009-09-02  
收藏,以后慢慢看
9 楼 snowolf 2009-09-01  
flynofry 写道
如果是在项目中开发,用apache的httpclient好些。

赞同!本文旨在说明底层实现!如果是J2ME模拟一个Post表单提交,就需要上述方式了!
8 楼 flynofry 2009-09-01  
如果是在项目中开发,用apache的httpclient好些。
7 楼 snowolf 2009-08-31  
wxwswjws 写道
果然我看得有点懵..

对requestPost()方法加了一些注释 ,这样应该能看懂些了吧!
6 楼 wxwswjws 2009-08-31  
果然我看得有点懵..
5 楼 lzyboy 2009-08-27  
不错  收藏了
4 楼 tk_zhang 2009-08-27  
嗯,楼主说的是啊~~
3 楼 metadmin 2009-08-26  
呵呵,楼主的文章挺用心的。

支持楼主继续,说不准先在社区火起来,然后可以直接出书了。提前恭喜了
2 楼 zhuxinyu 2009-08-26  
是得把基础再回来好好看看!^_^
1 楼 javaz 2009-08-26  
先顶一个!

相关推荐

    JAVA后端计算机网络面试题(整理)

    作者最近也是面临离职,重找下家的情况,之前大学学过的《计算机网络》,自己看过《TCP/IP》一些的书,发现作为一个java工程师,对于网络的概念划分不清。因为互联网本身有一定的模型分层,所以本文,根据模型分层,...

    Java 技术文档整理汇总大全

    9.网络10.日志 11.Zookeeper 12.Kafka 13.RabbitMQ 14.Hbase 15.MongoDB 16.Cassandra 17.设计模式 18.负载均衡 19.数据库 20.一致性算法 21.JAVA算法 22.数据结构 23.加密算法 24.分布式缓存 25.Hadoop 26.Spark 27...

    JAVA核心知识点整理.pdf

    本资源为整理网络上Java工作中常用的知识点,主要针对工作问题和面试问题,对于各个阶段的Java程序员有很强的实用性

    【白雪红叶】JAVA学习技术栈梳理思维导图.xmind

    关于java程序员发展需要学习的路线整理集合 技术 应用技术 计算机基础知识 cpu mem disk net 线程,进程 第三方库 poi Jsoup zxing Gson 数据结构 树 栈 链表 队列 图 操作系统 linux 代码控制...

    java互联网面试题整理

    整理互联网常见面试题,为春招、校招和社招做准备。如若不能下载,关注公众号“每日技术分享”,可免费下载资源。

    java服务端面试题整理.zip

    Java核心技术:如多线程、网络编程、序列化等都有详细的解释和示例。 常用框架:如Spring、MyBatis等框架的使用方法和内部原理都有涉及。 数据库相关:包括关系型数据库和非关系型数据库的使用,以及JDBC、MyBatis等...

    Java 笔试、面试 知识整理.zip

    Java核心技术:如多线程、网络编程、序列化等都有详细的解释和示例。 常用框架:如Spring、MyBatis等框架的使用方法和内部原理都有涉及。 数据库相关:包括关系型数据库和非关系型数据库的使用,以及JDBC、MyBatis等...

    搜索链接Java网络爬虫(蜘蛛)源码-zhizhu.zip

    Java网络爬虫(蜘蛛)源码_zhizhu.zip是一个基于Java语言开发的网络爬虫项目,适用于毕业设计、课程设计等场景。该项目主要功能是通过网络爬虫技术,自动抓取互联网上的信息,并将这些信息进行整理和存储。这个项目的...

    JAVA核心面试知识整理.pdf

    文档内容包括JVM,JAVA基础,数据库,计算机网络,微服务等知识点。

    基于Java的双代号网络图自动绘制系统研究与实现.zip

    (3)根据对需求的分类、整理,结合当前可利用的技术手段,设计系统原型; (4)实现系统。使用Java、stripes,实现编号、布点等核心算法与服务器端MVC结构、后台与前台的数据交互接口;通过HTML、CSS、JavaScript、Ajax...

    Java开发面试题整理含答案(计网、Java、操作系统、数据库、框架).zip

    Java核心技术:如多线程、网络编程、序列化等都有详细的解释和示例。 常用框架:如Spring、MyBatis等框架的使用方法和内部原理都有涉及。 数据库相关:包括关系型数据库和非关系型数据库的使用,以及JDBC、MyBatis等...

    Java开发者或者大数据开发者面试知识点整理.zip

    Java核心技术:如多线程、网络编程、序列化等都有详细的解释和示例。 常用框架:如Spring、MyBatis等框架的使用方法和内部原理都有涉及。 数据库相关:包括关系型数据库和非关系型数据库的使用,以及JDBC、MyBatis等...

    java各知识点详细总结(毕向东笔记整理)

    java各知识点详细总结(毕向东笔记整理)。第一章:编程基础 3-11 第二章:数组 11 -31 第三章:面向对象程序开发 31 -74 第四章:异常机制 74 -89 第五章:多线程技术 89 -122122122 第六章:常用类 API 122API 122 ...

    JAVA 五年的工作经验和学习笔记

    这里需要说明的时,该文档是本人5年工作经验的积累,文档中大部分知识点来源于实际工作中的总结,(除了JAR等资源文件外)其代码都是可运行的,还有一部分知识来源于网络或者其他书籍,这里做一些收集,使该体系更加...

    【Java面试+Java学习指南】 一份涵盖大部分Java程序员所需要掌握的核心知识。.zip

    Java核心技术:如多线程、网络编程、序列化等都有详细的解释和示例。 常用框架:如Spring、MyBatis等框架的使用方法和内部原理都有涉及。 数据库相关:包括关系型数据库和非关系型数据库的使用,以及JDBC、MyBatis等...

    JAVA核心面试知识整理

    9. 网络 10. 日志 11. ZOOKEEPER 12. KAFKA 13. RABBITMQ 14. HBASE 15. MONGODB 16. CASSANDRA 17. 设计模式 18. 负载均衡 19. 数据库 20. 一致性算法 21. JAVA 算法 22. 数据结构. 23. 加密算法. 24. 分布式缓存 ...

    基于java编程的毕业论文范文5篇

    Java 语言是编程语言史上的一个里程碑,在此基础上形成的 Java Applet技术是综合了计算机图形学、多媒体技术、网络技术的新技术,近年来在很多领域得到了快速的发展和应用。 本文是为大家整理的java的毕业论文范文,...

    【转】技术面试必备基础知识、Leetcode 题解、后端面试、Java 面试、春招、秋招、操作系统、计算机网络、系统设计.zip

    Java核心技术:如多线程、网络编程、序列化等都有详细的解释和示例。 常用框架:如Spring、MyBatis等框架的使用方法和内部原理都有涉及。 数据库相关:包括关系型数据库和非关系型数据库的使用,以及JDBC、MyBatis等...

    「Java面试核心」- 计算机网络知识合集整理

    包括Java基础、Java并发、JVM、MySQL、Redis、Spring、MyBatis、Kafka、计算机操作系统、计算机网络、系统设计、多个、Java项目实战等

Global site tag (gtag.js) - Google Analytics