**
前后端分离之数据交互
**
前言
前后端不分离的框架就是我们使用的Spring MVC框架,servlet层中包含了写前端页面的jsp和写后端逻辑的controller,在前端的页面中混入了很多后端的逻辑,这就是传统的web开发。在传统的web开发中,页面展示的内容以及页面之间的跳转逻辑,全都由后台来控制,这导致了前后端耦合度非常高,耦合度高则意味着,扩展性差,维护性差。前后端分离会使用JSON这种轻量级数据交互方式去返回数据给前端渲染。后端仅仅负责Model和Service即可,页面的渲染和跳转逻辑由前端来做。前后端分离在传统开发上增加了一个服务器处理静态资源,将View层和Controller层放到了前端,后台仅需处理数据存取相关以及业务逻辑相关.下面是前后端交互流程。
一、前后端交互流程?
上面已经讲到了抽象的流程,我们再来看一个淘宝搜索的示例:
二、代码实现流程
1.java对象转换成JSON数据
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class JSONTest {
public static void main(String[] args) {
UserBean bean = new UserBean();
bean.name = "Jeason";
bean.sex = "man";
String s = JSON.toJSONString(bean);
System.out.println(s);
List<UserBean> list = new ArrayList<>();
list.add( bean);
list.add( new UserBean("Tom","man"));
String s1 = JSON.toJSONString(list);
System.out.println(s1);
String json = "{\"name\":\"Jeason\",\"sex\":\"man\"}";
UserBean bean1 = JSON.parseObject(json, UserBean.class);
System.out.println(bean1);
JSONObject jsonObject = new JSONObject();
jsonObject.put("data",bean);
System.out.println(jsonObject);
}
}
输出:
{"name":"Jeason","sex":"man"}
[{"name":"Jeason","sex":"man"},{"name":"Tom","sex":"man"}]
UserBean{name='Jeason', sex='man'}
{"data":{"name":"Jeason","sex":"man"}}
2.写controller和Ajax请求
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "JSONServlet" ,urlPatterns = "/testJSON")
public class JSONServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//告诉客户端返回值的类型是JSON
response.setContentType("application/json");
//设置同源
response.setHeader("Access-Control-Allow-Origin","*");
response.getWriter().println("{\"name\":\"Jeason\",\"sex\":\"man\"}");
}
}
前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body>
<h1>这是主页</h1>
<script>
//发送一个异步请求
$.ajax({
url:"http://localhost:8080/day34_2/testJSON",
success:function(data){
console.log(data);
document.body.insertAdjacentHTML("beforeend","<h1>%</h1>".replace("%",data.name));
document.body.insertAdjacentHTML("beforeend","<h1>%</h1>".replace("%",data.sex));
document.getElementById("img").src = "";
},
error:function(err){
console.log(err);
document.getElementById("img").src = "";
}
});
</script>
</body>
</html>
案例总结
上面讲的是最基本的情况,使用 response来传输数据给前端,如下所示:
response.getWriter().println("{\"name\":\"Jeason\",\"sex\":\"man\"}");
现在我们可以定义一个response层,里面写经常用到的返回对象,这样就能提高代码的可读性。
首先封装一个response层,里面写具体的对象实体类。
import java.io.Serializable;
import java.util.List;
import lombok.Data;
@Data
public class GlobalResponse<T> implements Serializable{
private int code;
private String message;
private T data = null;
}
然后去写具体的返回逻辑:
@ApiOperation("下发指令接口")
@PostMapping("/new")
public GlobalResponse<Command> sendCommand(@RequestBody Command command) {
GlobalResponse<Command> resp = new GlobalResponse<>();
try {
resp.setCode(0);
resp.setMessage("success");
resp.setData(command);
return resp;
} catch (Exception e) {
e.printStackTrace();
resp.setCode(400);
resp.setMessage("fail");
resp.setData(command);
return resp;
}
}
之所以能够传输数据就是因为在构建泛型的GlobalrRsponse.java时实现了序列化,而在序列化接口时引入了io流。
这就是整体的实现逻辑。