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的登录操作,结果是可行的!
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值