별도의 전방 및 후방 단부
전통적인 개발 방법
옛날 옛적에, JSP와 자바 서블릿이 각광 시간 동안, 무한한 아름다움을 가져되어 있지만 인터넷의 지속적인 개발, 이러한 개발 방법을 점진적으로 모바일 인터넷 핫 오늘의 단점을 밝혀, 요구하는 백그라운드 서비스를위한 응용 프로그램 그것은받은 엄청난 변화가;
전통과 대화 형 프로젝트 개발 프로세스를 :
기존의 웹 개발에서, 페이지와 콘텐츠 페이지 사이의 논리적 점프는 모두 전면 및 후면 끝 커플 링 리드가 매우 높은, 높은 결합 수단, 확장 성, 가난, 정비 불량 등이다 백엔드에 의해 제어 보여 및 기타 문제
다음과 같이 전통적인 개발 문제는 다음과 같습니다
- 커플 링 고
문제는 자주 함께 전면을 확인하기 위해 필요하여 발생할 때, 문제를 디버깅
- 낮은 효율, 전방 및 후방 단부 상호 의존, 통신 비용, 높은 유지 비용 개발
- 가난한 확장 성, 다른 단말기와 호환되지 않습니다
대화 형 로직 혼란은 결국 코드 부패로 이어지는 (페이지 표시를 기억)
모바일 인터넷, 개발 속도의 급속한 발전에 적응하기 위해서는이 문제를 해결하는 방법을 개발하기위한 새로운 프로젝트를 찾을 필요가있다;
발전 모드는 전방 및 후방 단부를 분리
위의 문제의 근본 원인은 심각한 코어와 결합 전면과 후면 끝 명확한 경계, 또한 완전히 전면 및 후면 측 코드를 분리하는 것입니다 이러한 문제를 해결하지 않으려는 점에서 발생한다
이전과 분리 공정 개발 및 상호 작용의 종료 후 :
그래서 다른 무엇인가?
반면에 우리는 다음과 같은 차이점이 전체 프로젝트 구조 및 배포 환경 전에 서면으로 작성했습니다
기능 / 방법 | 전통 | 별도의 전방 및 후방 단부 |
---|---|---|
서버 환경 | 모든 tomca에 배포 할 수 있습니다 | 정적 리소스 서버 추가 |
MVC의 의무 | 모든 MVC에 대한 책임 배경 | VC에 대한 책임을 접수, M에 대한 책임을 무대 |
간단히 말해 :
기존 개발 전후 단부를 분리하면 정적 자원 서버 프로세스를 추가 , 컨트롤러와 원위 층에보기 층 , 백그라운드 프로세스 만 데이터 액세스와 관련 및 비즈니스 관련 로직
전면 :보기 및 컨트롤러 계층을 담당한다.
후면 : 만 책임 모델 층, 비즈니스 프로세스 / 데이터입니다.
별도의 전면 및 장단점 후단
장점 :
우려의 분리는, 뷰 레이어와 컨트롤 레이어 로직은 비즈니스 로직 및 시스템 아키텍처에 더 많은 관심을 지불 다시 전면으로 이동
커플 링 크게 개발 효율성 및 유지 관리 효율이 향상되었습니다 감소
수신 인터페이스 표시에 영향을주지 않습니다 오류 친화적 인, 무대 오류
개발자, 전면과 후면 끝은 더 이상 서로 너무 많은 언어의 개발에 참여 필요가 없습니다
단점 :
- 큰 프런트 엔드 개발자 압력, 레이어 컨트롤러에 초점을 맞출 필요가
- 增加静态服务器后,系统结构更复杂
- 更多的HTTP请求,在移动端运行效率差
- 逻辑靠近前端,不同平台需针对性重复实现,(安卓iOS+web)
- SEO优化无力,爬虫大多不支持ajax
前后端的重新定义:
在此之前区分前后端是根据硬件环境
分离后根据职责划分:如图
前后端分离页面执行流程(针对浏览器)
Controller层中会使用流程控制来完成数据校验,数据解析,页面的跳转等动作,那么如何完成呢,这就需要使用到JavaScript了
那么一个前后端分离的项目,前端是如何完成最终的数据展示呢?
如果前端是其他的例如iOS,安卓,则无需请求静态页面,页面的绘制是由系统原始语言实现的,只需要向后台请求json数据即可
what is json?
JSON全称(JavaScript Object Notation),js对象表示法,是一种轻量级数据交换格式
特点:
- 格式简单
- 解析方便,跨平台
- 轻量级
- 内容为字符串
最初产生于web项目中,后来因为太优秀,被各种CS结构项目使用
案例:
{
"uniquekey":"a56e67162bd84ee9c480e22a1170c14b",
"title":"人均负债17万从“全民储蓄”到“全民负债” 中国人的钱去哪儿了?",
"date":"2019-12-22 13:43",
"category":"头条",
"author_name":"鹤川倾海",
"url":"http://mini.eastday.com/mobile/191222134359221.html",
"thumbnail_pic_s":"http://05imgmini.eastday.com/mobile/20191222/20191222134359_b6ded6df388f5c6747e67bacfc32d125_4_mwpm_03200403.jpg"
}
你可以将其看做Map数据结构,以键值对形式存储,但是一些java中的数据结构json中是没有的例如,集合
不满足现状的前端小伙伴们-node.js
现在你已经知道了前后端分离的概念以及运行流程,作为后端开发的你不禁暗自窃喜,好了以后Controller不归我管了,你正要开始葛优躺时前端小伙伴炸锅了:
尼玛,各种页面跳转逻辑,用户验证逻辑,前端的表单验证………..,难道要在学学java?习惯了js的他们,肯定不愿意
问题就是动力,国外的Ryan Dahl这为兄台,决定改变这个现状,于是开发了使用JS作为开发语言的Node.js(2009/5),提供了异步IO,数据库支持,网络支持,等等,广大前端开发者激动落泪,以后别整什么java了,前后台一套JS全搞定,梦想是美好的,java(1996)是强大的,经历了二十几年的努力java已经是如此强大,稳定,node.js作为晚了13年的后期之秀还有很长的路要走;
相信使用一门语言编写所有程序的一天总会到来,也有很多人在努力实现这个梦想,例如RectNative;
Node.js在前后端分离中的作用
大家都知道淘宝网站做得很大面对成百上千的前台页面,想要提高整体开发效率,以及项目扩展性等,必然要采用前后端分离,大量的Controller层逻辑,以及数据校验逻辑,导致前端开发亚历山大,并且没有相对固定的开发模型,非常容易出问题
淘宝目前使用了一种叫做中途岛的构架,利用Node.js来完成了Controller层,并提供了一些其他良好的特性
构架:
职责:
优点:
- 请求聚合,Node在服务器端整合多个请求响应,一次性返回,效率更高
- SEO优化
- JS语言,学习成本低
- 浏览器与Node.js端代码可重用
- 服务器渲染
如果将其作为一个前端框架,Node.js对比Vue.js等无疑是重量级的
强调:
前后端分离并不是一定要加入node.js,前后端分离是责任划分问题,与使用什么服务器没有关系;
尝试一下
在页面中使用Ajax来请求数据,服务器返回json数据,前端使用js完成页面渲染
Ajax
Ajax是客户端的一种请求方式,全称(Asynchronous Javascript And XML)
用于异步的向服务器发送HTTP请求并获取响应数据,异步的好处在于,请求期间浏览器不会卡死,可以正常响应用户操作;而常见的表单提交,和直接打开指定地址,都是同步的;
对象转json
json数据的基本形式是键值对,对应着对象中的属性,是有规律的,那就可以使用代码来完成这一转换过程,下面列出了一些常见的json开源工具
- Gson
- FastJson
- Jackson
- Json-lib
性能对比请看这里对比
这里选择fastjson
下载jar
http://repo1.maven.org/maven2/com/alibaba/fastjson/
案例:
import com.alibaba.fastjson.JSON;
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
//Bean熟悉
ArrayList<String> hobby = new ArrayList<>();
hobby.add("girl");
hobby.add("music");
hobby.add("coding");
//JavaBean
Person p = new Person("jerry",18,true,hobby);
p.setDog(new Dog("小花花"));
//Bean转json字符串
String s = JSON.toJSONString(p);
System.out.println(s);
//json字符转Bean
Person person = JSON.parseObject(s,Person.class);
System.out.println(person);
//ArrAyList转json字符串
System.out.println(JSON.toJSONString(hobby));
}
}
前后端分离案例
现在把自己当成是前端,要开发一个前后分离的简单页面,用于展示学生信息列表
第一步
编写一个用于展示表格的静态页面
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<table id="tab" border="1">
<tr>
<th>编号</th>
<th>名字</th>
<th>年龄</th>
<th>性别</th>
</tr>
</table>
<button onclick="req()">请求数据</button>
<img id="img" />
</body>
</html>
不启动tomcat直接在编辑器中打开即可访问,测试他就是一个静态网页,而我们的编辑器就是一个HTTP服务器,可以响应静态网页
第二步
引入jquery使得ajax编写更方便
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
第三步
编写ajax,向服务器发送请求
第四步
将数据展示到页面上
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body>
<table id="tab" border="1">
<tr>
<th>编号</th>
<th>名字</th>
<th>年龄</th>
<th>性别</th>
</tr>
</table>
<button onclick="req()">请求数据</button>
<img id="img" />
</body>
<script>
function req(){
document.getElementById("img").src = "img/timg.gif";
$.ajax({
url:"http://localhost:8080/MyServer/getData",
success:function(data){
console.log(data);
document.body.insertAdjacentHTML("beforeend","<h1>%</h1>".replace("%",data));
document.getElementById("img").src = "";
},
error:function(err){
console.log(err);
document.getElementById("img").src = "";
}
});
}
</script>
</html>
现在身份切换回后端开发用于获取表格数据的接口
- 创建web项目
- 创建Servlet
- 引入fastjson
- 创建一个bean类
- 创建一堆bean放入列表中
- 将列表转为json字符串 返回给前端
Servlet代码
package com.kkb;
import java.io.IOException;
public class AServlet extends javax.servlet.http.HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
String s = "{\"name\":\"jack\"}";
response.getWriter().println(s);
}
}
启动服务,测试访问,会发现页面上没有显示服务器返回的结果….
跨越问题
打开浏览器检查页面会发现没有输出服务器返回的消息而是,出现了一个错误信息,这就是前后端分离最常见的跨越问题
什么是跨域
跨越为题之所以产生是因为浏览器都遵循了同源策略
同源策略:
同源策略(Same origin policy)是一种约定,它是[浏览器]最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,浏览器会先发送OPTION请求进行预检查,判断服务器是否允许跨域,如果允许才发送真正的请求,否则抛出异常。
简单的说:
同源策略浏览器的核心安全机制,其不允许在页面中解析执行来自其他服务器数据
如何判断是否跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
同源限制:
无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
无法向非同源地址发送 AJAX 请求
什么时候产生跨域问题:
浏览器在解析执行一个网页时,如果页面中的js代码请求了另一个非同源的资源,则会产生跨越问题
而浏览器直接跳转另一个非同源的地址时不会有跨域问题
解决跨越问题
상대방이 서버에 의해 신뢰 여부를 결정하기 위해 크로스 도메인 문제 행동의 금지 때문에 브라우저 만 크로스 도메인 요청을 실행하기 위해 데이터를 구문 분석하도록 브라우저를 설정해야 할 때, 그러나 이것은 서버 측에서 설정해야합니다
브라우저를 말하고, 응답 헤더의 필드를 추가, 서버는 신뢰할 수
package com.kkb;
import java.io.IOException;
public class AServlet extends javax.servlet.http.HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
response.setHeader("Access-Control-Allow-Origin","*");
String s = "{\"name\":\"jack\"}";
response.getWriter().println(s);
}
}
도약과 범위에 의해 지정된 도메인 이름의 값은, 모든 주소가 자신감을 표현할 수있다 *
기타 설정
//指定允许其他域名访问
'Access-Control-Allow-Origin:http://XXX.XXX.XXX'//一般用法(*,指定域,动态设置),注意*不允许携带认证头和cookies
//是否允许后续请求携带认证信息(cookies),该值只能是true,默认为false
//且需要前端配合进行相应设置才能让cookie跨越
'Access-Control-Allow-Credentials:true'
//预检查间隔时间
'Access-Control-Max-Age: 1800'
//允许的请求类型
'Access-Control-Allow-Methods:GET,POST,PUT,POST'
//列出必须携带的字段
'Access-Control-Allow-Headers:x-requested-with,content-type'
이 문제를 해결하려면 다음 위의 경우를 통해 개선
서블릿 코드 :
package com.kkb;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
public class AServlet extends javax.servlet.http.HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
//允许来自任何主机的跨越访问
response.setHeader("Access-Control-Allow-Origin","*");
//设置响应类型为json数据
response.setContentType("application/json;charset=utf-8");
//学生信息
ArrayList<Student> students = new ArrayList<>();
Student stu1 = new Student("s1","jack",20,"man");
Student stu2 = new Student("s2","tom",22,"girl");
Student stu3 = new Student("s3","jerry",10,"woman");
Student stu4 = new Student("s4","scot",24,"boy");
students.add(stu1);
students.add(stu2);
students.add(stu3);
students.add(stu4);
response.getWriter().println(JSON.toJSONString(JSON.toJSONString(students)));
}
}
HTML 코드
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body>
<table id="tab" border="1">
<tr>
<th>编号</th>
<th>名字</th>
<th>年龄</th>
<th>性别</th>
</tr>
</table>
<button onclick="req()">请求数据</button>
<img id="img" />
</body>
<script>
function req(){
document.getElementById("img").src = "img/timg.gif";
$.ajax({
url:"http://localhost:8080/MyServer/getData",
success:function(data){
data = JSON.parse(data)
console.log(data)
for (var i = 0; i < data.length; i++) {
a = data[i];
var row = "<tr><td>id</td><td>name</td><td>age</td><td>gender</td></tr>"
row = row.replace("id",a.id);
row = row.replace("name",a.name);
row = row.replace("age",a.age);
row = row.replace("gender",a.gender);
document.getElementById("tab").insertAdjacentHTML("beforeend",row);
}
document.getElementById("img").src = "";
},
error:function(err){
console.log(err);
document.getElementById("img").src = "";
}
});
}
</script>
</html>
케이스의 전후 단부의 간단한 분리는 도착