基于Servlet3.0的服务端消息推送,android应用
思路:使用Servlet3.0的AsyncContext将客户端请求响应保存起来,当服务端有数据变更时再响应,使用请求轮询的方式保持客户端和服务端的连接。
服务端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");
}
}

浙公网安备 33010602011771号