请问数据库jeojson显示地图页面 里的图片 JS输出到HTML页面怎么实现 懒加载

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&最新更新&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&-
在面试的时候有面试官问我,懒加载这个插件你有没有想到如何去优化?又间接问我函数节流的问题,嘿嘿,今天就更新下这个插件,顺便应用下函数节流(throttle),先直接上下代码,含解析
* 函数功能:函数节流
需要调用的函数
函数需要延迟处理的时间
* mustRunDelay
超过该时间,函数一定会执行
var throttle = function (fn, delay, mustRunDelay) {
//使用闭包存储timer
//闭包返回的函数
return function (val) {
var args = arguments, t_curr = +new Date();
//使用+new Date() 将字符串转换成数字
clearTimeout(timer);
if (!t_start) {
// 使用!t_start 如果t_start=undefined或者null 则为true
t_start = t_
if (t_curr - t_start &= mustRunDelay) {
fn.apply(null, args);
t_start = t_
timer = setTimeout(function () {
fn.apply(null, args);
}, delay);
/*使用方法*/
var throttle1 = throttle(fn, 500, 4000);
//在该需要调用的函数内部调用此函数
throttle1(val); //此处传人的参数为以上fn需要传人的参数
至于函数节流具体的好处,常用的场景,以下文章说得非常清楚,我就不再说啦~
好文推荐:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&华丽的分割线&&&&&&&&&&&&&&&&&&&&&&&&&&&&
很多网站都会用到&图片懒加载&这种方式对网站进行优化,即延迟加载图片或符合某些条件才开始加载图片。于是心血来潮,决定自己手动写一下&图片懒加载&插件。
使用这个技术有什么显著的优点?
比如一个页面中有很多图片,如淘宝首页等等,一个页面有100多的图片,如果一上来就发送这么多请求,页面加载就会很漫长,如果js文件都放在了文档的底部,恰巧页面的头部又依赖这个js文件,那就不好办了。用户感觉这个页面就会很卡。
懒加载原理:浏览器会自动对页面中的img标签的src属性发送请求并下载图片。通过动态改变img的src属性实现。
当访问一个页面的时候,先把img元素或是其他元素的背景图片路径替换成loading图片地址(这样就只需请求一次)
等到一定条件(这里是页面滚动到一定区域),用实际存放img地址的laze-load属性的值去替换src属性,即可实现'懒加载'。
//即使img的src值为空,浏览器也会对服务器发送请求。所以平时做项目的时候,如果img没有用到src,就不要出现src这个属性&
先上三个重要的知识点
1.获取屏幕可视窗口大小:
document.documentElement.clientHeight 标准浏览器及低版本IE标准模式
document.body.clientHeight 低版本混杂模式
2.元素相对于文档document顶部
element.offsetTop
3.滚动条滚动的距离
document.documentElement.scrollTop & 兼容ie低版本的标准模式&
document.body.scrollTop 兼容混杂模式;
滚动加载:当图片出现在可视区域时,动态加载该图片。
原理:当图片元素顶部是否在可视区域内,(图片相对于文档document顶部-滚动条滚动的距离)& 可视窗口大小,改变该img的src属性
实现原理:
1.首先从所有相关元素中找出需要延时加载的元素,放在element_obj数组中。
function initElementMap() {
var el = document.getElementsByTagName('img');
for (var j = 0, len2 = el. j & len2; j++) {
//判断当前的img是否加载过了,或者有lazy_src标志
if (typeof (el[j].getAttribute("lazy_src"))) {
element_obj.push(el[j]);
download_count++;
2.判断数组中的img对象,若满足条件,则改变src属性
1 function lazy() {
if (!download_count) return;
var innerHeight = getViewport();
for (var i = 0, len = element_obj. i & i++) {
5 //得到图片相对document的距上距离
var t_index = getElementViewTop(element_obj[i]);
if (t_index - getScrollTop() & innerHeight) {
element_obj[i].src = element_obj[i].getAttribute("lazy-src");
delete element_obj[i];
download_count--;
3.滚动的时候触发事件,1000毫秒后执行lazy()方法。
1 window.onscroll = window.onload = function () {
setTimeout(function () {
整部分代码位于闭包自执行函数中。相应的方法放在init中。
1 var lazyLoad = (function () {
function init() {
initElementMap();
init: init
&使用格式 :src填默认loading图片地址,真实的图片地址填在lazy-src属性里,切记需指定宽高。在外部调用 &lazyLoad.init();
&全部的代码以及例子已经上传到github上了,地址是:,欢迎star
阅读(...) 评论()-----不积跬步,无以至千里-----
HTML常见问题总结
本章节是的参考答案。 欢迎提出 PR 进行建议和指正!
DOCTYPE有什么用?
DOCTYPE是“document type”的缩写。它是 HTML 中用来区分标准模式和的声明,用来告知浏览器使用标准模式渲染页面。
从中获得的启发:在页面开始处添加&!DOCTYPE html&即可。
如何提供包含多种语言内容的页面?
这个问题有点问得含糊其辞,我认为这是在询问最常见的情况:如何提供包含多种语言内容的页面,并保证页面内容语言的一致性。
当客户端向服务器发送 HTTP 请求时,通常会发送有关语言首选项的信息,比如使用Accept-Language请求头。如果替换语言存在,服务器可以利用该信息返回与之相匹配的 HTML 文档。返回的 HTML 文档还应在&html&标签中声明lang属性,比如&html lang="en"&...&/html&
在后台中,HTML 将包含i18n占位符和待以替换的内容,这些按照不同语言,以 YML 或 JSON 格式存储。然后,服务器将动态生成指定语言内容的 HTML 页面。整个过程通常需要借助后台框架实现。
在设计开发多语言网站时,需要留心哪些事情?
在 HTML 中使用lang属性。
引导用户切换到自己的母语——让用户能够轻松地切换到自己的国家或语言,而不用麻烦。
在图片中展示文本会阻碍网站规模增长——把文本放在图片中展示,仍然是一种非常流行的方式。这样做可以在所有终端上,都能显示出美观的非系统字体。然而,为了翻译图片中的文本,需要为每种语言单独创建对应的图片,这种做法很容易在图片数量不断增长的过程中失控。
限制词语或句子的长度——网页内容在使用其他语言表述时,文字长度会发生变化。设计时,需要警惕文字长度溢出布局的问题,最好不要使用受文字长度影响较大的设计。比如标题、标签、按钮的设计,往往很受文字长度影响,这些设计中的文字与正文或评论部分不同,一般不可以自由换行。
注意颜色的使用——颜色在不同的语言和文化中,意义和感受是不同的。设计时应该使用恰当的颜色。
日期和货币的格式化——日期在不同的国家和地区,会以不同的方式显示。比如美国的日期格式是“May 31, 2012”,而在欧洲部分地区,日期格式是“31 May 2012”。
不要使用连接的翻译字符串——不要做类似这样的事情,比如“今天的日期是”+具体日期。这样做可能会打乱其他语言的语序。替代方案是,为每种语言编写带变量替换的模版字符串。请看下面两个分别用英语和中文表示的句子:I will travel on {% date %}和{% date %} 我会出发。可以看到,语言的语法规则不同,变量的位置是不同的。
注意语言阅读的方向——在英语中,文字是从左向右阅读的;而在传统日语中,文字是从右向左阅读的。
什么是data-属性?
在 JavaScript 框架变得流行之前,前端开发者经常使用data-属性,把额外数据存储在 DOM 自身中。当时没有其他 Hack 手段(比如使用非标准属性或 DOM 上额外属性)。这样做是为了将自定义数据存储到页面或应用中,对此没有其他更适当的属性或元素。
而现在,不鼓励使用data-属性。原因之一是,用户可以通过在浏览器中利用检查元素,轻松地修改属性值,借此修改数据。数据模型最好存储在 JavaScript 本身中,并利用框架提供的数据绑定,使之与 DOM 保持更新。
*-attributes
将 HTML5 看作成开放的网络平台,什么是 HTML5 的基本构件(building block)?
语义 - 提供更准确地描述内容。
连接 - 提供新的方式与服务器通信。
离线和存储 - 允许网页在本地存储数据并有效地离线运行。
多媒体 - 在 Open Web 中,视频和音频被视为一等公民(first-class citizens)。
2D/3D 图形和特效 - 提供更多种演示选项。
性能和集成 - 提供更快的访问速度和性能更好的计算机硬件。
设备访问 - 允许使用各种输入、输出设备。
外观 - 可以开发丰富的主题。
请描述cookie、sessionStorage和localStorage的区别。
上面提到的技术名词,都是在客户端以键值对存储的存储机制,并且只能将值存储为字符串。
localStorage
sessionStorage
由谁初始化
客户端或服务器,服务器可以使用Set-Cookie请求头。
在当前浏览器会话(browser sessions)中是否保持不变
取决于是否设置了过期时间
是否与域名(domain)相关联
是否随着每个 HTTP 请求发送给服务器
是,Cookies 会通过Cookie请求头,自动发送给服务器
容量(每个域名)
请描述&script&、&script async&和&script defer&的区别。
&script& - HTML 解析中断,脚本被提取并立即执行。执行结束后,HTML 解析继续。
&script async& - 脚本的提取、执行的过程与HTML解析过程并行,脚本执行完毕可能在HTML解析完毕之前。当脚本与页面上其他脚本独立时,可以使用async,比如用作页面统计分析。
&script defer& - 脚本仅提取过程与HTML解析过程并行,脚本的执行将在HTML解析完毕后进行。如果有多个含defer的脚本,脚本的执行顺序将按照在 document 中出现的位置,从上到下顺序执行。
注意:没有src属性的脚本,async和defer属性会被忽略。
把&link&放在&head&中
把&link&标签放在&head&&/head&之间是规范要求的内容。此外,这种做法可以让页面逐步呈现,提高了用户体验。将样式表放在文档底部附近,会使许多浏览器(包括Internet Explorer)不能逐步呈现页面。一些浏览器会阻止渲染,以避免在页面样式发生变化时,重新绘制页面中的元素。这种做法可以防止呈现给用户空白的页面或没有样式的内容。
把&script&标签恰好放在&/body&之前
脚本在下载和执行期间会阻止HTML解析。把&script&标签放在底部,保证HTML首先完成解析,将页面尽早呈现给用户。
例外情况是当你的脚本里包含document.write()时。但是现在,document.write()不推荐使用。同时,将&script&标签放在底部,意味着浏览器不能开始下载脚本,直到整个文档(document)被解析。也许,对此比较好的做法是,&script&使用defer属性,放在&head&中。
什么是渐进式渲染(progressive rendering)?
渐进式渲染是用于提高网页性能(尤其是提高用户感知的加载速度),以尽快呈现页面的技术。
在以前互联网带宽较小的时期,这种技术更为普遍。如今,移动终端的盛行,而移动网络往往不稳定,渐进式渲染在现代前端开发中仍然有用武之地。
一些举例:
图片懒加载——页面上的图片不会一次性全部加载。当用户滚动页面到图片部分时,JavaScript将加载并显示图像。
确定显示内容的优先级(分层次渲染)——为了尽快将页面呈现给用户,页面只包含基本的最少量的CSS、脚本和内容,然后可以使用延迟加载脚本或监听DOMContentLoaded/load事件加载其他资源和内容。
异步加载HTML片段——当页面通过后台渲染时,把HTML拆分,通过异步请求,分块发送给浏览器。更多相关细节可以在找到。
为什么在&img&标签中使用srcset属性?请描述浏览器遇到该属性后的处理过程。
因为需要设计响应式图片。我们可以使用两个新的属性——srcset 和 sizes——来提供更多额外的资源图像和提示,帮助浏览器选择正确的一个资源。
srcset 定义了我们允许浏览器选择的图像集,以及每个图像的大小。
sizes 定义了一组媒体条件(例如屏幕宽度)并且指明当某些媒体条件为真时,什么样的图片尺寸是最佳选择。
所以,有了这些属性,浏览器会:
查看设备宽度
检查sizes列表中哪个媒体条件是第一个为真
查看给予该媒体查询的槽大小
加载srcset列表中引用的最接近所选的槽大小的图像
你有过使用不同模版语言的经历吗?
有过,比如 Pug (以前叫 Jade)、 ERB、 Slim、 Handlebars、 Jinja、 Liquid 等等。在我看来,这些模版语言大多是相似的,都提供了用于展示数据的内容替换和过滤器的功能。大部分模版引擎都支持自定义过滤器,以展示自定义格式的内容。
HTML 常见问题
html中一些常见问题的解决方法
HTML和CSS常见问题总结
面试题汇总(HTML篇)
没有更多推荐了,jQuery+ajax实现滚动到页面底部自动加载图文列表效果(类似图片懒加载)
转载 &更新时间:日 10:55:24 & 作者:smartsmile2012
这篇文章主要介绍了jQuery+ajax实现滚动到页面底部自动加载图文列表效果,模拟图片懒加载功能,涉及jQuery的ajax与asp.net交互动态显示页面内容的相关技巧,需要的朋友可以参考下
本文实例讲述了jQuery+ajax实现滚动到页面底部自动加载图文列表效果。分享给大家供大家参考,具体如下:
&!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&
&html xmlns="http://www.w3.org/1999/xhtml"&
&title&滚动到页面顶部加载&/title&
&script src="js/jquery-1.11.1.min.js" type="text/javascript"&&/script&
&script src="js/endlesspage.js" type="text/javascript"&&/script&
&style type="text/css"&
.mainDiv {
width: 800
border: solid 1px #f00;
padding: 10
width: 600
height: 50
border: solid 1px #00ff90;
font-size: 12
margin: 10
font-size: 16
line-height: 20
.content {
line-height: 14
&h1&滚动测试&/h1&
&div class="mainDiv"&
&!--&div class="item"&
&div class="title"&title&/div&
&div class="content"&content content content content content content content&/div&
&div class="loaddiv"&
&img src="images/loading.gif" /&
&a href="javascript:void(0);" id="btn_Page" class="alink"&查看更多&&&&/a&
/*endlesspage.js*/
var gPageSize = 10;
var i = 1; //设置当前页数,全局变量
$(function () {
//根据页数读取数据
function getData(pagenumber) {
i++; //页码自动增加,保证下次调用时为新的一页。
$.get("/ajax/Handler.ashx", { pagesize: gPageSize, pagenumber: pagenumber }, function (data) {
if (data.length & 0) {
var jsonObj = JSON.parse(data);
insertDiv(jsonObj);
type: "post",
url: "/ajax/Handler.ashx",
data: { pagesize: gPageSize, pagenumber: pagenumber },
dataType: "json",
success: function (data) {
$(".loaddiv").hide();
if (data.length & 0) {
var jsonObj = JSON.parse(data);
insertDiv(jsonObj);
beforeSend: function () {
$(".loaddiv").show();
error: function () {
$(".loaddiv").hide();
//初始化加载第一页数据
getData(1);
//生成数据html,append到div中
function insertDiv(json) {
var $mainDiv = $(".mainDiv");
var html = '';
for (var i = 0; i & json. i++) {
html += '&div class="item"&';
html += ' &div class="title"&' + json[i].rowId + '
' + json[i].D_Name + '&/div&';
html += ' &div class="content"&' + json[i].D_Name + '
' + json[i].D_Password + '&/div&';
html += '&/div&';
$mainDiv.append(html);
//==============核心代码=============
var winH = $(window).height(); //页面可视区域高度
var scrollHandler = function () {
var pageH = $(document.body).height();
var scrollT = $(window).scrollTop(); //滚动条top
var aa = (pageH - winH - scrollT) / winH;
if (aa & 0.02) {//0.02是个参数
if (i % 10 === 0) {//每10页做一次停顿!
getData(i);
$(window).unbind('scroll');
$("#btn_Page").show();
getData(i);
$("#btn_Page").hide();
//定义鼠标滚动事件
$(window).scroll(scrollHandler);
//==============核心代码=============
//继续加载按钮事件
$("#btn_Page").click(function () {
getData(i);
$(window).scroll(scrollHandler);
&%@ WebHandler Language="C#" Class="Handler" %&
using System.W
using System.D
using MSCL;
using Newtonsoft.J
public class Handler : IHttpHandler {
public void ProcessRequest(HttpContext context)
//核心处理程序
string pageSize = context.Request["pagesize"];
string pageIndex = context.Request["pagenumber"];
if (string.IsNullOrEmpty(pageSize) || string.IsNullOrEmpty(pageIndex))
context.Response.Write("");
//请结合实际自行取分页数据,可调用分页存储过程
MSCL.PageHelper p = new PageHelper();
p.CurrentPageIndex = Convert.ToInt32(pageIndex);
p.FieldsName = "*";
p.KeyField = "d_id";
p.SortName = "d_id asc";
p.TableName = "testtable";
p.EndCondition = "count(*)";
p.PageSize = Convert.ToInt32(pageSize);
DataTable dt = p.QueryPagination();
string json = JsonConvert.SerializeObject(dt, Formatting.Indented);
context.Response.Write(json);
public bool IsReusable {
"rowId": 1,
"D_Id": 1,
"D_Name": "名称1",
"D_Password": "密码测试1",
"D_Else": "其他1"
"rowId": 2,
"D_Id": 2,
"D_Name": "名称2",
"D_Password": "密码测试2",
"D_Else": "其他2"
"rowId": 3,
"D_Id": 3,
"D_Name": "名称3",
"D_Password": "密码测试3",
"D_Else": "其他3"
"rowId": 4,
"D_Id": 4,
"D_Name": "名称4",
"D_Password": "密码测试4",
"D_Else": "其他4"
"rowId": 5,
"D_Id": 5,
"D_Name": "名称5",
"D_Password": "密码测试5",
"D_Else": "其他5"
"rowId": 6,
"D_Id": 6,
"D_Name": "名称6",
"D_Password": "密码测试6",
"D_Else": "其他6"
"rowId": 7,
"D_Id": 7,
"D_Name": "名称7",
"D_Password": "密码测试7",
"D_Else": "其他7"
"rowId": 8,
"D_Id": 8,
"D_Name": "名称8",
"D_Password": "密码测试8",
"D_Else": "其他8"
"rowId": 9,
"D_Id": 9,
"D_Name": "名称9",
"D_Password": "密码测试9",
"D_Else": "其他9"
"rowId": 10,
"D_Id": 10,
"D_Name": "名称10",
"D_Password": "密码测试10",
"D_Else": "其他10"
PS:这里还涉及json格式数据的交互操作,关于json数据操作小编推荐几个本站的在线工具供大家参考,相信在以后的开发中可以派上用场:
在线JSON代码检验、检验、美化、格式化工具:
在线XML/JSON互相转换工具:
json代码在线格式化/美化/压缩/编辑/转换工具:
C语言风格/HTML/CSS/json代码格式化美化工具:
更多关于jQuery相关内容感兴趣的读者可查看本站专题:《》、《》、《》、《》、《》、《》、《》及《》
希望本文所述对大家jQuery程序设计有所帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具JSON最佳实践
JSON是一种文本方式展示结构化数据的方式,从产生的时候开始就由于其简单好用、跨平台,特别适合HTTP下数据的传输(例如现在很流行的REST)而被广泛使用。
1、JSON是什么
JSON起源于1999年的(即15.12章节描述了格式与解析),后来2003年作为一个数据格式(很囧的序号有不有?)发布。
2006年,作为发布,这时规范增加到18页,去掉没用的部分,十页不到。
JSON的应用很广泛,这里有超过100种语言下的JSON库:。
更多的可以参考这里,。
2、优缺点、标准与schema
2.1 结构与类型
这估计是最简单标准规范之一:
- 只有两种结构:对象内的键值对集合结构和数组,对象用{}表示、内部是”key”:”value”,数组用[]表示,不同值用逗号分开
- 基本数值有7个: false / null / true / object / array / number / string
- 再加上结构可以嵌套,进而可以用来表达复杂的数据
- 一个简单实例:
"Image": {
"Height": 600,
"View from 15th Floor",
"Thumbnail": {
"http://www.example.com/image/",
"Height": 125,
"IDs": [116, 943, 234, 38793]
基于纯文本,所以对于人类阅读是很友好的。规范简单,所以容易处理,开箱即用,特别是JS类的ECMA脚本里是内建支持的,可以直接作为对象使用。平台无关性,因为类型和结构都是平台无关的,而且好处理,容易实现不同语言的处理类库,可以作为多个不同异构系统之间的数据传输格式协议,特别是在HTTP/REST下的数据格式。2.3 缺点
缺点也很明显:
- 性能一般,文本表示的数据一般来说比二进制大得多,在数据传输上和解析处理上都要更影响性能。
- 缺乏schema,跟同是文本数据格式的XML比,在类型的严格性和丰富性上要差很多。XML可以借由XSD或DTD来定义复杂的格式,并由此来验证XML文档是否符合格式要求,甚至进一步的,可以基于XSD来生成具体语言的操作代码,例如apache xmlbeans。并且这些工具组合到一起,形成一套庞大的生态,例如基于XML可以实现SOAP和WSDL,一系列的ws-*规范。但是我们也可以看到JSON在缺乏规范的情况下,实际上有更大一些的灵活性,特别是近年来REST的快速发展,已经有一些schema相关的发展(例如,,
),也有类似于WSDL的出现。
3. 常用技术与工具
3.1 相关技术以及与XML的关系
使用JSON实现RPC(类似XML-RPC):使用JSON实现path查询操作(类似XML-PATH):在线查询工具:例如上面的示例json,用表达式$.Image.IDs[:1]查询,得到116:
我们看到JSON与XML是如此之像,实际上这两个格式可以看做一个是学院排,一个是平民派。一个对象从POJO转换成XML与JSON的过程,基本是一致的(绝大部分工作可以复用,以后有机会再详细聊这个过程),10年前我自己也做过一个基于XML的RPC(,貌似已经被墙),里面实现了和dotnet、的XML序列化与反序列化,同时作为一个副产品,实现了JSON序列化。
后来thoughtsworks公司出品的XStream就是同时做了XML与JSON的序列化。而创建Jackson库的组织本来叫fasterxml,就是处理xml的。当然从这个角度来看,Fastjson库,稍微改改也是一个高性能的XML序列化库。
只是XML有着更严格的结构,更丰富的工具生态,拿查询与操作来说,XML还有XQuery、XLST等工具。处理方式上也有DOM方式与SAX流模式,这两个绝然不同的技术。
单从性能来考虑,XML更是有这种解决了DOM消耗太大内存与SAX只能单向每个节点读一次不能随机读的缺点的高性能处理方式。
3.2 Java类库
格式化工具:chrome插件:在线Mock: 其他Mock:可以支持,SwaggerUI也可以,也可以。
4. JSON编码指南
4.1 Google JSON风格指南
遵循好的设计与编码风格,能提前解决80%的问题:
- 英文版:
- 中文版:
简单摘录如下:
- 属性名和值都是用双引号,不要把注释写到对象里面,对象数据要简洁
- 不要随意结构化分组对象,推荐是用扁平化方式,层次不要太复杂
- 命名方式要有意义,比如单复数表示
- 驼峰式命名,遵循Bean规范
- 使用版本来控制变更冲突
- 对于一些关键字,不要拿来做key
- 如果一个属性是可选的或者包含空值或null值,考虑从JSON中去掉该属性,除非它的存在有很强的语义原因
- 序列化枚举类型时,使用name而不是value
- 日期要用标准格式处理
- 设计好通用的分页参数
- 设计好异常处理
4.2 使用JSON实现API
与Google JSON风格指南有很多可以相互参照之处。
是数据交互规范,用以定义客户端如何获取与修改资源,以及服务器如何响应对应请求。
JSON API设计用来最小化请求的数量,以及客户端与服务器间传输的数据量。在高效实现的同时,无需牺牲可读性、灵活性和可发现性。
- resteasy
6. SwaggerUI实现API文档管理与在线测试
7. JSON使用场景分析
JSON的使用,依据不同用途,有几个典型的场景:
1. 内部后台系统之间的数据传输,此种情况下基于HTTP的JSON格式其实没有优势。
2. 前后台之间的API调用,典型的是前端作为/VUE//ExtJS等框架做的,前后端使用JSON交互。
- 此时可以使用类似Dubbox之类的框架,或者原始一些SpringMVC的Controller上直接@ResponseBody或@RestController也可以。
- 强烈建议在Dubbox之类的rest之上再加一个Nginx转发,这样一些策略的控制,比如同源的控制、简单的缓存策略、安全策略等都可以放到Nginx上来做,也利于多个机器时的负载均衡。
- 建议使用swaggerUI来自动实现API文档和在线。功能很强大,操作简单,而且可以mock接口,在后台没有做好之前,前台就可以先开发了。
- 可以使用RestUnit或SoapUI来实现自动化测试与压力测试。
提供给第三方的开发接口API
基本同上,可以参考Google JSON风格指南与JSON API章节。8.JSON的一些经验
最近在协助处理一些Fastjson的bug问题,发现最常见的其实是大家使用的不规范性,这样碰到各种坑的可能性就很大。根据我平时使用的经验,以及总结大家常见的问题,归纳如下:
7.1 遵循Java Beans规范与JSON规范
实践告诉我们:遵循beans规范和JSON规范的方式,能减少大部分的问题,比如正确实现setter、getter,用别名就加annotation。注意基本类型的匹配转换,比如在fastjson的issue见到试图把”{“a”:{}}”中的a转换成List的。
7.2 使用正常的key
尽量不要使用数字等字符开头的key,尽量使用符合Java的class或property命名规范的key,这样会减少不必要的冲突。在jsonpath或js里,a.1可能会被解释成a[1]或a[“1”],这些都会带来不必要的麻烦。
7.3 关于日期处理
这一点前面的Google JSON风格指南里也提到了,尽量使用标准的日期格式。或者序列化和反序列化里都是用同样的datePattern格式。
7.4 关于自定义序列化与反序列化(包括过滤器)
对于新手来说,自定义序列化是一切罪恶的根源。
尽量不要使用自定义序列化,除非万不得已,优先考虑使用注解过滤,别名等方式,甚至是重新建一个VO类来组装实际需要的属性。使用自定义序列化时一切要小心,因为这样会导致两个问题:
- 改变了pojo &-& jsonstring 的自然对应关系,从而不利于阅读代码和排查问题,你改变的关系无法简单的从bean和json上看出来了;
- 反序列化可能出错,因为对应不上原来的属性了。
如果只是序列化发出去(响应)的是JSON数据、传过来(请求)的数据格式跟JSON无关或者是标准的,此时自定义序列化就无所谓了,反正是要接收方来处理。
7.5 JSONObject的使用
JSONObject是JSON字符串与pojo对象转换过程中的中间表达类型,实现了Map接口,可以看做是一个模拟JSON对象键值对再加上多层嵌套的数据集合,对象的每一个基本类型属性是map里的一个key-value,一个非基本类型属性是一个嵌套的JSONObject对象(key是属性名称,value是表示这个属性值的对象的JSONObject)。如果以前用过apache beanutils里的DynamicBean之类的,就知道JSONObject也是一种动态描述Bean的实现,相当于是拆解了Bean本身的结构与数据。这时候由于JSONObject里可能会没有记录全部的Bean类型数据,例如泛型的具体子类型之类的元数据,如果JSONObject与正常的POJO混用,出现问题的概率较高。
下列方式尽量不要使用:
public class TestBean{
@Setter @Getter
private TestBean1 testBean1;
@Setter @Getter
private JSONObject testBean2; // 尽量不要在POJO里用JSONObject
应该从设计上改为都用POJO比较合适:
public class TestBean{
@Setter @Getter
private TestBean1 testBean1;
@Setter @Getter
private TestBean2 testBean2;; // 使用POJO
}相对的,写一些临时性的测试代码,demo代码,可以直接全部用JSONObject先快速run起来。
同理,jsonstring中嵌套jsonstring也尽量不要用,例如:
"name":"zhangsan",
"score":"{\"math\":78,\"history\":82}"
应该改为全部都是JSON风格的结构:
"name":"zhangsan",
"math":78,
"history":82
另外,对于jsonstring转POJO(或POJO转jsonstring),尽量使用直接转的方式,而不是先转成JSONObject过渡的方式。特别是对于Fastjson,由于性能优化的考虑,这两个执行的代码是不一样的,可能导致不一样的结果。
String jsonstring = "{\"a\":12}";
// 不推荐这种方式
// 除非这里需要对jsonObject做一些简单处理
JSONObject jsonObject = JSON.parseObject(jsonstring);
A a = jsonObject.toJavaObject(A.class);
// 推荐方式
A a = JSON.parseObject(jsonstring, A.class);7.6 Hibernate相关问题
懒加载与级联,可能导致出现问题,例如,建议封装一层VO类型来序列化。使用VO类还有一个好处,就是可以去掉一些没用的属性,减少数据量,同时可以加上额外的属性。
7.7 深层嵌套与泛型问题
尽量不要在使用过多的层次嵌套的同时使用泛型(List、Map等),可能导致类型丢失,而且问题比较难查。
7.8 抽象类型与子类型问题
尽量不要在同一个Bean的层次结构里使用多个子类型对象,可能导致类型丢失,而且问题比较难查。当然我们可以通过代码显示的传递各种正确的类型,但是这样做引入了更多的不确定性。良好的做法应该是一开始设计时就避免出现这些问题。
7.9 避免循环引用
尽量避免循环引用,这个虽然可以通过序列化特性禁掉,但是如果能避免则避免。
7.10 注意编码和不可见字符(特别是二进制数据流)
对于InputStream、OutputStream的处理,有时候会报一些奇怪的错误,not match之类的,这时候也许我们看日志里的json字符串可能很正常,但就是出错。
这时可能就是编码的问题了,可能是导致字符错乱,也可能是因为UTF-8文件的BOM头,这些潜在的问题可能在二进制数据转文本的时候,因为一些不可见字符无法显示,导致日志看起来只有正常字符而是正确的,问题很难排查。
处理办法就是按二进制的方式把Stream保存起来,然后按hex方式查看,看看是否有多余字符,或者其他错误。
8.fastjson的最佳实践
8.1 Maven下引入Fastjson
pom.xml文件里添加依赖即可:
&dependency&
&groupId&com.alibaba&/groupId&
&artifactId&fastjson&/artifactId&
&version&1.2.32&/version&
&/dependency&8.2 序列化一个对象成JSON字符串
User user = new User();
user.setName("校长");
user.setAge(3);
user.setSalary(new BigDecimal("23"));
String jsonString = JSON.toJSONString(user);
System.out.println(jsonString);
// 输出 {"age":3,"name":"校长","old":false,"salary":23}8.3 反序列化一个JSON字符串成Java对象
String jsonString = "{\"age\":3,\"birthdate\":2,\"name\":\"校长\",\"old\":true,\"salary\":23}";
User u = JSON.parseObject(jsonString ,User.class);
System.out.println(u.getName());
// 输出 校长
String jsonStringArray = "[{\"age\":3,\"birthdate\":2,\"name\":\"校长\",\"old\":true,\"salary\":23}]";
List&User& userList = JSON.parseArray(jsonStringArray, User.class);
System.out.println(userList.size());
// 输出 18.4 日期格式处理
Fastjson能识别下面这么多种日期格式的字符串:
private final static String
defaultPatttern
= "yyyy-MM-dd HH:mm:ss";
private final static DateTimeFormatter defaultFormatter
= DateTimeFormatter.ofPattern(defaultPatttern);
private final static DateTimeFormatter formatter_dt19_tw
= DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
private final static DateTimeFormatter formatter_dt19_cn
= DateTimeFormatter.ofPattern("yyyy年M月d日 HH:mm:ss");
private final static DateTimeFormatter formatter_dt19_cn_1
= DateTimeFormatter.ofPattern("yyyy年M月d日 H时m分s秒");
private final static DateTimeFormatter formatter_dt19_kr
= DateTimeFormatter.ofPattern("yyyy?M?d? HH:mm:ss");
private final static DateTimeFormatter formatter_dt19_us
= DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss");
private final static DateTimeFormatter formatter_dt19_eur = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
private final static DateTimeFormatter formatter_dt19_de
= DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");
private final static DateTimeFormatter formatter_dt19_in
= DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
private final static DateTimeFormatter formatter_d8
= DateTimeFormatter.ofPattern("yyyyMMdd");
private final static DateTimeFormatter formatter_d10_tw
= DateTimeFormatter.ofPattern("yyyy/MM/dd");
private final static DateTimeFormatter formatter_d10_cn
= DateTimeFormatter.ofPattern("yyyy年M月d日");
private final static DateTimeFormatter formatter_d10_kr
= DateTimeFormatter.ofPattern("yyyy?M?d?");
private final static DateTimeFormatter formatter_d10_us
= DateTimeFormatter.ofPattern("MM/dd/yyyy");
private final static DateTimeFormatter formatter_d10_eur
= DateTimeFormatter.ofPattern("dd/MM/yyyy");
private final static DateTimeFormatter formatter_d10_de
= DateTimeFormatter.ofPattern("dd.MM.yyyy");
private final static DateTimeFormatter formatter_d10_in
= DateTimeFormatter.ofPattern("dd-MM-yyyy");
private final static DateTimeFormatter ISO_FIXED_FORMAT =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault());
private final static String formatter_iso8601_pattern
= "yyyy-MM-dd'T'HH:mm:ss";
private final static DateTimeFormatter formatter_iso8601
= DateTimeFormatter.ofPattern(formatter_iso8601_pattern);
默认序列化Date输出使用”yyyy-MM-dd HH:mm:ss”格式,可以用UseISO8601DateFormat特性换成”yyyy-MM-dd’T’HH:mm:ss”格式。JSON.defaultTimeZone = TimeZone.getTimeZone("Asia/Shanghai");
JSON.defaultLocale = Locale.US;
public static class Model {
@JSONField(format = "MMM dd, yyyy h:mm:ss aa")
private java.util.D
public java.util.Date getDate() {
public void setDate(java.util.Date date) {
this.date =
@JSONField(format = "MMM-dd-yyyy h:mm:ss aa")
public java.sql.Date date2;
}8.5 常见序列化特性的使用
Fastjson的序列化特性定义在枚举类com\alibaba\fastjson\serializer\SerializerFeature.java中,目前正好有30项。
可以通过设置多个特性到FastjsonConfig中全局使用,也可以在某个具体的JSON.writeJSONString时作为参数使用。
1. QuoteFieldNames, //key使用引号
2. UseSingleQuotes, //使用单引号
3. WriteMapNullValue, //输出Map的null值
4. WriteEnumUsingToString, //枚举属性输出toString的结果
5. WriteEnumUsingName, //枚举数据输出name
6. UseISO8601DateFormat, //使用日期格式
7. WriteNullListAsEmpty, //List为空则输出[]
8. WriteNullStringAsEmpty, //String为空则输出””
9. WriteNullNumberAsZero, //Number类型为空则输出0
10. WriteNullBooleanAsFalse, //Boolean类型为空则输出false
11. SkipTransientField,
12. SortField, //排序字段
13. WriteTabAsSpecial,
14. PrettyFormat, // 格式化JSON缩进
15. WriteClassName, // 输出类名
16. DisableCircularReferenceDetect, // 禁止循环引用
17. WriteSlashAsSpecial, // 对斜杠’/’进行转义
18. BrowserCompatible,
19. WriteDateUseDateFormat, // 全局修改日期格式,默认为false。JSON.DEFFAULT_DATE_FORMAT = “yyyy-MM-dd”;JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);
20. NotWriteRootClassName,
21. DisableCheckSpecialChar,
22. BeanToArray,
23. WriteNonStringKeyAsString,
24. NotWriteDefaultValue,
25. BrowserSecure,
26. IgnoreNonFieldGetter,
27. WriteNonStringValueAsString,
28. IgnoreErrorGetter,
29. WriteBigDecimalAsPlain,
30. MapSortField
使用示例如下(可以):
Word word = new Word();
word.setA("a");
word.setB(2);
word.setC(true);
word.setD("d");
word.setE("");
word.setF(null);
word.setDate(new Date());
System.out.println(JSON.toJSONString(word));
System.out.println(JSON.toJSONString(word, SerializerFeature.PrettyFormat,
SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty,
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteNullListAsEmpty));8.6 Annotation注解的使用
1) JSONField
可以配置在属性(setter、getter)和字段(必须是public field)上。
详情参见此处:
package com.alibaba.fastjson.
public @interface JSONField {
// 配置序列化和反序列化的顺序,1.1.42版本之后才支持
int ordinal() default 0;
// 指定字段的名称
String name() default "";
// 指定字段的格式,对日期格式有用
String format() default "";
// 是否序列化
boolean serialize()
// 是否反序列化
boolean deserialize()
@JSONField(name="ID")
public int getId() {}
// 配置date序列化和反序列使用yyyyMMdd日期格式
@JSONField(format="yyyyMMdd")
public Date date1;
// 不序列化
@JSONField(serialize=false)
public Date date2;
// 不反序列化
@JSONField(deserialize=false)
public Date date3;
// 按ordinal排序
@JSONField(ordinal = 2)
private int f1;
@JSONField(ordinal = 1)
private int f2;2) JSONType
自定义序列化:子类型处理:JSONType.alphabetic属性: fastjson缺省时会使用字母序序列化,如果你是希望按照java fields/getters的自然顺序序列化,可以配置JSONType.alphabetic,使用方法如下:@JSONType(alphabetic = false)
public static class B {
public int f2;
public int f1;
public int f0;
}8.7 自定义序列化与反序列化
自定义序列化
只需要2步:
1)实现ObjectSerializer
public class CharacterSerializer implements ObjectSerializer {
public void write(JSONSerializer serializer,
Object object,
Object fieldName,
Type fieldType,
int features) throws IOException {
SerializeWriter out = serializer.
Character value = (Character)
if (value == null) {
out.writeString("");
char c = value.charValue();
if (c == 0) {
out.writeString("\u0000");
out.writeString(value.toString());
}2)注册ObjectSerializer
SerializeConfig.getGlobalInstance().put(Character.class, new CharacterSerializer());11自定义反序列化只需要2步:
1)自定义实现ObjectDeserializer
public static enum OrderActionEnum {
FAIL(1), SUCC(0);
OrderActionEnum(int code){
this.code =
public static class Msg {
public OrderActionEnum actionE
public static class OrderActionEnumDeser implements ObjectDeserializer {
@SuppressWarnings("unchecked")
public &T& T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
Integer intValue = parser.parseObject(int.class);
if (intValue == 1) {
return (T) OrderActionEnum.FAIL;
} else if (intValue == 0) {
return (T) OrderActionEnum.SUCC;
throw new IllegalStateException();
public int getFastMatchToken() {
return JSONToken.LITERAL_INT;
}2)注册并使用ObjectDeserializer
ParserConfig.getGlobalInstance().putDeserializer(OrderActionEnum.class, new OrderActionEnumDeser());
Msg msg = JSON.parseObject("{\"actionEnum\":1,\"body\":\"A\"}", Msg.class);
Assert.assertEquals(msg.body, "A");
Assert.assertEquals(msg.actionEnum, OrderActionEnum.FAIL);
Msg msg = JSON.parseObject("{\"actionEnum\":0,\"body\":\"B\"}", Msg.class);
Assert.assertEquals(msg.body, "B");
Assert.assertEquals(msg.actionEnum, OrderActionEnum.SUCC);
8.8 自定义序列化之过滤器
全局的过滤器:JSON.toJSONString方法的参数中可以配置处理所有类型的SerializeFilter类级别过滤器:属性过滤器:多余字段处理器:定制反序列化:,可用于添加没有的字段标签过滤:自动识别嵌套对象子类型:8.9 与Spring MVC的配合使用
FastJson 提供了 MVC HttpMessageConverter的实现,将POJO输出为JSONP,支持跨域数据访问。
FastJsonpHttpMessageConverter4 for Spring MVC 4.2+:
&mvc:annotation-driven&
&mvc:message-converters&
class="com.alibaba.fastjson.support.spring.FastJsonpHttpMessageConverter4"&
&property name="supportedMediaTypes"&
&value&application/charset=UTF-8&/value&
&/property&
&/mvc:message-converters&
&/mvc:annotation-driven&
&mvc:default-servlet-handler /&
&bean id="fastJsonpResponseBodyAdvice" class="com.alibaba.fastjson.support.spring.FastJsonpResponseBodyAdvice"&
&constructor-arg&
&value&callback&/value&
&value&jsonp&/value&
&/constructor-arg&
8.10 与Spring Boot的集成使用
参见此处:
8.11 泛型处理
eReference
8.12jaxrs支持
FastJson 提供了JAX-RS Provider的实现
可用于在构建Restful服务时使用FastJson进行数据的Serialize and Deserialize
8.13 swagger支持
更多功能 todo list
9.Fastjson的设计说明
没有更多推荐了,

我要回帖

更多关于 html页面解析json数据 的文章

 

随机推荐