前后端交互

273 阅读6分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前后端交互

利用Cookie

Cookie 是一些数据, 存储于电脑上的文本文件中,只要客户端cookie开放且有数据,每一次请求都会自动添加到http报文中,后台可以实时接收观察获取这些Cookie 。

Cookie 的作用就是用于解决 "如何记录客户端的用户信息":

当用户访问 web 页面时,他的名字可以记录在 cookie 中。 在用户下一次访问该页面时,可以在 cookie 中读取用户访问记录。 利用Session对象 session对象表示特定会话session的用户数据。

客户第一次访问支持session的JSP网页,服务器会创建一个session对象记录客户的信息。当客户访问同一网站的不同网页时,仍处于同一个session中。

request.getSession().setAttribute();
request.getSession().getAttribute();

只要浏览器不关闭,就能使用。所以用户访问网站整个生命都会用到的数据一般都用session来存储,比如用户名、登录状态之类的。

利用Request参数设置

request.setAttribute();
request.getRequestDispatcher("welcome.jsp").forward(request, response);
request.getAttribute();

不能用sendRedirect(),因为已经切换到另一个请求了,request参数的有效期为本次请求。

Ajax

前端用ajax发起请求。

window.onload=function(){
    var jsondata={
        "name":"Sarrans",
        "password":"123456"
    }
    $.ajax({
        type:"post",
        url:"login",
        data:jsondata,
        success:function(data){
            alert(data.name+"请求成功");
        }
        error:function(e){
            alert("Error");
    }
    })
}

后台servlet接收请求处理

@WebServlet("/login")//ajax的url
public class login extends HttpServlet{
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        //从前端传递的request取值
        String name=request.getParameter("name");
        //构造一个新的json传回去
        String s="{\"name\":\"Gerorge\",\"password\":\"1234567\"}";
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(s);//写入返回结果
        //如果前台结果为success,会输出 Gerorge请求成功
    }
}

jsonp

结合跨域方式,因为前端请求到数据需要在回调函数中使用,所以后端得将数据放回到回调函数中。

$.ajax({
    url:"",
    dataType:"jsonp",
    jsonp:'callback',
    success(function(res){
      console.log(res)
    })
})

性能改进

Comet

Comet的实现主要有两种方式,基于Ajax的长轮询方式和基于 Iframe 及 htmlfile 的流(http streaming)方式。而这些大部分功能在后台完成,前端要做的就是通过ajax请求成功后,在XMLHttpRequest的onreadystatechange函数中持续获取数据。

典型的Ajax通信方式也是http协议的经典使用方式,要想取得数据,必须首先发送请求。在低延迟要求比较高的web应用中,只能增加服务器请求的频率。Comet则不同,客户端与服务器端保持一个长连接,只有客户端需要的数据更新时,服务器才主动将数据推送给客户端。

var xhr=getXmlHttpRequest();
xhr.onreadystatechange=function(){
    console.log(xhr.readyStae);
    if(xhr.readyState===3&&xhr.status===200){
        //获取成功后执行操作
        //数据在xhr.responseText
        console.log(xhr.responseText);
    }
}

SSE

SSE是一种允许服务端向客户端推送新数据的HTML5技术。它是 WebSocket 的一种轻量代替方案,使用 HTTP 协议。

严格地说,HTTP 协议是没有办法做服务器推送的,但是当服务器向客户端声明接下来要发送流信息时,客户端就会保持连接打开,SSE 使用的就是这种原理。

与由客户端每隔几秒从服务端轮询拉取新数据相比,这是一种更优的解决方案。

应用场景:例如邮箱服务的新邮件提醒,微博的新消息推送、管理后台的一些操作实时同步等.

var source=new EventSource("myevent");
source.onmessage=function(event){
    console.log(event.data);
};
source.onerror=function(){
    console.log("失败,连接状态"+source.readySate)
};

EventSource对象参数为入口点,必须与创建对象的页面同源(url模式,域、端口)。连接断开会自动建立,或者使用source.close()强制断开。open事件在连接建立时触发,message事件在接收到新数据时触发,error事件在无法建立连接时触发。推送数据保存在event.data中。

WebSocket

Websocket是一个全新的、独立的协议,基于TCP协议,与http协议兼容、却不会融入http协议。他被设计出来的目的就是要取代轮询和 Comet 技术。

WebSocket通过单个TCP连接提供全双工(双向通信)通信信道的计算机通信协议。此WebSocket API可在用户的浏览器和服务器之间进行双向通信。用户可以向服务器发送消息并接收事件驱动的响应,而无需轮询服务器。 它可以让多个用户连接到同一个实时服务器,并通过API进行通信并立即获得响应。

它允许用户和服务器之间的流连接,并允许即时信息交换。在聊天应用程序的示例中,通过套接字汇集消息,可以实时与一个或多个用户交换,具体取决于谁在服务器上“监听”(连接)。

WebSockets适用于需要实时更新和即时信息交换的任何应用程序。一些示例包括但不限于:现场体育更新,股票行情,多人游戏,聊天应用,社交媒体等。

var socket=new WebSocket("url");
socket.send("hello world");
socket.onmessage=function(event){
    console.log(event.data);
    console.log(event.readyState);
}

请求方式变化

jQuery ajax

传统 Ajax 指的是 XMLHttpRequest(XHR), 最早出现的发送后端请求技术,隶属于原始js中,核心使用XMLHttpRequest对象,多个请求之间如果有先后关系的话,就会出现回调地狱。 JQuery ajax 是对原生XHR的封装,除此以外还增添了对JSONP的支持。

$.ajax({
   type: 'POST',
   url: url,
   data: data,
   dataType: dataType,
   success: function () {},
   error: function () {}
});

缺点:

本身是针对MVC的编程,不符合现在前端MVVM的浪潮 基于原生的XHR开发,XHR本身的架构不清晰。 JQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理(采取个性化打包的方案又不能享受CDN服务) 不符合关注分离(Separation of Concerns)的原则 配置和调用方式非常混乱,而且基于事件的异步模型不友好。

fetch

fetch
try {
  let response = await fetch(url);
  let data = response.json();
  console.log(data);
} catch(e) {
  console.log("Oops, error", e);
}

fetch号称是AJAX的替代品,是在ES6出现的,使用了ES6中的promise对象。Fetch是基于promise设计的。Fetch的代码结构比起ajax简单多了,参数有点像jQuery ajax。但是,fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。

优点:

符合关注分离,没有将输入、输出和用事件来跟踪的状态混杂在一个对象里 语法简洁,更加语义化 基于标准 Promise 实现,支持 async/await 同构方便,使用 脱离了XHR,是ES规范里新的实现方式 更加底层,提供的API丰富(request, response) 缺点:

fetch只对网络请求报错,对400,500都当做成功的请求,服务器返回 400,500 错误码时并不会 reject,只有网络错误这些导致请求不能完成时,fetch 才会被 reject。 fetch默认不会带cookie,需要添加配置项: fetch(url, {credentials: 'include'}) fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费 fetch没有办法原生监测请求的进度,而XHR可以

axios

axios({
    method: 'post',
    url: '/user/12345',
    data: {
        firstName: 'Fred',
        lastName: 'Flintstone'
    }
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范。

特点:

从浏览器中创建 XMLHttpRequest 支持 Promise API 客户端支持防止CSRF 提供了一些并发请求的接口(重要,方便了很多的操作) 从 node.js 创建 http 请求 拦截请求和响应 转换请求和响应数据 取消请求 自动转换JSON数据