package com.pat.postrequestemulator;
importjava.io.BufferedReader;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.io.OutputStreamWriter;
importjava.net.HttpURLConnection;
importjava.net.URL;
public classPostRequestEmulator
{
public static void main(String[] args)throws Exception
{
// 服务地址
URL url = newURL("http://127.0.0.1:8080/test/upload");
// 设定连接的相关参数
HttpURLConnection connection= (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
OutputStreamWriter out = newOutputStreamWriter(connection.getOutputStream(), "UTF-8");
// 向服务端发送key = value对
out.write("username=kevin&password=pass");
out.flush();
out.close();
// 获取服务端的反馈
String strLine="";
String strResponse ="";
InputStream in =connection.getInputStream();
BufferedReader reader = newBufferedReader(new InputStreamReader(in));
while((strLine =reader.readLine()) != null)
{
strResponse +=strLine +"\n";
}
System.out.print(strResponse);
}
}
服务端的servlet可以这么写:
packagecom.pat.handlinghttprequestservlet;
importjava.io.IOException;
importjava.io.PrintWriter;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
public classHandlingHttpRequestServlet extends HttpServlet
{
private static final longserialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequestreq, HttpServletResponse resp)
throws ServletException, IOException
{
super.doGet(req, resp);
}
@Override
protected voiddoPost(HttpServletRequest req, HttpServletResponse resp)
throwsServletException, IOException
{
String username =req.getParameter("username"); //获取username所对应的value
String password =req.getParameter("password"); //获取password所对应的value
System.out.println("Thereceived username and password is: " + username + "/" +password);
// 向请求端发回反馈信息
PrintWriter out =resp.getWriter();
out.print("OK");
out.flush();
out.close();
super.doPost(req, resp);
}
}
一切看起来都不复杂。但是如果要模拟的表单,除了要向服务器传递如上面的“key = value”这样的普通信息,同时还要上传文件,事情就复杂得多。下面详解如下:
1. 准备
玄机逸士很久没有开发web方面的应用了,所以机器上没有现成的环境,为此先要进行这方面的准备。
a) 到http://tomcat.apache.org 上下载tomcat压缩包apache-tomcat-6.0.33.zip,将其解压到指定目录即可,
如:D:\Tomcat6
b) 到http://commons.apache.org上下载用于文件上传的两个包:commons-fileupload-1.2.2-bin.zip
和commons-io-2.1-bin.zip, commons-fileupload依赖于commons-io,但在编程的过程中,
不会直接用到commons-io
c) 检查Tomcat的安装是否成功。双击D:\Tomcat6\bin目录中的startup.bat文件,就可以启动tomcat。
打开浏览器,访问http://localhost:8080/,如果出现tomcat相关的页面,则说明tomcat安装成功。
d) 在D:\Tomcat6\webapps目录下创建一个test子目录,我们等会开发的servlet就将部署在这里。在
test目录下再建立两个目录WEB-INF(必须大写)和upload,在WEB-INF下面 创建两个目录classes和lib,
同时在新建一个web.xml文件;在upload目录下,创建一个temp子目录,这些工作做完以后,test目录
下面的目录文件结构如下图所示。
其中的classes目录,用来存放将要开发的servlet,lib用来存放commons-fileupload和commons-io相关的jar包,web.xml是一些应用描述信息;upload用于存放客户端(即我们要开发的Java application)上传过来的文件,temp则用于存放上传过程中可能产生的一些临时文件。
e) 将commons-fileupload-1.2.2-bin.zip和commons-io-2.1-bin.zip解压,可以得到commons-fileupload-
1.2.2.jar和commons-io-2.1.jar,我们将这两个文件拷贝到d)中创建的lib目录中。
f) 编辑web.xml使之如下:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
这个web.xml可以先从D:\Tomcat6\webapps\examples\WEB-INF下面拷贝过来,再进行如上黑体字所示的修改即可。 到此,前期准备工作结束。下面准备写代码。 2.Servlet的代码 packagecom.pat.handlinghttprequestservlet; importjava.io.File; importjava.io.IOException; importjava.io.PrintWriter; importjava.util.ArrayList; importjavax.servlet.ServletException; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importorg.apache.commons.fileupload.FileItem; importorg.apache.commons.fileupload.disk.DiskFileItemFactory; importorg.apache.commons.fileupload.servlet.ServletFileUpload; public classHandlingHttpRequestServlet extends HttpServlet { private static final longserialVersionUID = 1L; @Override protected void doGet(HttpServletRequestreq, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } @SuppressWarnings({"unchecked", "deprecation" }) @Override protected voiddoPost(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException { DiskFileItemFactory factory =new DiskFileItemFactory(); String path = req.getRealPath("/upload"); //得到绝对文件夹路径,比如 // "D:\\Tomcat6\\webapps\\test\\upload" String repositoryPath =req.getRealPath("/upload/temp"); //临时文件夹路径 factory.setRepository(newFile(repositoryPath)); // 设定临时文件夹为repositoryPath factory.setSizeThreshold(1024* 1024); // 设定上传文件的阈值,如果上传文件大于1M, // 就可能在repository所代 表的文件夹中产生 // 临时文件,否则直接在内存中进行处理 //System.out.println("----"+ req.getContextPath()); // 得到相对文件夹路径,比如 "/test" // 创建一个ServletFileUpload对象 ServletFileUpload uploader =new ServletFileUpload(factory); try { // 调用uploader中的parseRequest方法,可以获得请求中的相关内容, // 即一个FileItem类型的ArrayList。FileItem是在 // org.apache.commons.fileupload中定义的,它可以代表一个文件, // 也可以代表一个普通的form field ArrayList System.out.println(list.size()); for(FileItemfileItem : list) { if(fileItem.isFormField()) // 如果是普通的form field { Stringname = fileItem.getFieldName(); Stringvalue = fileItem.getString(); System.out.println(name+ " = " + value); } else // 如果是文件 { Stringvalue = fileItem.getName(); intstart = value.lastIndexOf("\\"); StringfileName = value.substring(start + 1); // 将其中包含的内容写到path(即upload目录)下, // 名为fileName的文件中 fileItem.write(newFile(path, fileName)); } } } catch(Exception e) { e.printStackTrace(); } // 向客户端反馈结果 PrintWriter out =resp.getWriter(); out.print("OK"); out.flush(); out.close(); super.doPost(req, resp); } } 再在classes目录建立如下目录结构com\pat\handlinghttprequestservlet,这用来代表HandlingHttpRequestServlet这个servlet所在的包名,将编译好的HandlingHttpRequestServlet.class,拷贝到这个目录下,然后启动(或者重新启动)tomcat 3.Java application的代码 package com.pat.postrequestemulator; importjava.io.BufferedReader; importjava.io.DataInputStream; importjava.io.File; import java.io.FileInputStream; importjava.io.InputStream; importjava.io.InputStreamReader; importjava.io.OutputStream; importjava.io.Serializable; importjava.net.HttpURLConnection; importjava.net.URL; importjava.util.ArrayList; public classPostRequestEmulator { public static void main(String[] args)throws Exception { // 设定服务地址 String serverUrl ="http://127.0.0.1:8080/test/upload"; // 设定要上传的普通Form Field及其对应的value ArrayList ffkvp.add(newFormFieldKeyValuePair("username", "Patrick")); ffkvp.add(newFormFieldKeyValuePair("password", "HELLOPATRICK")); ffkvp.add(newFormFieldKeyValuePair("hobby", "Computer programming")); // 设定要上传的文件 ArrayList ufi.add(newUploadFileItem("upload1", "E:\\Asturias.mp3")); ufi.add(newUploadFileItem("upload2", "E:\\full.jpg")); ufi.add(newUploadFileItem("upload3", "E:\\dyz.txt")); HttpPostEmulator hpe = newHttpPostEmulator(); String response =hpe.sendHttpPostRequest(serverUrl, ffkvp, ufi); System.out.println("Responsefrom server is: " + response); } } classHttpPostEmulator { //每个post参数之间的分隔。随意设定,只要不会和其他的字符串重复即可。 private static final String BOUNDARY ="----------HV2ymHFg03ehbqgZCaKO6jyH"; public StringsendHttpPostRequest(String serverUrl, ArrayList ArrayList { // 向服务器发送post请求 URL url = newURL(serverUrl/*"http://127.0.0.1:8080/test/upload"*/); HttpURLConnection connection= (HttpURLConnection) url.openConnection(); // 发送POST请求必须设置如下两行 connection.setDoOutput(true); connection.setDoInput(true); connection.setUseCaches(false); connection.setRequestMethod("POST"); connection.setRequestProperty("Connection","Keep-Alive"); connection.setRequestProperty("Charset","UTF-8"); connection.setRequestProperty("Content-Type","multipart/form-data; boundary=" + BOUNDARY); // 头 String boundary = BOUNDARY; // 传输内容 StringBuffer contentBody =new StringBuffer("--" + BOUNDARY); // 尾 String endBoundary ="\r\n--" + boundary + "--\r\n"; OutputStream out =connection.getOutputStream(); // 1. 处理文字形式的POST请求 for(FormFieldKeyValuePairffkvp : generalFormFields) { contentBody.append("\r\n") .append("Content-Disposition: form-data; name=\"") .append(ffkvp.getKey() + "\"") .append("\r\n") .append("\r\n") .append(ffkvp.getValue()) .append("\r\n") .append("--") .append(boundary); } String boundaryMessage1 =contentBody.toString(); out.write(boundaryMessage1.getBytes("utf-8")); // 2. 处理文件上传 for(UploadFileItem ufi :filesToBeUploaded) { contentBody = newStringBuffer(); contentBody.append("\r\n") .append("Content-Disposition:form-data; name=\"") .append(ufi.getFormFieldName() +"\"; ") // form中field的名称 .append("filename=\"") .append(ufi.getFileName() +"\"") //上传文件的文件名,包括目录 .append("\r\n") .append("Content-Type:application/octet-stream") .append("\r\n\r\n"); StringboundaryMessage2 = contentBody.toString(); out.write(boundaryMessage2.getBytes("utf-8")); // 开始真正向服务器写文件 File file = newFile(ufi.getFileName()); DataInputStream dis= new DataInputStream(new FileInputStream(file)); int bytes = 0; byte[] bufferOut =new byte[(int) file.length()]; bytes =dis.read(bufferOut); out.write(bufferOut,0, bytes); dis.close(); contentBody.append("------------HV2ymHFg03ehbqgZCaKO6jyH"); StringboundaryMessage = contentBody.toString(); out.write(boundaryMessage.getBytes("utf-8")); //System.out.println(boundaryMessage); } out.write("------------HV2ymHFg03ehbqgZCaKO6jyH--\r\n".getBytes("UTF-8")); // 3. 写结尾 out.write(endBoundary.getBytes("utf-8")); out.flush(); out.close(); // 4. 从服务器获得回答的内容 String strLine=""; String strResponse =""; InputStream in =connection.getInputStream(); BufferedReader reader = newBufferedReader(new InputStreamReader(in)); while((strLine =reader.readLine()) != null) { strResponse +=strLine +"\n"; } //System.out.print(strResponse); return strResponse; } } classFormFieldKeyValuePair implements Serializable { private static final longserialVersionUID = 1L; // The form field used for receivinguser's input, // such as "username" in " private String key; // The value entered by user in thecorresponding form field, // such as "Patrick" the abovementioned formfield "username" private String value; public FormFieldKeyValuePair(Stringkey, String value) { this.key = key; this.value = value; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } classUploadFileItem implements Serializable { private static final longserialVersionUID = 1L; // The form field name in a form used foruploading a file, // such as "upload1" in " private String formFieldName; // File name to be uploaded, thefileName contains path, // such as "E:\\some_file.jpg" private String fileName; public UploadFileItem(StringformFieldName, String fileName) { this.formFieldName =formFieldName; this.fileName = fileName; } public String getFormFieldName() { return formFieldName; } public void setFormFieldName(StringformFieldName) { this.formFieldName =formFieldName; } public String getFileName() { return fileName; } public void setFileName(StringfileName) { this.fileName = fileName; } } 4.运行结果 运行PostRequestEmulator之前,服务器的upload目录下的情况: 运行PostRequestEmulator后,服务器的upload目录下的情况: PostRequestEmulator从服务端得到的反馈情况: Response fromserver is: OK Tomcat控制台输出: 如果上传的文件中有大于1M的情况,第二次执行PostRequestEmulator的时候,就会在temp目录中产生临时文件。 本文参考材料: http://v.youku.com/v_show/id_XMjc0ODMxMTA4.html http://www.iteye.com/topic/1116110(在Android中用Application模拟http post请求) http://apps.hi.baidu.com/share/detail/46728849 http://www.eoeandroid.com/thread-22679-1-1.html http://blog.zhaojie.me/2011/03/html-form-file-uploading-programming.html