Ajax
序列化表单元素:
serialize():把选择器选中的元素的name和value序列化为字符串。
【注意:以下情况不会被序列化】
1、表单元素被禁用
2、表单元素没有name属性
3、表单元素没有选中【仅限单选按钮和复选框】
4、file元素不会被序列化(文件域)
5、按钮不会被序列化
json是一种轻量级的数据交换格式,独立于任何编程语言,通常用在服务器和客户端之间传递数据的一个字符串。
【json就是一个字符串,只是这个字符串的格式是固定的】
json字符串的格式:
用json字符串描述一个对象:
{"name":"张三" , "age":"18" , "sex":"男"}
用json字符串描述多个对象:
[{"name":"张三" , "age":"18" , "sex":"男"},{"name":"李四" , "age":"22" , "sex":"女"}]
Fastjson框架:一个可以灵活的将对象、集合、数组、Map序列化成字符串的框架
常用类:JSON
常用方法:toJSONString(Object obj)等
ajax+json
一、AJAX:asynchronous javascript and xml【异步的javascript和xml(异步刷新技术)】
ajax需要结合javascript,通过异步引擎对象向服务器发送请求,并通过回调函数得到返回的结果
这个过程是异步的【异步引擎把请求发送完之后javascript会继续执行而不等待服务器响应】
二、异步引擎对象:XMLHttpRequest【javascript里的类】
常用属性:
readyState:对象的状态,返回值:
0:对象尚未初始化
1:对象开始发送请求
2:请求发送完成
3:开始读取服务器响应
4:服务器响应读取完成
status:响应状态,返回值:
200:服务器正常响应
404:请求资源未找到
500:服务器内部错误【后台报错】
403:没有访问权限
statusText:得到响应状态的文本【OK:正常】
responseText:获取服务器响应的数据,以文本的方式返回
responseXml:获得服务器响应的数据,解析成DOM对象返回
常用方法:
open(请求方式,URL,是否异步):初始化xmlHttpRequest的请求信息。
send(数据字符串):发送请求
abort():取消当前请求
常用事件:
onreadystatechange:在readyState属性的值发生变化时触发。
三、原生javascript发送ajax请求的代码:
//1、创建XMLHttpRequest对象【因为要兼容不同浏览器,所以要用判断是否支持】
var req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
//2、设置回调函数
req.onreadystatechange = 回调函数名;
//3、初始化
req.open("post","XXXServlet?param1=value1¶m2=value2",true);
//4、发送请求【如果参数拼接在url里面,则这里的参数可以写null】
req.send(null)
回调函数代码:
//1、判断服务器是否正常响应,并且响应的结果是否已经读取完毕
if(req.readyState==4&&req.status==200){
//2、获得响应的数据
var data = req.responseText;
//3、拿数据来使用
//alert(data);
document.write(data);
}
四、jQuery对ajax进行了封装,jQuery可以使用简单的几行代码来实现异步请求。
jQuery的ajax方法包括:
3、$.ajax(settings):可以灵活的自定义请求
settings的写法:{XXX : XXX , YYY : YYY}【详情参照帮助文档】
五、json
json是一种轻量级的数据交换格式,独立于任何编程语言,通常用在服务器和客户端之间传递数据的一个字符串。
【json就是一个字符串,只是这个字符串的格式是固定的】
json字符串的格式:
用json字符串描述一个对象:
{"name":"张三" , "age":"18" , "sex":"男"}
用json字符串描述多个对象:
[{"name":"张三" , "age":"18" , "sex":"男"},{"name":"李四" , "age":"22" , "sex":"女"}]
jQuery的ajax方法:
$.ajax(settings):可以灵活的自定义请求
settings的写法:{XXX : XXX , YYY : YYY}【详情参照帮助文档】
$.get(url,data,callBack): 发送异步的get请求,参数有:
url:请求的路径,通常是一个servlet
data:请求的参数,格式可以写成 name=value&name1=value1 或者 {name:value,name1:value1}
callback:回调函数
例如:
$("LoginServlet",{username:"admin",password:"123456"},function(data){
//这里的data就是servlet写给客户端的内容。
});
$.post(url,data,callBack): 发送异步的post请求,使用方式与$.get()一样。
$.getJSON(url,data,callBack): 发送异步的get请求,使用方式与$.get()一样。
【注意:返回的数据必须是json格式,且在回调函数中能自动转成json对象】
$(selector).load(): 远程加载数据到指定的元素中。
例如
$("#content").load("DataServlet");该代码可以把DataServlet写给客户端的数据加载到id为content的元素中
el与jstl
一、sEL表达式
1、为什么需要EL表达式?
2、EL简介
3、语法:${ EL表达式 }
1)使用变量名获取值,变量名即存储在page、request、session、application中的键
request.setAttribute("name","admin");
${ name }
2)如果保存的对象,则通过"."或"[]"获取属性值
${user.name}
${user["name"]}
注意:
a- 如果属性名中包含特殊字符必须使用"[]"
b- 使用"[]"访问对象属性时必须加引号
c- "[]"还可以直接访问数组和集合元素
4、EL运算符
5、EL隐式对象
1)作用域访问对象:与JSP作用域对应,获取存储在page、request、session、application中的数据
pageScope,requestScope,sessionScope,applicationScope
2)参数访问对象:用于获取页面请求参数(表单和URL),与request.getParameter()/getParameterValues()对应
param,paramValues
二、JSTL
1、为什么需要JSTL?
2、JSTL环境准备:
1)jar包
2)指令 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3、JSTL核心标签库
1)通用标签
<c:set>
<c:out>
<c:remove>
2)条件标签
<c:if>
<c:choose>
3)迭代标签
<c:forEach
初识JSP
1、了解什么是动态网页
动态网页:同一个页面会随不同人群访问而显示不同的内容,它可以实现服务器端与客户端之间的交互
静态网页:页面内容永远不会变化,无法与服务器端取得交互。
2、什么是B/S架构与C/S架构,它们的区别
B/S架构:基于浏览器/服务器的一种架构,例如淘宝网、百度、京东等网站系统
C/S架构:基于客户端/服务器的一种架构,例如QQ、酷狗、LOL等
BS架构与CS架构的区别:
C/S:使用C/S架构软件需要安装客户端,每次更新需要升级,使用不方便,维护代价高。
B/S:使用B/S架构软件无需安装客户端,免去升级烦恼,使用方便,维护代价较低。
3、什么是URL,以及它的组成部分
URL是统一资源定位符,也就是所谓的网址,它由三部分组成
数据传输协议:http(超文本传输协议)、https(超文本加密传输协议)
服务器地址和端口:本机(localhost)、端口默认为80(80端口在URL中可以省略不写)
资源路径:如vjia/index.html
http://localhost:8080/vjia/index.html
上面这个URL是访问本机8080端口下路径为vjia文件夹下的index.html页面
4、tomcat服务器
a、tomcat是apache公司的一个开源项目,它是一款专门用来发布web项目的服务器
b、tomcat服务器并不是传统意义上的服务器系统,而是安装在服务器上的一个软件,可以称之为一个web容器,也可以叫做中间件。
c、它的作用就是用来处理网页的所有请求和响应
d、tomcat适用于中小型web项目的生产发布和学习使用,大型系统有JBOSS与weblogic,它们的原理都是一样的。
5、tomcat的安装及配置
a、安装tomcat绿色版(解压版)
b、配置环境变量CATALINA_HOME为tomcat的安装目录(与安装JDK时配置JAVA_HOME变量相同)
6、tomcat目录结构
bin:该目录放置了tomcat的所有可执行文件,windows下常用的如startup.bat和shutdown.bat,linux上用startup.sh与shutdown.sh
conf:该目录放置了tomcat的所有配置文件,常用的如server.xml、context.xml和tomcat-users.xml
lib:该目录存放了tomcat服务器所需的各种jar包
logs:该目录存放了tomcat运行的日志文件
temp:该目录存放了tomcat运行时的临时文件
webapps:该目录存放所有部署在tomcat的项目文件
work:该目录存放了tomcat翻译编译jsp后生成的.java文件和.class文件
7、在MyEclipse中配置tomcat。
8、WEB项目的目录结构
src:编写java源文件的根路径,所有java文件写到这个文件夹下。
webRoot:应用根目录,里面的所有文件均对客户端都可以访问,如JSP页面、HTML页面
WEB-INF:WebRoot的子目录,该目录下的所有文件都是不能被客户端直接访问的,只能通过服务器来访问,其中的关键文件为web.xml
WEB-INF/classes:存放所有的class文件
WEB-INF/lib:存放项目所需的jar包
9、JSP的组成部分
静态元素:包括HTML标签,CSS样式,以及静态的文字
指令:<%@ 指令%>,通常用来设置页面的属性、导包等
小脚本:<% java代码 %>,通过小脚本,在jsp中嵌入java代码
表达式:<%=表达式 %>,用来在页面上输出变量的值
声明:<%! 声明方法 %>,用来在jsp中定义一个方法,以便重用,定义变量时,为成员变量
注释:<%-- 注释 --%>,服务器注释,在客户端上无法看到
10、JSP的执行原理:
a、访问网页localhost:8080/web01/index.jsp,发送一个请求到服务器
b、tomcat服务器找到index.jsp文件
c、将index.jsp翻译成.java文件
d、将.java文件编译成.class文件
e、运行.class文件,输出内容到客户端
初识Servlet,单例模式
servlet概念
servlet是一个运行在服务器端,用于处理客户端请求并作出响应的,符合特定规范的java程序(类)
例如:
客户端访问index.jsp时,tomcat会将index.jsp翻译成一个java类,然后再编译该java类,最后执行里面的某个方法,其实这个翻译过来的java类就是一个servlet。
在早期的javaEE开发,并没有jsp,浏览器发送请求时直接请求到一个servlet,然后在servlet中用out对象的write方法把HTML页面代码逐行输出来,后来为了把页面与java代码分离,就创建了jsp的标准,允许在jsp文件中直接编写静态页面代码。
所以可以说jsp是对servlet的一种扩展(因为jsp最终还是会翻译成java类)
Servlet API有两个包
1、javax.servlet 支持通用的不依赖于协议的Servlet
2、javax.servlet.http 支持http协议的Servlet(常用)
由于网站都基于http协议,所以在编写servlet时通常都是使用javax.servlet.http的API
步骤:
1、编写一个普通类去继承javax.servlet.http.HttpServlet
2、重写以下方法:
doGet():此方法在客户端以get方式请求时被执行
doPost():此方法在客户端以post方式请求时被执行
3、编写web.xml文件映射servlet
a、在根节点下编写servlet节点
<servlet>
<servlet-name>servlet的名称</servlet-name>
<servlet-class>servlet的完整类路径</servlet-class>
<servlet>
b、在servlet节点下配置初始化参数(可选步骤),可以配置多个参数
<servlet>
<servlet-name>servlet的名称</servlet-name>
<servlet-class>servlet的完整类路径</servlet-class>
<init-param>
<param-name>参数名</param-name>
<param-value>参数值</param-value>
</init-param>
<servlet>
c、在根节点下编写servlet-mapping节点
<servlet-name>引用上面配置的名称</servlet-name>
<url-pattern>映射的请求资源名称</url-pattern>
</servlet-mapping>
步骤b配置的参数可以在servlet中调用getInitParameter方法来获取
String param = getInitParameter(参数名);
执行顺序:
第一次请求servlet:
tomcat实例化servlet对象
init()方法被调用
service()方法被调用
doPost()或doGet()方法被调用
第2~N次请求servlet
service()方法被调用
doPost()或doGet方法被调用
停止服务时:
destroy()方法被调用
从上执行顺序中得知,init方法和destroy方法只会执行一次,一个是初始化执行,一个是服务停止时执行,所以可以得到servlet的生命周期大概如下:
servlet的生命周期:
1、实例化
2、初始化
3、服务
4、销毁
在Servlet中获取内置对象:
获取out对象:
PrintWriter out = response.getWriter();
获取session对象:
HttpSession session = request.getSession();
获取application对象:
ServletContext application = request.getServletContext();
内置对象out、session、application只是一个对象名,相当于一个变量名,它们的类型是PrintWriter、HttpSession、ServletContext
在web.xml中配置上下文参数
1、在根节点下配置init-param
<context-param>
<param-name>参数名</param-name>
<param-value>参数值</param-value>
</context-param>
2、在每一个servlet中都可以通过application的getInitParameter方法来获取
String param = this.getServletContext().getInitParameter(参数名);
servlet初始化参数 与 上下文参数的区别
上下文参数可以在所有servlet中共享
servlet初始化参数只能在配置的那个servlet中使用
分页
实现分页的步骤:
1、确定每页显示的数据量(pageSize)
2、确定当前页数(pageIndex)
3、编写SQL语句,实现分页查询
mysql:select * from 表名 limit ?,?
4、将查询出来的数据显示到JSP页面
在分页的过程中,可以使用封装类Page来封装分页信息
Page类需要写的属性与方法
属性:
int pageSize:每页显示的数据量
int pageIndex:当前页
int totalCount:总记录数
int totalPage:总页数
List list:查询出来的数据集合
方法:getter、setter方法
数据传递和保存
回顾:
1、Tomcat服务器:
运行JSP的Web容器
2、JSP页面:
静态元素
<%@指令 %>
<% Java小脚本 %>
<%=表达式 %>
<%! 方法声明 %>
<%--注释--%>
3、JSP执行过程:
编写-->*.jsp-->翻译-->*.java-->编译-->*.class-->生成-->*.html-->浏览器显示
JSP内置对象:
由Web容器创建的一组对象,可以直接在JSP页面使用,无需使用“new”获取实例,名称是保留字
五大内置对象:out,request,response,session,application
一、out对象:用于向浏览器输出数据
1、常用方法:
print() -->用于在页面中显示字符串信息,可识别网页标签
注意:<%=表达式 %> 将被翻译成 out.print("");
二、request对象:用于处理客户端请求以及获取请求中的数据
1、常用方法:
String getParameter(String name) -->根据页面表单组件名称获取页面提交数据
String[] getParameterValues(String name) -->获取一个页面表单组件对应多个值时的用户的请求数据
void setCharacterEncoding(String charset) -->指定每个请求的编码,在调用getParameter()之前进行设定,可以解决中文乱码问题
RequestDispatcher getRequestDispatcher(String path) -->返回一个RequestDispatcher对象,该对象的forward()方法用于转发请求
2、中文乱码问题:由于字符集编码不一致造成,WEB容器默认编码方式为ISO-8859-1
1)POST方式提交表单中文数据时:
request.setCharacterEncoding("UTF-8");
String name=request.getParameter("name");
2)GET方式提交表单中文数据时:
String name=request.getParameter("name");
name=new String(name.getBytes("ISO-8859-1"),"UTF-8");
3)在Tomcat中设置字符集:解决GET方式多个参数进行编码转换的麻烦
conf\server.xml文件:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"/>
注意:如果已在Tomcat中设置了字符集,则无需在JSP页面中进行编码转换,否则仍将出现中文乱码
3、post提交和get提交的区别:
1)安全性:get方式提交的数据将显示在URL中,安全性较低
2)数据大小限制:get方式提交的数据不能超过2K,post无限制
注意:一般情况下,表单提交都采用post,超链接属于get
三、response对象:用于响应客户请求并向客户端输出信息
1、常用方法:
void sendRedirect(String location) -->将请求重新定位到一个不同的URL,即页面重定向
2、页面转发:在多个页面交互过程中实现请求数据的共享
实现:RequestDispatcher对象.forward()方法
<%
RequestDispatcher rd=request.getRequestDispatcher("welcome.jsp");
rd.forward(request,response);
%>
3、转发 VS 重定向:
1)转发是在服务器端发挥作用,通过forward方法将提交信息在多个页面间进行传递。request不会丢失,可以共享请求的数据
2)转发是在服务器内部控制权的转移,客户端浏览器的地址栏不会显示出转向后的地址。
3)重定向是在客户端发挥作用,通过请求新的地址实现页面转向。request会丢失,无法共享请求的数据
4)重定向是通过浏览器重新请求地址,在地址栏中可以显示转向后的地址。
4、超链接传递数据:
1)表现方式:<a href="test.jsp?name=value&name=value"></a>
2)所属响应方式:重定向,新的请求
3)所属提交方式:get
四、session对象:用于在多个请求和响应过程中存储状态信息,如:登录、购物车
1、http协议的特点:无状态,无连接
2、session,会话:浏览器与服务器之间的一次通话
1)个人状态管理,1个客户端(1个浏览器)对应1个session
2)session存储在服务器端,sessionid存储在客户端
3、session应用:权限访问控制,必须先登录才能访问主页
设置值:session.setAttribute(key,value);键值对
获取值:session.getAttribute(key);返回Object
4、设置session失效
1)手动设置失效:invalidate()
2)超时失效
a- 通过setMaxInactiveInterval()方法,单位:秒
<%
session.setAttribute("login","admin");
session.setMaxInactiveInterval(600);
%>
b- 通过设置项目的web.xml或Tomcat目录/conf/web.xml文件,单位:分钟
<session-config>
<session-timeout>10</session-timeout>
</session-config>
九大内置对象
不经常使用的内置对象
pageContext
config
page
exception
******************************************
application
session
out
response
request
===============
解决乱码方法:
1.改变request取出来的数据的编码
String name=request.getParameter("userName");
name=new String(name.getBytes("IOS-8859-1"),"utf-8");
2.设置url的编码格式
在tomcat的配置文件中修改 URIEncoding="UTF-8";
数据传递与保存(二)
1、application对象:系统的一个全局对象,主要用于将数据保存在缓存,并且能够在所有客户端上共享。
主要方法:
application.setAttribute("key",Object); 在application缓存中存储数据,以键值对的方式存储,这些数据可以在所有的客户端进行共享。
application.getAttribute("key"); 通过key,获取application缓存中的数据,返回Object类型的对象。
application.removeAttribute("key"); 通过key,将数据从application缓存中清除。
2、内置对象的作用域
在学完这些JSP的常用内置对象之后,我们发现有一些方法在好几个对象中都有,这些方法是:
setAttribute("key",Object);
getAttribute("key");
removeAttribute("key");
这三个方法在request、session、application中都有,那么这些方法到底是干啥用的呢?为什么要有这么多,它们的区别是什么?
首先除了request、session、application之外,还有一个内置对象也有这些方法,那就是pageContext对象。
之前有介绍,setAttr...类型的方法都是把数据保存到缓存中,而getAttri...这类方法都是从缓存中拿取数据,removeAttr...则是从内存中移除数据。
而每个对象的这些方法的作用域与生命周期都不一样,下面来简单的介绍一下。
pageContext作用域:如果调用它的setAttri...方法,将数据保存进去,那这些数据只能在本页面使用,如果离开(无论是转发还是重定向),里面的数据都会清掉。
request作用域:调用request的setAttr...方法,将数据保存进去,这些数据可以在同一请求中生效。
session作用域:将数据保存到session.setAttribute方法时,将数据保存到session作用域,直到会话结束、session失效或主动移除。
application作用域:将数据保存到application作用域,整个服务启动期间有效,并且这些数据可以在所有的客户端中共享。
对象名称 作用域
pageContext 当前页面
request 同一请求
session 一次会话
application 整个服务启动期间
Cookie介绍
Cookie是保存在客户端电脑上的一个文件,大小不超过4KB,以键值对的方式存放一些简单的文本信息。
在发送请求的时候,会自动把客户端的Cookie文件封装成一个对象放到Request里传给服务器,服务器就可以获取到cookie里的信息。
sessionid就是保存在cookie里。
cookie中的数据没有经过加密,安全性极低,非常容易泄露。
可以使用cookie来实现访问记录以及自动登录。
方法:
request.getCookies();获取客户端的所有cookie,返回一个Cookie对象数组。
Cookie对象的常用方法;
getName(); 获取cookie的key,返回String字符串
getValue(); 获取cookie的值,返回String字符串
setMaxAge(int s); 设置cookie的有效时间,以秒为单位
添加Cookie的方法:
response.addCookie(Cookie cookie); 将一个cookie对象通过响应的方式写入到客户端。
数据源及分层开发
1、JNDI:Java Nameing and Directory Interface(java命名与目录接口)
jndi的作用是在服务器上配置一些数据,让应用服务器上的所有项目都可以使用,从而实现跨应用共享数据。
JNDI使用方式:
1、在tomcat的context.xml中配置jndi
<Environment name="变量名" value="变量值" type="变量的类型全名" />,例如:
<Environment name="myJndiName" value="测试JNDI" type="java.lang.String" />
2、在jsp中查找jndi,通过Context对象的lookup()方法来查找,步骤如下
a、创建Context对象
Context context = new InitialContext();
b、执行Context对象的lookup()方法,返回Object类型,参数为以下格式的字符串
Object obj = context.lookup("java:comp/env/变量名");
c、把对象强转成你想要的类型,并拿来使用
String str = (String)obj;
out.print(str);
2、连接池:(Connection pool)连接池可以理解成一个放了很多连接对象的池子,这些连接对象都是tomcat容器自动创建好了的,程序只要直接拿来用就可以了。
为什么有了JDBC还需要连接池?
JDBC连接数据库的方式是一种比较传统的连接方式,这种连接方式在执行过程中,需要经常与数据库建立连接,并且在使用后再关闭连接,释放资源。可想而知,频繁的连接和释放操作必然要耗费很多系统资源,因而需要有一种新的技术来弥补它的不足,这就是连接池(Connection Pool)技术。
使用连接池的好处:
1、不用频繁的去创建连接,每次都要去加载数据库驱动,使用完了要释放连接
2、当并发访问数量较大时,网站速度收到极大影响
3、系统的安全性和稳定性相对较差
数据源:DataSource
javax.sql.DataSource负责建立与数据库的连接
从Tomcat的数据源获得连接
把连接保存在连接池中
连接池中存放了很多的连接对象,而这些连接对象又是由数据源DataSource来创建的,但是DataSource又是通过什么方式来创建连接的呢?
1、DataSource怎么知道要连到哪个数据库?
2、DataSource怎么知道要创建多少个连接对象?
3、DataSource怎么知道连接数据库的用户名和密码是多少?
4、DataSource怎么知道数据库的驱动包路径是什么?
上述问题都可以通过JNDI来解决,步骤如下:
1、在tomcat中配置JNDI数据源:
<Resource name="jdbc/news"
auth="Container"type="javax.sql.DataSource" maxActive="100"
maxIdle="30" maxWait="10000" username="sa" password="sa"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://localhost:1433;DatabaseName=NewsManager"/>
2、在项目的web.xml中配置DataSource
<resource-ref>
<res-ref-name> jdbc/news </res-ref-name>
<res-type> javax.sql.DataSource </res-type>
<res-auth> Container </res-auth>
</resource-ref>
3、在BaseDao中查找jndi,通过Context对象的lookup()方法来查找
Context context = new InitialContext();
DataSource ds = context.lookup("java:comp/env/jdbc/news");
4、从DataSource对象中获取连接对象Connection
Connection conn = ds.getConnection();
context.xml中的<DataSource>属性讲解:
name:jndi名称(可以自定义)
auth:权限(取值Application、Container)
type:javax.sql.DataSource(不能改)
maxActive:指定连接池中处于活动状态的数据库连接的最大数目(最多创建多少个连接)
maxIdle:指定连接池中处于空闲状态的数据库连接的最大数目(最少存在多少个连接)
maxWait:指定连接池中的连接处于空闲的最长时间
username:连接数据库的用户名
password:连接数据库的密码
driverClassName:数据库驱动包路径
url:数据库的连接字符串
web.xml中的<resource-ref>讲解
<res-ref-name>子元素:表示引用哪个jndi,填写引用的jndi名称
<res-type>子元素:表示该jndi的数据类型,与context.xml中<Resource>的type要一致
<res-auth>子元素:表示权限名称,与context.xml中<Resource>的auth要一致
分层:
在以前的项目,只有两层,即数据访问层与界面展示层,随着项目的做大,业务的不断改变,数据层的代码要不断的进行修改,而且还时不时影响到其他的功能,维护起来非常麻烦。
后来在两层的基础上增加了一个业务层,随着业务的变化,在修改代码的时候,只需要修改业务层的代码,而数据层的不需要动它,维护起来风险小,比较方便。
三层:
即数据访问层(dao):数据库表的增、删、改、查操作
业务层(service):提供对业务逻辑处理的封装
表示层(jsp):用于用户展示与交互
分层的原则:
上层依赖其下层,依赖关系不跨层
表示层不能直接访问数据访问层
下一层不能调用上一层
下一层不依赖上一层
上层的改变不会影响下一层
下层的改变会影响上一层得到的结果
在上一层中不能出现下一层的概念
分工明确,各司其职