Ajax实现Web长连接

这篇文章写的很好Web 通信 之 长连接、长轮询(long polling),受益匪浅。

1.什么是长轮询,长连接

用通俗易懂的话来说,就是客户端不停的向服务器发送请求以获取最新的数据信息。这里的“不停”其实是有停止的,只是我们人眼无法分辨是否停止,它只是一种快速的停下然后又立即开始连接而已。

2.我的应用场景

想做一个二维码签到系统.
主要要求:
- 在浏览器上发布签到
- 一个二维码只能用一次
- 当浏览器上显示的二维码被使用过后,自动刷新成新的二维码

3.具体代码

页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title></title>
</head>
<script type="text/javascript">
  function myajax() {
    var myhttp;
    myhttp=new XMLHttpRequest();
    myhttp.open("GET", "qrajax", true);
    myhttp.send();
    myhttp.onreadystatechange=function()
    {
      if (myhttp.readyState==4 && myhttp.status==200)
      {
        var msg=myhttp.responseText;
        document.getElementById("asd").innerHTML=msg;
        if(msg!="failed"){
          document.getElementById("QRcode").src=
                  "qrcoder?flag="+Math.random()+"&teacherID="+document.getElementById("tecID").value;
        }
      }
    }
  }
  //长轮询,10秒发送一次ajax请求
  window.setInterval(myajax,10000);

</script>
<body>
<textarea id="asd"></textarea>
<img src="qr" id="qrajax"/>
<input type="text" id="tecID"/>
<button type="button" onclick="myajax()">Change Content</button>
</body>
</html>

服务器端

package com.servlet;

import com.service.QRService;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
public class QRAjax extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session=request.getSession();
        QRService service=new QRService();
        PrintWriter out = response.getWriter();
        //计时
        int time=0;
        if(session!=null){
            //长轮询
            while(true) {
                time++;
                //判断二维码是否被使用过
                if (service.isReflash()) {
                    out.print("no "+session.getAttribute("recordCount")+" ");
                    break;
                }else{
                    //保持10秒
                    if(time>=10){
                        out.print("failed");
                        break;
                    }else {
                        try {
                            //保持住,1秒循环一次
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                }
            }
        }
        out.close();
    }
}
原文地址:https://www.cnblogs.com/A-yes/p/9894199.html