基于Servlet3.0的服务端消息推送,android应用

思路:使用Servlet3.0的AsyncContext将客户端请求响应保存起来,当服务端有数据变更时再响应,使用请求轮询的方式保持客户端和服务端的连接。

image


服务端tomcat7+ servlet3.0:

@WebServlet(urlPatterns = "/server",asyncSupported = true)
public class MessageServer extends HttpServlet {
	
	
	// TODO 任务队列 ,还没实现 
	ConcurrentLinkedQueue<String> taskQueue = new ConcurrentLinkedQueue<String>();
	//请求响应队列
	ConcurrentLinkedQueue<AsyncContext> contextQueue = new ConcurrentLinkedQueue<AsyncContext>();
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
	doPost(req, resp);
	}
	protected void doPost(final HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		String flag = request.getParameter("flag");
		String task =  StringUtil.Stream2String(request.getInputStream());
		
		System.out.println(task);
		
		if(StringUtil.NotEmpty(flag)){
			//客户端有数据发送过来
			if("client".equals(flag)&&StringUtil.NotEmpty(task)){
//				taskQueue.offer(task);
				push(task);
			}else if("receiver".equals(flag)){
				//响应客户端
				response.getWriter().flush();
				
				final AsyncContext asyncContext = request.startAsync();
				new Thread(){
					public void run() {
						asyncContext.setTimeout(0);
						contextQueue.offer(asyncContext);
						System.out.println("现有接收方:"+contextQueue.size());
					};
				}.start();
			}
		}
		
	}

	/**
	 *  从响应请求队列取出响应对象,逐一响应
	 * @param task 
	 * @throws IOException
	 */
	private synchronized void  push(String task) throws IOException {
		while(!contextQueue.isEmpty()){
			AsyncContext asyncContext = contextQueue.poll();
			HttpServletResponse response = (HttpServletResponse) asyncContext.getResponse();
			response.getWriter().println(task);
			response.setStatus(HttpServletResponse.SC_OK);
			asyncContext.complete();
		}
	}
	
}

 

接收端(android客户端):

=========MasycTask.java 异步任务类===========

public class MasyncTask extends AsyncTask<URL,String, Void> {
	TextView info;
	boolean flag;
	HttpURLConnection conn;
	public MasyncTask(TextView info) {
		this.info = info;
	}
	
	protected Void doInBackground(URL... urls) {
		
		try {
			HttpURLConnection conn = (HttpURLConnection) urls[0].openConnection();
			conn.setConnectTimeout(5000);
			this.conn = conn;
			
			if(conn.getResponseCode()==HttpURLConnection.HTTP_OK){
				if(!flag){
					publishProgress("成功连接服务器!");
					flag = true;
				}
				//将服务端返回的信息发送到前台方法
				String string = StringUtil.Stream2String(conn.getInputStream());
				if(StringUtil.NotEmpty(string)){
					publishProgress(string);
				}
				doInBackground(urls);
			}
		} catch (IOException e) {
			publishProgress("网络连接异常!"+e.getMessage());
		}
		
		return null;
	}
	
	protected void onProgressUpdate(String... values) {
		info.append(values[0]+"\n");
	}
	
	public void mCancel(){
		conn.disconnect();
		conn = null;
	}
}
===========MainActivity.java================
public class MainActivity extends Activity {

	TextView info;
	MasyncTask asyncTask;
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		info = (TextView) findViewById(R.id.info);
		
		try {
			asyncTask = new MasyncTask(info);
			asyncTask.execute(new URL("http://192.168.1.100:8080/MessageServer/server?flag=receiver"));
		} catch (MalformedURLException e) {
			info.append("URL解析异常!\n");
		}
	}
	
	@Override
	protected void onDestroy() {
		//中断连接
		asyncTask.mCancel();
		super.onDestroy();
	}
}

发送端( android客户端):

==========MTask.java========

 

public class Mtask extends AsyncTask<String, Void,String> {

	EditText msg;
	Context context;
	public Mtask(EditText msg,Context context) {
		this.msg = msg;
		this.context = context;
	}


	protected String doInBackground(String... strUrl) {
		String result=null;
		try {
			String string = msg.getText().toString();
			if(StringUtil.NotEmpty(string)){
				HttpPost method = new HttpPost(strUrl[0]);
				HttpConnectionParams.setConnectionTimeout(method.getParams(),5000);
				HttpEntity entity = new StringEntity(string,"UTF-8");
				method.setEntity(entity);
				//执行请求,如果中途想终止请求可以使用abort()
				HttpResponse response = new DefaultHttpClient().execute(method);
				if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
					result = "发送成功!";
				}
			}
		} catch (IOException e) {
			result = "网络连接异常!"+e.getMessage();
		}
		return result;
	}
	protected void onPostExecute(String result) {
		Toast.makeText(context,result,Toast.LENGTH_SHORT).show();
	}
	
}
 
============MainActivity.java=============
public class MainActivity extends Activity {

	EditText msg;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        msg = (EditText) findViewById(R.id.msg);
    }
    
    public void sendMsg(View v){
    	new Mtask(msg,this).execute("http://192.168.1.100:8080/MessageServer/server?flag=client");
    }

}
 

posted on 2012-09-29 15:09  东方泛起鱼肚白  阅读(2233)  评论(1编辑  收藏  举报

导航