1. 程式人生 > >關於servlet服務端接收客戶端傳送的List資料的問題

關於servlet服務端接收客戶端傳送的List資料的問題

   這些天由於任務需要,又研究了一下servlet,因為以前學習過客戶端和伺服器通過JSON串傳輸資料,知道可以在servlet中查詢資料庫,再將資料組裝成JSON串傳送給客戶端,讓客戶端解析資料。但是這次由於涉及到客戶端上傳資料,經過servlet處理,然後存入資料庫中。這樣就不知道怎麼處理了。

   在實踐過程發現,如果在客戶端將資料組裝成JSON串,在傳送給servlet接收,用不了JSONjar(目測是需要導包的,因為servlet是在一個java工程中寫的,JSON for java的包蠻難找的- - ),想解析就碰到問題了。

   因為比較懶^^,所以想如果客戶端傳送List<

>資料(?號可以表示某個javabean)servlet能接收到,然後通過getXXX()的方法獲取資料該多好。。(感覺挺不錯的樣子)然後就開始找資料了…不知道是不是公司的網路畢竟廢,限制很多的原因,貌似沒找到啥相關的資料,只看到有個傳送List<String> 的例子,和預想中的自定義javabean還是有點差距。好在經過不懈的努力,最後終於成功了.廢話了一堆,以下開始寫流程:

1. 首先寫一個自定義的JavaBean,以UserInfo.java為例,需要實現物件序列化的介面,因為之後輸出流物件需要實現輸出可序列化的物件。不這樣的話,後續時傳送時會報異常。

package xl.java.bean;

import java.io.Serializable;

/**
 * 使用者資訊
 * @author xl 2012-9-20
 */
public class UserInfo implements Serializable
{

	private static final long serialVersionUID = 1L;

	/**
	 * 使用者名稱
	 */
	private String UserName;

	/**
	 * 密碼
	 */
	private String Password;

	/**
	 * 暱稱
	 */
	private String NickName;

	/**
	 * QQ號
	 */
	private int QQNumber;

	/**
	 * 電話號
	 */
	private String TelNumber;

	/**
	 * 年齡
	 */
	private int Age;

	public String getUserName()
	{
		return UserName;
	}

	public void setUserName(String userName)
	{
		UserName = userName;
	}

	public String getPassword()
	{
		return Password;
	}

	public void setPassword(String password)
	{
		Password = password;
	}

	public String getNickName()
	{
		return NickName;
	}

	public void setNickName(String nickName)
	{
		NickName = nickName;
	}

	public int getQQNumber()
	{
		return QQNumber;
	}

	public void setQQNumber(int qQNumber)
	{
		QQNumber = qQNumber;
	}

	public String getTelNumber()
	{
		return TelNumber;
	}

	public void setTelNumber(String telNumber)
	{
		TelNumber = telNumber;
	}

	public int getAge()
	{
		return Age;
	}

	public void setAge(int age)
	{
		Age = age;
	}
}

1. 為了讓客戶端引用的JavaBean包名和servlet引用的一致,請右鍵點選UserInfo.java選擇Export----java---JAR file-----選好匯出的路徑然後點finish,沒錯,我們這裡選擇將它打包,這是在LZ糾結了幾個小時後,才解決的一個問題。之前servlet端一直提示ClassNotFoundException,找不到這個bean類,由於沒仔細看Log,還一直以為是servlet端的引用問題,後來才發現,因為在客戶端工程中這個類的路徑是xl.java.bean.UserInfo.java,而我的servlet是在另外一個工程中寫的,相同的UserInfo.java

路徑不同,在servlet中接收到的List<UserInfo>一直提示找不到UserInfo這個類,糾結的….打包完全是因為水平不行..

(最新發現,可以不用打包,只要在WEB-INF \classes中建立資料夾xl\java\bean即可,然後將UserInfo放入bean資料夾內,通過javac UserInfo.java將它編譯成Class檔案就可以了,也就是說,包名一樣就行- -)

好吧 讓我們跳過亂七八糟的第2步,進行第三步好了。。


package xl.java.send;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import xl.java.bean.UserInfo;

/**
 * 模擬傳送資料
 * @author xl 2012-9-20
 * 
 */
public class SendData
{

	private static final String BASIC_URL_QUEST =
			"http://192.168.1.1:8080/test/TestServlet";

