1. 程式人生 > >Java應用程式模擬向Servlet傳送POST請求

Java應用程式模擬向Servlet傳送POST請求

在某些情況下,需要用Java applicatioin來模擬form,向伺服器(本文以servlet為例)傳送http post請求,包括提交表單域中的資料以及上傳檔案。如果僅僅是傳遞form中的資料,而不包含上傳檔案,那是很簡單的,比如Java application可以這麼寫:

package com.pat.postrequestemulator;

importjava.io.BufferedReader;

importjava.io.InputStream;

importjava.io.InputStreamReader;

importjava.io.OutputStreamWriter;

importjava.net.HttpURLConnection;

importjava.net.URL;

public class PostRequestEmulator

{

         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 class HandlingHttpRequestServlet extends HttpServlet

{

         private static final longserialVersionUID = 1L;

         @Override

         protected void doGet(HttpServletRequestreq, HttpServletResponse resp)

         throws ServletException, IOException

         {

                   super.doGet(req, resp);

         }

         @Override

         protected void doPost(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方面的應用了,所以機器上沒有現成的環境,為此先要進行這方面的準備。

     如:D:\Tomcat6

     和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使之如下:

<?xmlversion="1.0" encoding="ISO-8859-1"?>

<!--

 Licensed to the Apache Software Foundation(ASF) under one or more

  contributor license agreements.  See the NOTICE file distributed with

  this work for additional informationregarding copyright ownership.

  The ASF licenses this file to You under theApache License, Version 2.0

  (the "License"); you may not usethis file except in compliance with

  the License. You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreedto in writing, software

  distributed under the License is distributedon an "AS IS" BASIS,

  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,either express or implied.

  See the License for the specific languagegoverning permissions and

  limitations under the License.

-->

<web-appxmlns="http://java.sun.com/xml/ns/javaee"

  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">

   <servlet>

         <servlet-name>Hello</servlet-name>

          <servlet-class>com.pat.handlinghttprequestservlet.HandlingHttpRequestServlet</servlet-class>

    </servlet>

    <servlet-mapping>  

         <servlet-name>Hello</servlet-name>

         <url-pattern>/upload</url-pattern> 

    </servlet-mapping>

</web-app>

這個web.xml可以先從D:\Tomcat6\webapps\examples\WEB-INF下面拷貝過來,再進行如上黑體字所示的修改即可。<servlet>標籤描述的是servlet程式碼方面的資料,其中<servlet-name>Hello</servlet-name>是給這個servlet起一個名字Hello,它必須和下面的<servlet-mapping>中的<servlet-name>一致,該名字具體是什麼可以隨意寫定。

<servlet-class>com.pat.handlinghttprequestservlet.HandlingHttpRequestServlet</servlet-class>說明了完整的servlet類名,即servlet的類名為HandlingHttpRequestServlet,它位於包com.pat.handlinghttprequestservlet中。

<url-pattern>/upload</url-pattern>,說明了如果客戶端向“http://Web伺服器的URL地址:埠號/test/upload”發出了請求,則該請求將由位於包com.pat.handlinghttprequestservlet中的HandlingHttpRequestServlet進行處理。

到此,前期準備工作結束。下面準備寫程式碼。

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 class HandlingHttpRequestServlet 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 void doPost(HttpServletRequest req, HttpServletResponse resp)

         throwsServletException, IOException

         {       

                   DiskFileItemFactory factory =new DiskFileItemFactory();

                   //得到絕對資料夾路徑,比如"D:\\Tomcat6\\webapps\\test\\upload"

                   String path = req.getRealPath("/upload");

                   //臨時資料夾路徑

                   String repositoryPath =req.getRealPath("/upload/temp");       

                   // 設定臨時資料夾為repositoryPath

                   factory.setRepository(newFile(repositoryPath));

                   // 設定上傳檔案的閾值,如果上傳檔案大於1M,就可能在repository

                   // 所代 表的資料夾中產生臨時檔案,否則直接在記憶體中進行處理

                   factory.setSizeThreshold(1024* 1024);

                   //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<FileItem>list = (ArrayList<FileItem>)uploader.parseRequest(req);

                            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

                   // 類FormFieldKeyValuePair的定義見後面的程式碼

                   ArrayList<FormFieldKeyValuePair> ffkvp = new ArrayList<FormFieldKeyValuePair>();

                   ffkvp.add(newFormFieldKeyValuePair("username", "Patrick"));

                   ffkvp.add(newFormFieldKeyValuePair("password", "HELLOPATRICK"));

                   ffkvp.add(newFormFieldKeyValuePair("hobby", "Computer programming"));

                   // 設定要上傳的檔案。UploadFileItem見後面的程式碼

                   ArrayList<UploadFileItem> ufi = new ArrayList<UploadFileItem>();

                   ufi.add(newUploadFileItem("upload1", "E:\\Asturias.mp3"));

                   ufi.add(newUploadFileItem("upload2", "E:\\full.jpg"));

                   ufi.add(newUploadFileItem("upload3", "E:\\dyz.txt"));

                   // 類HttpPostEmulator的定義,見後面的程式碼

                   HttpPostEmulator hpe = new HttpPostEmulator();

                   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<FormFieldKeyValuePair>generalFormFields,

                                                ArrayList<UploadFileItem>filesToBeUploaded) throws Exception

         {

                   // 向伺服器傳送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. 處理普通表單域(即形如key = value對)的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;

         }

}

// 一個POJO。用於處理普通表單域形如key = value對的資料

classFormFieldKeyValuePair implements Serializable

{

         private static final longserialVersionUID = 1L;

         // The form field used for receivinguser's input,

         // such as "username" in "<inputtype="text" name="username"/>"

         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;

         }

}

// 一個POJO。用於儲存上傳檔案的相關資訊

classUploadFileItem implements Serializable

{

         private static final longserialVersionUID = 1L;

         // The form field name in a form used foruploading a file,

         // such as "upload1" in "<inputtype="file" name="upload1"/>"

         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目錄中產生臨時檔案。

本文參考材料:

相關推薦

Java應用程式模擬Servlet傳送POST請求

在某些情況下,需要用Java applicatioin來模擬form,向伺服器(本文以servlet為例)傳送http post請求,包括提交表單域中的資料以及上傳檔案。如果僅僅是傳遞form中的資料,而不包含上傳檔案,那是很簡單的,比如Java application可以

Java】不依賴第三方庫傳送post請求

原始碼取自某簡訊平臺,不依賴第三方庫,無異常處理程式碼,僅供參考 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.P

Multipart/form-data POST檔案上傳詳解 理論 簡單的HTTP POST 大家通過HTTP伺服器傳送POST請求提交資料,都是通過form表單提交的,程式碼如下:

Multipart/form-data POST檔案上傳詳解 理論 簡單的HTTP POST 大家通過HTTP向伺服器傳送POST請求提交資料,都是通過form表單提交的,程式碼如下: <form method="post"action="http://w.soh

Url傳送post請求傳遞引數

        #region  向Url傳送post請求,返回網站響應內容        /// <summary>        /// 向Url傳送post請求,返回網站響應內容        /// </summary>        ///

Java EE --- JspServlet傳送引數

方法一: 在 body /body 中使用 href 傳送要刪除的ID。 //向 DemoServlet 中傳送 屬性名為 userId ,值為 ${user.userId},Servlet 通過userId 獲取它的值 <a href="DemoServlet?userId=$

java後臺模擬傳送post請求,get也請用此種方式避免編碼問題

public static String geturl1(String geturl,String content) throws Exception { //請求的webse

Java學習--HttpURLConnection傳送post請求

import java.io.*; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; /**

開發筆記9 | 部署 Java 應用程式到阿里雲 EDAS

前言 在之前的一篇文章中,我們介紹了 如何將一個本地的 Java 應用程式直接部署到阿里雲 EDAS ,有不少讀者反饋,如果目前已經在使用阿里雲 EDAS 了,那該如何配合這個外掛部署應用呢?在本文中,我們來介紹 部署 Java 應用程式到阿里雲 EDAS。 關於 EDAS EDAS 是一個圍繞應用和微

Fiddler監聽Java應用程式http請求方法(Configure a Java Application to Use Fiddler)

Fiddler官網:http://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/ConfigureJavaApp Configure a Java Application to Use Fiddler 要配置Java應用程式以向Fiddle

ARM40-A5應用程式——CAN匯流排的傳送和接收

ARM40-­A5應用程式——CAN匯流排的傳送和接收 版權宣告:本文為博主原創文章,允許轉載。      ARM40-A5系列板卡共有2路隔離CAN匯流排,CAN匯流排的引腳定義見《ARM40-­A5指南——CAN匯流排介面與測試》。 一、shell中CAN匯流排的接收與傳送

Java應用程式效能監控

Java應用程式效能監控 您想知道Java Runtime環境的執行狀況嗎? 您想監控執行緒死鎖、異常記憶體、CPU消耗和Java應用程式嗎? 監控Java應用程式 利用ManageEngine Applications Manager Java Runtime 監控功能,可以監

Java後臺傳送post請求,並接收返回資訊

/** * 向指定的 URL傳送遠端POST方法的請求 * @param url傳送請求的 URL * @param json請求引數, * @return 所代表遠端資源的響應結果 */ public static JSONObject sendPost(String

編寫一個Java應用程式,當用戶在輸入對話方塊中輸入兩個日期後(日期格式為YYYYMMDD,如1999年1月12日應輸入為19990112),程式將判斷兩個日期的先後順序,以及兩個日期之間的間隔天數(例

編寫一個Java應用程式,當用戶在輸入對話方塊中輸入兩個日期後(日期格式為YYYYMMDD, 如1999年1月12日應輸入為19990112), 程式將判斷兩個日期的先後順序, 以及兩個日期之間的間隔天數(例如1999年1月1日和1999年1月2日之間的間隔是1天。  

Java使用原始的HTTPURLConnect傳送post請求

主要介紹jdk中的httpURLConnect傳送post請求: package dbzhang.test; import java.beans.Encoder; import java.io.BufferedReader; import java.io.DataOutputStream; i

Java應用程式中將PDF轉換為圖片和將圖片轉換為PDF

這篇文章將介紹如何在Java應用程式中將PDF檔案轉換為圖片以及將圖片轉換為PDF檔案。 使用元件: Free Spire.PDF for JAVA Free Spire.PDF for JAVA是一款完全免費的PDF Java元件,開發人員可以使用它在Java應用程式中進行建立PD

java實現httpclient傳送post請求

需求:現在要在java後端介面中直接請求客戶提供的其他介面來獲取所需要的資料,那麼就需要用到httpclient來做,下面做一個實現以記錄... 第一步:匯入所需要的jar包並寫一個工具類 1.post請求工具類 因為我們需要的協議是https協議,所以我做了

通過ajax傳送post請求controller傳遞引數後,頁面無法跳轉問題

我的專案之前都是用location.href來向後臺傳遞引數,因為最近在學習ajax,所以將傳值方式改成了ajax傳送post請求,於是問題便接踵而來,我發現在controller中通過返回ModelAndView物件竟然不能實現頁面跳轉了,剛開始百思不得其解,現在總算明白這到底是怎麼一回事了,也想

使用ajax傳送post請求後呼叫servlet成功前臺沒有呼叫success

使用jquery ajax傳送請求後,前臺success方法一直沒有呼叫。 經除錯,返回狀態碼200說明請求傳送成功,後臺執行OK,猜測問題應該在前臺解析返回值部分。 錯誤示例: function validateName() {var name = $("#nameInputId").

冷門的 Java 應用程式安全沙箱機制瞭解一下

如果你經常閱讀原始碼,你會發現 Java 的原始碼中到處都有類似於下面這一段程式碼 class File { // 判斷一個磁碟檔案是否存在 public boolean exists() { SecurityManager security = System.getSecurityMana

axios傳送post請求java後端獲取不到資料原因及處理

場景/功能描述:     最近再學習前端的框架vue,發請求使用的是axios,自己簡單的寫了個後端,實現一個學生列表的crud,web層使用的是springmvc,並使用jq的$.ajax方式測試過介面沒問題。 出現的問題:     已經再次確保後端介面能接收jquery