学习网页的概念和分类,了解静态网页和动态网页的不同;了解网页浏览器的工作原理。了解HTML,XHTML,HTML5的概念,制作简单的HTML页面的开发。
可以在internet上通过网页浏览信息,如新闻,图片等,还可发布信息,如招聘信息等,网页是在某个地方某一台计算机上的一个文件。
网页主要由3部分组成:结构,表现,行为。
静态网页的特点是不论在何时何地浏览这个网页,看到的形式和内容都相同,且只能浏览,用户无法与网站进行互动。静态页面由HTML编写,扩展名一般为.htm, .html, .shtml, .xml等。与动态页面相比,动态网页是以.asp, .jsp, .php, .perl, .cgi等形式为后缀。
动态网页指网页的内容可以根据某种条件而自动改变。
采用B/S结构,即浏览器/服务器结构,用户工作界面是通过www浏览器来实现的:
浏览器的工作原理:
www的基础是HTTP协议,web浏览器就是用于通过url来获取并显示web网页的一种软件工具,url用于指定要取得的Internet上资源的位置与方式。
HTML是一种用来制作超文本文档的简单标记语言,用其编写的超文本文档称为HTML文档,它能独立于各种操作系统平台。
可扩展超文本标记语言XHTML:
XHTML是不需要编译,可以直接由浏览器执行,是一种增强了的HTML。它的可扩展性和灵活性将适应未来网络应用的更多需求,是基于XML的应用。开发者在HTML4.0的基础上,用XML的规则对其进行一些扩展,由此得到了XHTML,所以,建立XHTML的目的是为了实现HTML向xml的过渡。
HTML5简化了:<!DOCTYPE html>,简化了DOCTYPE,简化了字符集声明,以浏览器的原生能力替代脚本代码的实现,简单而强大的HTML5API。
文件扩展名是操作系统用来标志文件格式的一种机制。扩展名如同文件的身份说明,区别了文件的类别和作用。
HTML网页的文件后缀名是.html或者.htm.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"xxx">
声明的作用,告诉浏览器所书写的HTML代码的版本。
复制代码
<meta>标签,是HTML文档<head>标签内的一个辅助性标签,meta标签分为2个重要的属性:name和http-equiv,通常用于能够优化页面被搜索的可能性。
meta标签下name属性的使用:
<head>
<meta name="keywords" content="nine, twenty-three">
<meta name="description" content="...">
<meta name="generator" content="Dreamweaver">
<meta name="author" content="depp">
<meta name="robots" content="all">
</head>
复制代码
meta标签下的另一个属性http-equiv,其作用是反馈给浏览器一些明确的信息,帮助浏览器更精确地展示页面。
<head>
<meta http-equiv="content-type" content="text/html; charset=gb2312"/>
</head>
复制代码
link标签,定义了一个外部文件的链接,经常被用于链接外部css样式。
base标签为整个页面定义了所有链接的基础定位,其主要的作用是确保文档中所有的相对url都可以被分解成确定的文档地址。
style标签用于定义css的样式。表明了在页面中引入一个.style的样式表。
script标签用于定义页面内的脚本。
titl标题标签,body体标签.
一个好的HTML文档应具备以下3个方面:
<br>..</br>
<p>...</p>
复制代码
<p align=left>...</p>
<p align=center>...</p>
<p align=right>...</p>
复制代码
给文本加标注:<acronym title="">...</acronym>注释的内容放在title属性后的引号中,被注释的内容放在标签内。
无序列表:ul,li,有序列表:ol li
定义列表:
<dl>
<dt>...</dt>
<dd>...</dd>
<dt>...</dt>
<dd>...</dd>
</dl>
复制代码
所以总的来说:jepg可以压缩图像的容量,png的质量较好,gif可以做动画。
矢量图
说说矢量图和位图最大的区别:
无论是否对图像进行缩放,都不会影响矢量图的效果,但会影响图的质量。
设计者一般只愿意将logo,ui图标,标识符号等简单图像存为矢量图。
图像的分辨率
分辨率的单位是dpi即每英寸显示的线数。通常所指的分辨率有两种,屏幕分辨率和图片分辨率,屏幕分辨率即计算机显示器默认的分辨率。
一般目前大部分显示器的分辨率是1024px x 768px,图片分辨率定义是用于量度位图图像内数据量多少的一个参数。
分辨率越高的图像,包含的数据越多,图像的容量就越大,会消耗更多的计算机资源,需要更大的存储空间。
分辨率指的是每英寸的像素值,通过像素和分辨率的换算可以测算图片的长度。
页面中的图像
<img src=... alt=.../>
复制代码
<img style="vertial-align:text-top"/>
复制代码
<img style="vertical-align:middle"/>
复制代码
<img style="vertical-align:text-bottom"/>
复制代码
<img style="vertical-alignbaseline"/>
复制代码
hspace=30px表示图像左,右两边与页面其他内容隔30px的距离。vspace=30px表示图像上,下两边与页面的其他内容的间隔距离是30px。
<img src="" widht="" height="">
<img src="..." border=>
<hr align=".." width="..." size="...">
<a href="链接对象的路径">链接锚点对象</a>
复制代码
把邮箱留给需要联系你的人
<a href="mailto:邮箱地址">链接锚点对象</a>
复制代码
dashed 虚线
double 双线
groove 槽线
inset 内陷
outset 外陷
复制代码
热点图像区域的链接
map标签:
<map id=...>
<area shape="..." coords="..." href="...">
</map>
复制代码
shape属性,用于确定选区的形状,rect矩形,circle圆形,poly多边形。href属性,就是超链接。coords属性,用于控制形状的位置,通过坐标来找到这个位置。
计算矩形的面积
<html>
<head>
<title>计算矩形的面积</title>
<style type="text/css">
.result {font-weight:bold;}
</style>
<script language="JavaScript">
function calculate() {
var length=document.data.length.value;
var width=document.data.width.value;
var height=document.data.height.value;
var area=document.getElementById('area');
area.innerHTML=length*widht;
volume.innerHTML=length*widht*height;
}
</script>
复制代码
<form action="my.php"></form>
复制代码
它表明了这是一个表单,其作用是提交my.php页面中的数据。
<form name="data">
复制代码
原理:在客户端接收用户的信息,然后将数据递交给后台的程序来操控这些数据。
<script language="JavaScript">
复制代码
如果通过引用外部javascript程序,就像链接外联样式:
<script type="text/javascript" src="dada.js"></script>
复制代码
<form action="da.php"></form>
复制代码
提交方式用get,表单域中输入的内容会添加在action指定的url中,当表单提交之后,用户会获取一个明确的url。get在安全性上较差,所有表单域的值直接呈现。post除了有可见的处理脚本程序,别的东西都可以隐藏。
<form name="dada">
复制代码
<form action="mailto:da@qq.com" method="post" name="dada"
enctype="text/plain" target="_blank"></form>
复制代码
是指用户输入数据的地方,表单域可分为3个对象,input, textarea, select。
input对象下的多种表单的表现形式。
<input name="" type="" value="" size="" maxlength="">
复制代码
<form action="" method="post">
<input name="name" type="text" size="20" maxlength="12">
</form>
<input name="secret" type="password" size="20" maxlength="20">
<input name="one" type="radio" value="one" checked="checked">
<input name="one" type="radio" value="two">
<input type="submit" value="确定">
<input type="reset" value="恢复">
复制代码
创建submit按钮或reset按钮时,name属性不是必需的。
使用hidden来记录页面的数据并将它隐藏起来,用户对这些数据通常并不关心,但是必须提交数据。
<form action=da.asp>
<input type=hidden name=somehidden value=dada>
<input type=submit value=下一页>
</form>
复制代码
image样式的表单
<input type="image" src="图片/小图标.jpg" alt="确定">
复制代码
file上传文件的样式表单
file样式表单允许用户上传自己的文件
<html>
<head>
<title>file样式的表单</title>
<style type="text/css">
body {font:120% 微软雅黑;}
input {font:100% 微软雅黑;}
</style>
</head>
上传我的文件:
<form action="..." method="post" enctype="multipart/form-data">
<input type="file" name="uploadfile" id="uploadfile"/>
</form>
</body>
</html>
复制代码
textarea对象的表单
textarea对象的表单
<html>
<head>
<title>file样式的表单</title>
<style type="text/css">
body{font:120% 微软雅黑;}
textarea{font:80% 微软雅黑;color:navy;}
</style>
</head>
<body>
留言板
<form action="..." method="post" enctype="multipart/form-data">
<textarea name="dada" rows="10" cols="50" value="dada">请说:</textarea>
</form>
</body>
</html>
复制代码
select对象的表单
select对象的表单
<form action="">
地址:
<select name="da1">
<option>1</option>
</select>
</form>
复制代码
使用optgroup标签配合label属性来给选项分类:
<select name="上海">
<optgroup label="da1">
<option>1</option>
</optgroup>
<optgroup label="da2">
<option>2</option>
</optgroup>
</select>
复制代码
在select标签中加入size属性即可,如size=6表示是一个能容纳6行文字的文本框,超出设置的行数时,将出现滚动条。
<select name="上海" size="6">
复制代码
表单域集合:表单域的代码由fieldset标签和legend标签组合而成。
<form action="..." method="post">
<fieldset>
<legend>注册信息:</legend>
输入用户名:<input name="name" type="text" size="20" maxlength="12">
</fieldset>
</form>
复制代码
表单输入类型
<input type="url" name="webUrl" id="webUrl" value="http://wwwxxx"/>
复制代码
<input type="email" name="dada" id="dada" value="23@qq.com"/>
复制代码
<input type="range" name="volume" id="volume" min="0" max="1" step="0.2"/>
复制代码
<input type="number" name="score" id="score" min="0" max="10" step="0.5"/>
复制代码
增加表单的特性以及元素
<input name="name" type="text" form="form1" required/>
<form id="form1">
<input type="submit" value="提交"/>
</form>
复制代码
<form id="form1" method="post">
<input name="name" type="text" form="form1"/>
<input type="submit" value="提交到page1" formaction="?page=1”/>
<input type="submit" value="提交到page2" formaction="?page=2"/>
<input type="submit" value="提交"/>
</form>
复制代码
placeholder特性
<input name="name" type="text" placeholder="请输入关键词"/>
复制代码
autofocus特性:用于当页面加载完成时,可自动获取焦点,每个页面只允许出现一个有autofocus特性的input元素。
<input name="key" type="text" autofocus/>
复制代码
autocomplete特性用于form元素和输入型的Input元素,用于表单的自动完成。
input name="key" type="text" autocommplete="on"/>
复制代码
autocomplete特性有三个值,可以指定"on","off"和""不指定,不指定就将使用浏览器的默认设置。
<input name="email" type="email" list="emaillist"/>
<datalist id="emaillist">
<option value="23#qq.com">xxxx</option>
</datalist>
复制代码
keygen元素提供一个安全的方式来验证用户。
<form action="">
<input type="text" name="name"/><br>
<keygen name="security"/>
<br><input type="submit"/>
</form>
复制代码
<form oninput="x.value=dada.value">
<input type="range" name="volume" value="50"/>
<output name="x"></output>
</form>
复制代码
为某个表单内部的元素设置了required特性,那么这项的值不能为空,否则无法提交表单。
<input name="name" type="text" placeholder="dada" required/>
复制代码
<input name="code" type="text" value="" pattern="[0-9]{6}" placeholder="da"/>
复制代码
<input type="range" name="dada" id="dada" min="0" max="1" step="0.2"/>
复制代码
<form action="dada.asp" novalidate="novalidate">
<input type="email" name="user_email"/>
<input type="submit"/>
</form>
复制代码
var validityState=document.getElementById("username").validity;
复制代码
var willValidate=document.getElementById("username").willValidate;
复制代码
var validationMessage=document.getElementById("username").validationMessage;
复制代码
好了各位,以上就是这篇文章的全部内容,能看到这里的人都是人才。我后面会不断更新技术相关的文章,如果觉得文章对你有用,欢迎给个“赞”,也欢迎分享,感谢大家 !!
前后端分离已成为互联网项目开发的业界标准使用方式,通过nginx+tomcat的方式(也可以中间加一个nodejs)有效的进行解耦,并且前后端分离会为以后的大型分布式架构、弹性计算架构、微服务架构、多端化服务(多种客户端,例如:浏览器,车载终端,安卓,IOS等等)打下坚实的基础。这个步骤是系统架构从猿进化成人的必经之路。
核心思想:前端html页面通过ajax调用后端的restuful api接口并使用json数据进行交互。
在互联网架构中,
web服务器:一般指像nginx,apache这类的服务器,他们一般只能解析静态资源。
应用服务器:一般指像tomcat,jetty,resin这类的服务器可以解析动态资源也可以解析静态资源,但解析静态资源的能力没有web服务器好。
一般都是只有web服务器才能被外网访问,应用服务器只能内网访问。
以前的JavaWeb项目大多数都是java程序员又当爹又当妈,又搞前端(ajax/jquery/js/html/css等等),又搞后端(java/mysql/oracle等等)。
随着时代的发展,渐渐的许多大中小公司开始把前后端的界限分的越来越明确,前端工程师只管前端的事情,后端工程师只管后端的事情。正所谓术业有专攻。
对于后端java工程师:
把精力放在java基础,设计模式,jvm原理,spring+springmvc原理及源码,linux,mysql事务隔离与锁机制,mongodb,http/tcp,多线程,分布式架构(dubbo,dubbox,spring cloud),弹性计算架构,微服务架构(springboot+zookeeper+docker+jenkins),java性能优化,以及相关的项目管理等等。
后端追求的是:三高(高并发,高可用,高性能),安全,存储,业务等等。
对于前端工程师:
把精力放在html5,css3,jquery,angularjs,bootstrap,reactjs,vuejs,webpack,less/sass,gulp,nodejs,Google V8引擎,javascript多线程,模块化,面向切面编程,设计模式,浏览器兼容性,性能优化等等。
前端追求的是:页面表现,速度流畅,兼容性,用户体验等等。
通常我们的JavaWeb项目都是使用了若干后台框架,springmvc/struts + spring + spring jdbc/hibernate/mybatis 等等。大多数项目在java后端都是分了三层,控制层(controller/action),业务层(service/manage),持久层(dao)。控制层负责接收参数,调用相关业务层,封装数据,以及路由&渲染到jsp页面。然后jsp页面上使用各种标签(jstl/el/struts标签等)或者手写java表达式(<%=%>)将后台的数据展现出来,玩的是MVC那套思路。紧接着系统发布,你需要用maven或者eclipse等工具把你的代码打成一个war包,然后把这个war包发布到你的生产环境下的web容器(tomcat/jboss/weblogic/websphere/jetty/resin)里,对吧?发布完了之后,你要启动你的web容器,开始提供服务,这时候你通过配置域名,dns等等相关,你的网站就可以访问了。这样一来,你的前后端代码全都在那个war包里了,包括你的js,css,图片,各种第三方的库。
在浏览器中输入你的网站域名(www.xxx.com),之后发生了什么?浏览器通过域名,再通过dns服务器找到你的服务器外网ip,将http请求发送到你的服务器,在tcp3次握手之后(http下面是tcp/ip),通过tcp协议开始传输数据,你的服务器得到请求后,开始提供服务,接收参数,之后返回你的应答给浏览器,浏览器再通过content-type来解析你返回的内容,呈现给用户。
我们先假设你的首页中有100张图片,此时,用户的看似一次http请求,其实并不是一次,用户在第一次访问的时候,浏览器中不会有缓存,你的100张图片,浏览器要连着请求100次http请求(有人会跟我说http长连短连的问题,不在这里讨论),你的服务器接收这些请求,都需要耗费内存去创建socket来玩tcp传输(消耗你服务器上的计算资源)。这样的话,你的服务器的压力会非常大,因为页面中的所有请求都是只请求到你这台服务器上,如果1个人还好,如果10000个人并发访问呢(先不聊服务器集群,这里就说是单实例服务器),那你的服务器能扛住多少个tcp连接?你的带宽有多大?你的服务器的内存有多大?你的硬盘是高性能的吗?你能抗住多少IO?你给web服务器分的内存有多大?会不会宕机?
这就是为什么,越是大中型的web应用,他们越是要解耦。
理论上你可以把你的数据库+应用服务+消息队列+缓存+用户上传的文件+日志+等等都扔在一台服务器上,你也不用玩什么服务治理,也不用做什么性能监控,什么报警机制等等。但是这样把鸡蛋都放在一个篮子里,隐患非常大。如果因为一个子应用的内存不稳定导致整个服务器内存溢出而hung住,那你的整个网站就挂掉了。
JSP的痛点:
以前的javaWeb项目大多数使用jsp作为页面层展示数据给用户,因为流量不高,因此也没有那么苛刻的性能要求,但现在是大数据时代,对于互联网项目的性能要求是越来越高。
1.动态资源和静态资源全部耦合在一起,服务器压力大,因为服务器会收到各种http请求,例如css的http请求,js的,图片的等等。一旦服务器出现状况,前后台一起玩完,用户体验极差。
2.UI出好设计图后,前端工程师只负责将设计图切成html,需要由java工程师来将html套成jsp页面,出错率较高,修改问题时需要双方协同开发,效率低下。
3.jsp必须要在支持java的web服务器里运行(例如tomcat,jetty,resin等),无法使用nginx等(nginx据说单实例http并发高达5w,这个优势要用上),性能提不上来。
4.第一次请求jsp,必须要在web服务器中编译成servlet,第一次运行会较慢。
5.每次请求jsp都是访问servlet再用输出流输出的html页面,效率没有直接使用html高。
6.jsp内有较多标签和表达式,前端工程师在修改页面时会遇到很多痛点。
7.如果jsp中的内容很多,页面响应会很慢,因为是同步加载。
8.需要前端工程师使用java的ide(例如eclipse),以及需要配置各种后端的开发环境,你们有考虑过前端工程师的感受吗。
基于上述的一些痛点,我们应该把整个项目实现前后端真正的解耦!
前后分离的优势:
1.可以实现真正的前后端解耦,前端服务器使用nginx。
前端/WEB服务器放的是css,js,图片等等一系列静态资源(甚至你还可以css,js,图片等资源放到特定的文件服务器,例如阿里云的oss,并使用cdn加速),前端服务器负责控制页面引用&跳转&路由,前端页面异步调用后端的接口,后端/应用服务器使用tomcat(把tomcat想象成一个数据提供者),加快整体响应速度。
(这里需要使用一些前端工程化的框架比如nodejs,react,router,react,redux,webpack)
2.发现bug,可以快速定位是谁的问题,不会出现互相踢皮球的现象。
页面逻辑,跳转错误,浏览器兼容性问题,脚本错误,页面样式等问题,全部由前端工程师来负责。
接口数据出错,数据没有提交成功,应答超时等问题,全部由后端工程师来解决。
双方互不干扰,前端与后端是相亲相爱的一家人。
3.在大并发情况下,可以同时水平扩展前后端服务器,比如淘宝的一个首页就需要2000+台前端服务器做集群来抗住日均多少亿+的日均pv。
4.减少后端服务器的并发/负载压力
除了接口以外的其他所有http请求全部转移到前端nginx上,接口的请求调用tomcat,参考nginx反向代理tomcat。
且除了第一次页面请求外,浏览器会大量调用本地缓存。
5.即使后端服务暂时超时或者宕机了,前端页面也会正常访问,只不过数据刷不出来而已。
6.也许你也需要有微信相关的轻应用,那样你的接口完全可以共用,如果也有app相关的服务,
那么只要通过一些代码重构,也可以大量复用接口,提升效率。(多端应用)
7.页面显示的东西再多也不怕,因为是异步加载。
8.nginx支持页面热部署,不用重启服务器,前端升级更无缝。
9.增加代码的维护性&易读性(前后端耦在一起的代码读起来相当费劲)。
10.提升开发效率,因为可以前后端并行开发,而不是像以前的强依赖。
11.在nginx中部署证书,外网使用https访问,并且只开放443和80端口,其他端口一律关闭(防止黑客端口扫描),内网使用http,性能和安全都有保障。
12.前端大量的组件代码得以复用,组件化,提升开发效率,抽出来!
总结一下新的方式的请求步骤:
大量并发浏览器请求--->web服务器集群(nginx)--->应用服务器集群(tomcat)--->文件/数据库/缓存/消息队列服务器集群
同时又可以玩分模块,还可以按业务拆成一个个的小集群,为后面的架构升级做准备。
击上方 关注订阅黑码教主获取更多精彩内容
在多重嵌套循环的程序上,如果能分出出多个独立循环也比嵌套在一个循环体内来的更有益。
优化循环的3种方式:减少每次迭代的开销、减少迭代的次数或者重新设计应用程序。
在测试的时候仅可能模拟真实环境:如低端机器和低速网络。
?
对于连续页面之间的差别很小的应用而言,使用Ajax技术能带来显著的改善。
?
在HTML页面完成展现之后,动态改变页面元素或调整CSS样式都会引起浏览器重绘,性能的损耗直接取决于动态改变的范围:如果只是改变一个元素的颜色之类的信息则只会重绘该元素;而如果是增删节点或调整节点位置则会引起其兄弟节点也一并重绘。
减少重绘并不是说不要重绘,而是要注意重绘范围:
以改变一个<a>标签的背景色、宽度和颜色为例。
<a href="javascript:void(0);" id="example">传统的代码</a> <script> var example=document.getElementById("example"); example.ondblclick=function() { example.style.backgroundColor="red"; example.style.width="200px"; example.style.color="white"; } </script>
以上会执行3次重绘,而通过CSS代替javascript多次执行则只进行一次重绘。
<style> .dblClick { width: 200px; background: red; color: white; } </style> <a href="javascript:;" id="example">CSS优化的代码</a> <script> var example=document.getElementById("example"); example.ondblclick=function() { example.className="dblClick"; } </script>
当浏览器在解析常规的script标签时,它需要等待script下载完毕,再解析执行,而后续的HTML代码只能等待。CSS文件引入要放在头部,因为这是HTML渲染必备元素。
?
为了避免阻塞加载,应把脚本放到文档的末尾,而CSS是需要放在头部的!
<head> <link rel="stylesheet" href="common.css"> ...... <script src="example.js"></script> </body>
深层级嵌套的节点在初始化构建时往往需要更多的内存占用,并且在遍历节点时也会更慢些,这与浏览器构建DOM文档的机制有关。浏览器会把整个HTML文档的结构存储为DOM“树”结构。当文档节点的嵌套层次越深,构建的DOM树层次也会越深。
如下代码,完全能够去掉
或其中一个标签。<div> <span> <label>嵌套</label> </span> </div>
页面缓存
通常不设置缓存的情况下,每次刷新页面都会重新读取服务器的文件,而如果设置缓存之后,所有文件都可以从本地取得,这样明显极大提高了页面效率。
我们可以通过设置页面头的expires来定义页面过期时间,将过期时间定久一点就达到了“永久”缓存。
<meta http-equiv="expires" content="Sunday 26 October 2099 01:00 GMT" />
当然,如果你的项目代码有变更,因为客户端缓存了文件就得不到最新的文件,势必造成显示错误。基于这个问题的解决方案就是给链接文件加一个时间戳,如果时间戳有变化,浏览器会认为是新文件,就会向服务器请求最新文件。
<script src="example2014-6-17.js"></script> //如果是JSP,可以用EL表达式来取时间戳信息,这样管理更加方便 <script src="example${your time param}.js"></script> //或者这样的写法更优秀: <script src="example.js?time=2014-6-7"></script> <script src="example.js?time=${your time param}"></script>
所有涉及到请求数据的文件尽量做压缩,比如Javascript文件、css文件及图片文件,特别是图片文件,如果没有高清晰要求,完全可以压缩后再使用。
数量少体积大的文件要比数量多体积小的文件加载速度快,所以有时候可以考虑将多个js文件、多个css文件合并在一起。
除此之外减少HTML文档大小还可以采取下面几种方法:
图像合并其实就是把网页中一些背景图片整合到一张图片文件中,再利用CSS 的“background-image”,“background- repeat”,“background-position”的组合进行背景定位,background-position可以用数字能精确的定位出背景图片的位置。
一个页面要用到多个图标,完全可以将多个图标合并成一个图,然后只需要发一次图片请求,通过css定位分割图标即可。
使用iframe并不会增加同域名下的并行下载数,浏览器对同域名的连接总是共享浏览器级别的连接池,在页面加载过程中iframe元素还会阻塞父文档onload事件的触发。并且iframe是html标签中最消耗资源的标签,它的开销比DIV、SCRIPT、STYLE等DOM高1~2个数量级。
避免onload事件被阻塞,可使用JavaScript动态的加载iframe元素或动态设置iframe的src属性(但其仅在高级浏览器IE9及以上有效)。
<iframe id="if"></iframe> document.getElementById("if").setAttribute("src","url");
一般来说,浏览器对于相同域名的图片,最多用2-4个线程并行下载(不同浏览器的并发下载数是不同的)。而相同域名的其他图片,则要等到其他图片下载完后才会开始下载。
有时候,图片数据太多,一些公司的解决方法是将图片数据分到多个域名的服务器上,这在一方面是将服务器的请求压力分到多个硬件服务器上,另一方面,是利用了浏览器的特性。(大家可以去新浪、腾讯门户网站查看,这些大型站点同一页面加载的图片可能由多个站点提供)
注:一个HTML请求的域名也不要太多(2~3个差不多),多了可能造成不同服务器连接时间差异,反而影响速度。
如<img src=""><a href="">这样的设置方式是非常不可取的,即使链接为空,在旧的浏览器也会以固定步骤发送请求信息。
另外<a href="#"></a>也不可取,最好的方式是在链接中加一个空的js代码<a href="javascript:void();"></a>
base64是一串字符串,他可以代表一个图片的所有信息,也就是可以通过
(S表示一串base64码)来显示图片,这种方式不需要再向服务器发送请求,完全由浏览器解析成图片。
目前高级浏览器都支持此功能,但要注意两点:
如果HTML里的图片没有指定尺寸(宽和高),或者代码描述的尺寸与实际图片的尺寸不符时,浏览器则要在图片下载完成后再“回溯”该图片并重新显示,这会消耗额外时间。
<iframe id="if"></iframe> document.getElementById("if").setAttribute("src","url");
如果浏览器不能获知页面的编码字符集,一般都会在执行脚本和渲染页面前,把字节流缓存,然后再搜索可进行解析的字符集,或以默认的字符集来解析页面代码,这会导致消耗不必要的时间。
<iframe id="if"></iframe> document.getElementById("if").setAttribute("src","url");
渐进式增强设计的通俗解释就是:首先写一段满足所有浏览器的基本样式,再在后面针对不同高级浏览器编写更漂亮的样式
如下代码,所有浏览器都支持background-color: #2067f5;满足了浏览器基本现实需求,而后面的background-image: -webkit-gradient等则为不同高级浏览器使用,只要浏览器识别就能执行这段代码(不识别,CSS也不会报错只会直接忽略)。
<div class="someClass"></div> .someClass { width: 100px; height: 100px; background-color: #2067f5; background-image: -webkit-gradient(linear, left top, left bottom, from(#2067f5), to(#154096)); background-image: -webkit-linear-gradient(top, #2067f5, #154096); background-image: -moz-linear-gradient(top, #2067f5, #154096); background-image: -ms-linear-gradient(top, #2067f5, #154096); background-image: -o-linear-gradient(top, #2067f5, #154096); background-image: linear-gradient(to bottom, #2067f5, #154096); }
预加载和懒加载,是一种改善用户体验的策略,它实际上并不能提高程序性能,但是却可以明显改善用户体验或减轻服务器压力。
预加载表示当前用户在请求到需要的数据之后,页面自动预加载下一次用户可能要看的数据,这样用户下一次操作的时候就立刻呈现,依次类推。
懒加载表示用户请求什么再显示什么,如果一个请求要响应的时间非常长,就不推荐懒加载。
当一个页面非常大,内容非常多,可以采用flush的形式分部分返回给页面,这样能告诉用户我正在工作,显示一部分内容比白屏等很长时间要好得多。在Java Web技术中,实现Flush非常简单,只要调用 HttpServletResponse.getWriter输出流的flush方法,就可以将已经完成加载的内容写回给客户端。
这种方式只适用于返回数据特别多、请求时间特别长的情况,常规数据还是用正常的实时全部返回最佳。这种实现方式实际会增加浏览器渲染时间和用户整体等待时间,但从用户体验上会更加优秀。
所谓的CDN,就是一种内容分发网络,它采用智能路由和流量管理技术,及时发现能够给访问者提供最快响应的加速节点,并将访问者的请求导向到该加速节点,由该加速节点提供内容服务。
通俗点说,你在成都(浏览器)购买了北京卖家(服务器)的产品,北京卖家通过快递(CDN服务)寄送包裹,从北京到成都可以走路、坐汽车、火车或飞机,而采用CND的快递会选择飞机直达,因为这种寄送方式最快。
当然使用CDN有两个注意事项:
浏览器缓存带来的性能提升已经众人皆知了,而很多人却并不知道浏览器的缓存过期时间、缓存删除、什么页面可以缓存等,都可以由我们程序员来控制,只要您熟悉HTTP协议,就可以轻松的控制浏览器。
所谓的动静分离,就是将Web应用程序中静态和动态的内容分别放在不同的Web服务器上,有针对性的处理动态和静态内容,从而达到性能的提升。我们知道如果一个HTML有多个域名请求数据文件会提高
Tomcat服务器在处理静态和并发问题上比较弱,所以事先动静分离的方式一般会用Apache+Tomcat、Nginx+Tomcat等。
以Apache+Tomcat为例,其运行机理是:页面请求首先给Apache,然后Apache分析请求信息是静态还是动态,静态则本机处理,动态则交给Tomcat做处理。
这其实是负载均衡的雏形,这样的实现不用让开发人员做任何特殊开发,一个
交给服务器即可,至于这个文件是从Apache还是从Tomcat取得,开发人员完全无需关注。
持久连接(Keep-Alive)也叫做长连接,它是一种TCP的连接方式,连接会被浏览器和服务器所缓存,在下次连接同一服务器时,缓存的连接被重新使用。HTTP无状态性表示了它不属于长连接,但HTTP/1.1提供了对长连接的支持(不过这必须依赖浏览器和服务器双方均支持长连接功能才行),最常见的HTTP长连接例子是“断点下载”。
浏览器在请求的头部添加 Connection:Keep-Alive,以此告诉服务器“我支持长连接,你支持的话就和我建立长连接吧”,而倘若服务器的确支持长连接,那么就在响应头部添加“Connection:Keep-Alive”,从而告诉浏览器“我的确也支持,那我们建立长连接吧”。服务器还可以通过Keep-Alive:timeout=..., max=...的头部告诉浏览器长连接失效时间。
配置长连接通常是要服务器支持设置,有测试数据显示,使用长连接和不使用长连接的性能对比,对于Tomcat配置的maxKeepAliveRequests为50来说,效率竟然提升了将近5倍。
HTTP协议支持GZIP的压缩格式,当服务器返回的HTML信息报头中包含Content-Encoding:gzip,它就告诉浏览器,这个响应的返回数据已经压缩成GZIP格式,浏览器获得数据后要进行解压缩操作,一定程度上减轻了服务器传输数据的压力。
很多服务器已经支持通过配置来自动将HTML信息压缩成GZIP,比如tomcat、又比如很火的Nginx。如果无法配置服务器级别的GZIP压缩机制,可以改为程序压缩。
// 监视对 gzipCategory 文件夹的请求 @WebFilter(urlPatterns={ "/gzipCategory/*" }) public class GZIPFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String parameter=request.getParameter("gzip"); // 判断是否包含了 Accept-Encoding 请求头部 HttpServletRequest s=(HttpServletRequest)request; String header=s.getHeader("Accept-Encoding"); //"1".equals(parameter) 只是为了控制,如果传入 gzip=1,才执行压缩,目的是测试用 if ("1".equals(parameter) && header !=null && header.toLowerCase().contains("gzip")) { HttpServletResponse resp=(HttpServletResponse) response; final ByteArrayOutputStream buffer=new ByteArrayOutputStream(); HttpServletResponseWrapper hsrw=new HttpServletResponseWrapper( resp) { @Override public PrintWriter getWriter() throws IOException { return new PrintWriter(new OutputStreamWriter(buffer, getCharacterEncoding())); } @Override public ServletOutputStream getOutputStream() throws IOException { return new ServletOutputStream() { @Override public void write(int b) throws IOException { buffer.write(b); } }; } }; chain.doFilter(request, hsrw); byte[] gzipData=gzip(buffer.toByteArray()); resp.addHeader("Content-Encoding", "gzip"); resp.setContentLength(gzipData.length); ServletOutputStream output=response.getOutputStream(); output.write(gzipData); output.flush(); } else { chain.doFilter(request, response); } } // 用 GZIP 压缩字节数组 private byte[] gzip(byte[] data) { ByteArrayOutputStream byteOutput=new ByteArrayOutputStream(10240); GZIPOutputStream output=null; try { output=new GZIPOutputStream(byteOutput); output.write(data); } catch (IOException e) { } finally { try { output.close(); } catch (IOException e) { } } return byteOutput.toByteArray(); } …… }
如果你觉得本篇还不错,请点赞关注!
文字由黑码教主创作,配图源于网络,版权归原作者所有,如有侵权联系删除!
你有更好的网站性能优化方案吗?
欢迎留言分享。
*请认真填写需求信息,我们会在24小时内与您取得联系。