	public static void main(String[] args)
	{
		SendData senddata=new SendData();
		try
		{
			senddata.sendDataToServer();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 上傳處理結果
	 * 
	 * @throws IOException
	 * 
	 */
	private void sendDataToServer() throws IOException
	{
		//用於servlet判別請求,執行相應方法
		String QuestId = "SubmitUserInfoList";
		//模擬傳送自定義型別的List資料
		List<UserInfo> listdata = new ArrayList<UserInfo>();
		for (int i = 0; i < 10; i++)
		{
			UserInfo li = new UserInfo();
			li.setUserName("XL" + i);
			li.setPassword("00000" + i);
			li.setQQNumber(1234567 + i);
			li.setTelNumber("15012344321" + i);
			li.setNickName("xiaolang" + i);
			li.setAge(18 + i);
			listdata.add(li);
		}

		URL url = new URL(BASIC_URL_QUEST);
		try
		{
			URLConnection con = url.openConnection();
			HttpURLConnection httpUrlConnection = (HttpURLConnection) con;
			httpUrlConnection.setUseCaches(false);
			httpUrlConnection.setDoOutput(true);
			httpUrlConnection.setDoInput(true);
			httpUrlConnection.setRequestProperty("Content-type",
					"application/x-java-serialized-object");
			//不設定這個預設為Get,伺服器會沒反應,不知道什麼情況,
			//糾結了很久,改成Post的話,servlet裡的
			//doPost方法就有反應了
			httpUrlConnection.setRequestMethod("POST");
			httpUrlConnection.connect();
			OutputStream outStrm = httpUrlConnection.getOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(outStrm);
			//輸出流第一段資料是QuestId的值
			oos.writeObject(QuestId);
			//第二段資料是List資料
			oos.writeObject(listdata);		oos.flush();
			oos.close();
			InputStream inStrm = httpUrlConnection.getInputStream();
			System.out.println("資料傳送成功!");
		}

		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
}


4. 編寫TestServlet.java類,並把編寫完成的類,放在E:\Tomcat 7.0\webapps\test\WEB-INF\classes路徑下,同時開啟TestServlet.java類,把包名刪了,如下綠色字型部分,防止出現莫名其妙的錯誤- -然後通過javac編譯。

//package xl.java.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import xl.java.bean.UserInfo;

/**
 * @author xl 2012-9-20
 * 
 */
public class TestServlet extends HttpServlet
{

	private static final long serialVersionUID = 1L;

	private Connection mConnection = null;

	private Statement mStatement = null;

	private String QuestId = "";

	private static final String SUBMIT_USERINFO_LIST = "SubmitUserInfoList";// 客戶端提交到使用者資訊

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response)
	{
		System.out.println("________---------doPost--------_____________");

		try
		{
			// 連結資料庫
			Class.forName("org.gjt.mm.mysql.Driver").newInstance();
			mConnection =
					DriverManager
							.getConnection("jdbc:mysql://localhost/test?user=root&password=123&useUnicode=true&characterEncoding=UTF-8");
			mStatement =
					mConnection.createStatement(
							ResultSet.TYPE_SCROLL_INSENSITIVE,
							ResultSet.CONCUR_READ_ONLY);
			// 如果不是通過URL的Get形式上傳資料時,呼叫此方法,獲取上傳的list資料
			getListDataByObjectInputStream(request, response);
		}
		catch (SQLException e)
		{
			e.printStackTrace();
		}
		catch (InstantiationException e)
		{
			e.printStackTrace();
		}
		catch (IllegalAccessException e)
		{
			e.printStackTrace();
		}
		catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}

	}

	/**
	 * 獲取輸入流中的資料
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	private void getListDataByObjectInputStream(HttpServletRequest request,
			HttpServletResponse response) throws IOException,
			ClassNotFoundException
	{
		System.out.println("---------getListDataByObjectInputStream--------");
		response.setContentType("text/html");
		InputStream inStream = request.getInputStream();
		ObjectInputStream objInStream = new ObjectInputStream(inStream);
		QuestId = (String) objInStream.readObject();
		@SuppressWarnings("unchecked")
		List<UserInfo> inList = (List<UserInfo>) objInStream.readObject();
		if (QuestId.equals(SUBMIT_USERINFO_LIST))
		{
			System.out.println("QuestId.equals(SUBMIT_ORDER_LIST)");
			submitOrderList(request, response, inList);
		}
		objInStream.close();
		System.out.println("objInStream.close()");
	}

	/**
	 * @param request
	 * @param response
	 * @param inList
	 */
	private void submitOrderList(HttpServletRequest request,
			HttpServletResponse response, List<UserInfo> inList)
	{
		// 獲取資料,插入資料庫
		for (UserInfo item : inList)
		{
			System.out.println("UserName=" + item.getUserName());
			System.out.println("Password=" + item.getPassword());
			System.out.println("NickName=" + item.getNickName());
			System.out.println("QQNumber=" + item.getQQNumber());
			System.out.println("TelNumber=" + item.getTelNumber());
			System.out.println("Age=" + item.getAge() + "\n");
		}
		/**
		 * 插入資料庫程式碼可以寫在這..
		 */
	}
}


5. 執行SendData.java檔案,可看到控制檯輸出,根據前面的設定我們知道,客戶端和服務端已經建立連線,並且資料成功傳送給了服務端,然後我們E:\Tomcat 7.0\logs下的stdout_20120920.log(反正目錄下最後一個檔案),檢視Tomcat的列印資訊,如下圖

  最後說明下,不知道以這種形式傳送資料的效率怎麼樣,水平有限,感覺有點用,所以寫篇文章記錄下,如果大家對如何在android端通過servlet訪問MySql有疑問可以看下http://blog.csdn.net/wlzf6296149/article/details/7309971 比較早寫的一篇文章,應該能解決一些問題吧=. =