`

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核心技术整理

    Java核心技术是Java编程语言的核心组成部分,它包括了Java的基础语法、面向对象编程概念、类库以及JVM(Java虚拟机)的工作原理等多个方面。这里,我们将深入探讨这些关键知识点。 首先,Java的基础语法是学习Java...

    Java常用代码整理

    在"Java常用代码整理"这个主题中,我们可以探讨多个Java编程中的关键知识点,包括基础语法、面向对象特性、异常处理、集合框架、IO流、多线程、网络编程以及实用工具类等。 1. **基础语法**:Java的基础语法包括...

    Java 网络程序设计

    从提供的文件信息中,我们可以提取和解读出多个与Java网络程序设计相关的知识点。 首先,文档标题“Java 网络程序设计”直接指出了本文档的中心主题。网络程序设计是指在编程中如何实现网络通信的过程,而Java作为...

    java常用技术整理.rar

    以上就是Java常用的一些技术点,如果"java常用技术整理.rar"中包含了这些内容,那么这将是一个非常全面的学习资源,涵盖了从基础到进阶的多个方面。通过学习和掌握这些知识点,开发者能够提升自己的Java编程技能,并...

    Java开发技术大全源码整理

    【Java开发技术大全源码整理】是一份集大成的Java编程学习资源,包含了丰富的Java开发相关的源代码示例和教程。这份资料旨在帮助开发者深入理解Java编程语言,提升编程技能,同时也为初学者提供了宝贵的实践参考。 ...

    java核心技术-整理过的笔记

    2. **Java EE(Enterprise Edition)**:企业版,针对大型企业级网络应用。 3. **Java ME(Micro Edition)**:微型版,适用于嵌入式设备和移动终端。 #### 二、开发环境搭建 开发Java应用,首先需搭建以下环境: -...

    JAVA核心面试知识整理.pdf

    Java核心面试知识整理包括了对JVM内存区域、...总结而言,这份面试知识点整理为Java开发者提供了一个全面、系统的复习框架,帮助面试者巩固和加深对Java核心技术的理解,以便在面试中展现出扎实的理论基础和实践能力。

    java笔试试题整理

    11. **Java EE**:如果面试涉及Web开发,那么对Servlet、JSP、JDBC、EJB、Spring、Hibernate等Java企业版技术的理解也是必不可少的。 12. **Java 8及更高版本的新特性**:例如lambda表达式、流(Stream API)、...

    JAVA开发网络游戏(英文版)Java实用源码整理learns

    在Java开发网络游戏的过程中,开发者需要掌握一系列的关键技术与概念。这个资源包,"JAVA开发网络游戏(英文版)Java实用源码整理learns",显然包含了有关这个主题的实用代码示例和学习材料,旨在帮助Java程序员提升在...

    java常用技术整理-基础架构方面.rar

    这份"java常用技术整理-基础架构方面.rar"的压缩包文件很可能包含了一系列关于Java基础架构技术的文章、笔记或教程,旨在帮助开发者系统地学习和掌握这些知识。 首先,Java的基础架构涉及JVM(Java虚拟机)。JVM是...

    Java从网络取得文件源码整理

    在Java编程语言中,从网络获取文件是一项常见的任务,它涉及到网络编程和I/O操作。...以上就是关于Java从网络获取文件的核心知识点,理解并熟练运用这些技术,可以编写出高效且可靠的文件下载程序。

    Java开发技术大全Java实用源码整理learns

    Java开发技术大全,Java实用源码整理,是Java开发者深入学习和实践的重要资源集合。这份压缩包文件包含了一些关键的学习材料,旨在帮助开发者提升技能,理解并掌握Java编程的核心概念和高级特性。 首先,让我们来看...

    java面试题整理集合

    在Java领域,面试是评估求职者技术实力的重要环节。这份整理集合涵盖了Java编程语言的基础、进阶、并发、内存管理、框架等多个方面,旨在帮助准备面试的开发者全面了解并掌握Java的核心知识。以下是对这些知识点的...

    Java面试题整理.docx

    ### Java面试题整理知识点 #### 数据结构理解与应用 **数据结构定义与分类:** - **集合结构**:集合中的元素除同属于一种类型外,彼此间没有其他关系。 - **线性结构**:线性结构中的数据元素之间存在一对一的...

    Java核心面试知识整理.pdf

    本文档是一份关于Java核心面试知识的整理资料,内容涉及Java虚拟机(JVM)、Java内存模型、垃圾回收机制、Java IO/NIO、Java集合等多个关键知识点。通过对这些知识的梳理,能够帮助Java开发者更好地准备面试,同时也...

    140个java源码实例Java实用源码整理learns

    《140个Java源码实例Java实用源码整理learns》这一资源的出现,恰好满足了广大Java学习者的需求。 该资源以实例的形式,提供了140个精选的Java源码,涵盖了Java编程的各个方面。无论是Java基础概念,如控制流、循环...

    java技术网经典资料整理

    以上只是Java技术体系中的一部分,这份"java技术网经典资料整理"很可能涵盖了这些主题,甚至是更深入的专题,如并发编程的最佳实践、微服务架构、Docker容器化等。通过深入学习和实践,你可以成为一名熟练的Java...

    JAVA核心知识点整理.pdf

    垃圾回收机制是JVM的核心功能之一,涉及到多种算法,包括引用计数法、可达性分析、标记-清除、复制、标记-整理算法,以及分代收集算法等。Java中定义了四种引用类型:强引用、软引用、弱引用和虚引用。这些引用类型...

    JAVA写的个人博客源码Java实用源码整理learns

    2. **更多Java资料学习.url** - 这可能是一个URL链接,指向一个网站或网页,提供了更多的Java学习资源,包括但不限于教程、文档、最佳实践或者社区论坛,对于深入学习Java语言和技术栈非常有帮助。 3. **jsymxx169....

Global site tag (gtag.js) - Google Analytics