[转载]jQuery EasyUI 源代码分析之parser

mikel阅读(1266)

[转载]Jquery easyui 源代码分析之parser – 读码笔记 – 博客频道 – CSDN.NET.

parser模块是easyloader第一个加载的模块,它的主要作用,就是扫描页面上easyui开头的class标签,然后初始化成easyui控件。

 

	/**
	 * parser模块主要是解析页面中easyui的控件
	 */
	$.parser = {
		// 是否自动解析
		auto: true,

		// 可以被解析的控件
		plugins:['linkbutton','menu','menubutton','splitbutton','layout',
				 'tree','window','dialog','datagrid',
				 'combobox','combotree','numberbox','validatebox',
				 'calendar','datebox','panel','tabs','accordion'
		],

		// 解析函数
		parse: function(context){
			if ($.parser.auto){
				for(var i=0; i<$.parser.plugins.length; i++){
					(function(){
						// 控件名
						var name = $.parser.plugins[i];
						// 查找class为easyui-控件名的jq对象,例如,easyui-layout
						var r = $('.easyui-' + name, context);

						if (r.length){
							// 如果有这个对象,那么判断它有没有初始化函数
							if (r[name]){
								// 如果有直接调用
								r[name]();
							} else if (window.easyloader){
								// 如果没有用easyloader把模块的js文件载入进来,再调用
								easyloader.load(name, function(){
									r[name]();
								})
							}
						}
					})();
				}
			}
		}
	};

	// 调用parse方法,实际上easyloader中已经调用了,我估计这个是给不是easyloader加载时使用的
	$(function(){
		$.parser.parse();
	});
})(jQuery);

[转载]jQuery EasyUI 源代码分析之easyloader

mikel阅读(1144)

JQuery easyui是一个JavaScript UI 组件库,使用它可以快速开发企业级的业务系统。如果你正准备开发系统后台,可以选择JQuery easyui,也可以选择Ext JS。我个人的看法是,如果开发团队就两三个人,开发工期很短,就一两个月。那么选择jQuery easyui就对了,jQuery easyui源代码量不多,便于阅读和自行修改。而Ext JSy源代码太多,短时间很难看完,学习曲线也比较陡峭。如果人手充足,时间也富裕,可以考虑使用Ext JS来开发,毕竟Ext JS更强大,控件更多。
jQuery easyui是基于Jquery插件机制扩展的,所以如果你很熟悉Jquery,那么使用它开发会很简单。

Jquery easyui的源代码svn地址:http://jquery-easyui.googlecode.com/svn
easyloader模块是用来加载jquery easyui的js和css文件的,而且它可以分析模块的依赖关系,先加载依赖项。模块加载好了会调用parse模块来解析页面。把class是easyui开头的标签都转化成easyui的控件。

 

先看Demo1例子,再分析源代码。

  1. <!DOCTYPE HTML>  
  2. <html>  
  3. <head>  
  4. <meta http-equiv=“Content-Type” content=“text/html; charset=utf-8”>  
  5. <title>Demo1</title>  
  6. <script type=“text/JavaScript src=“jquery-easyui-1.2.3/jquery-1.4.4.min.js”></script>  
  7. <script type=“text/JavaScript src=“jquery-easyui-1.2.3/easyloader.js”></script>  
  8. </head>  
  9. <body>  
  10.     <div class=“easyui-panel” title=“Demo1” fit=“true” collapsible=“true” minimizable=“true” maximizable=“true” closable=“true” style=“width: 100%; height: 200px;” >  
  11.         easyloader会自动解析这个div,因为class属性中带有easyui开头的类!  
  12.     </div>  
  13. </body>  
  14. </html>  

 

还有一种正常加载方法,不使用easyuiloader来加载。

  1. <!DOCTYPE HTML>  
  2. <html>  
  3. <head>  
  4. <meta http-equiv=“Content-Type” content=“text/html; charset=utf-8”>  
  5. <title>Demo2</title>  
  6. <link rel=“stylesheet” type=“text/css” href=“jquery-easyui-1.2.3/themes/default/easyui.css”>  
  7. <link rel=“stylesheet” type=“text/css” href=“jquery-easyui-1.2.3/themes/icon.css”>  
  8. <script type=“text/javascript” src=“jquery-easyui-1.2.3/jquery-1.4.4.min.js”></script>  
  9. <script type=“text/javascript” src=“jquery-easyui-1.2.3/jquery.easyui.min.js”></script>  
  10. </head>  
  11. <body>  
  12.     <div class=“easyui-panel” title=“Demo1” fit=“true” collapsible=“true” minimizable=“true” maximizable=“true” closable=“true” style=“width: 100%; height: 200px;” >  
  13.         easyloader会自动解析这个div,因为class属性中带有easyui开头的类!  
  14.     </div>  
  15. </body>  
  16. </html>  

 

这两种方法都行,作者开发此模块,说明应该尽量使用easyuiloader来加载。因为他定制性更强,可以自定义主题和国际化等。而压缩过的文件的优势在于一次性把所有模块都加载进来,速度上更快。

  1. /** 
  2.  * easyloader – jQuery EasyUI 
  3.  *  
  4.  * Licensed under the GPL: 
  5.  *   http://www.gnu.org/licenses/gpl.txt 
  6.  * 
  7.  * Copyright 2010 stworthy [ stworthy@gmail.com ]  
  8.  *  
  9.  */  
  10. (function(){  
  11.     // 模块文件定义  
  12.     var modules = {  
  13.         draggable:{  
  14.             js:‘jquery.draggable.js’  
  15.         },  
  16.         droppable:{  
  17.             js:‘jquery.droppable.js’  
  18.         },  
  19.         resizable:{  
  20.             js:‘jquery.resizable.js’  
  21.         },  
  22.         linkbutton:{  
  23.             js:‘jquery.linkbutton.js’,  
  24.             css:‘linkbutton.css’  
  25.         },  
  26.         pagination:{  
  27.             js:‘jquery.pagination.js’,  
  28.             css:‘pagination.css’,  
  29.             dependencies:[‘linkbutton’]  
  30.         },  
  31.         datagrid:{  
  32.             js:‘jquery.datagrid.js’,  
  33.             css:‘datagrid.css’,  
  34.             dependencies:[‘panel’,‘resizable’,‘linkbutton’,‘pagination’]  
  35.         },  
  36.         treegrid:{  
  37.             js:‘jquery.treegrid.js’,  
  38.             css:‘tree.css’,  
  39.             dependencies:[‘datagrid’]  
  40.         },  
  41.         panel: {  
  42.             js:‘jquery.panel.js’,  
  43.             css:‘panel.css’  
  44.         },  
  45.         window:{  
  46.             js:‘jquery.window.js’,  
  47.             css:‘window.css’,  
  48.             dependencies:[‘resizable’,‘draggable’,‘panel’]  
  49.         },  
  50.         dialog:{  
  51.             js:‘jquery.dialog.js’,  
  52.             css:‘dialog.css’,  
  53.             dependencies:[‘linkbutton’,‘window’]  
  54.         },  
  55.         messager:{  
  56.             js:‘jquery.messager.js’,  
  57.             css:‘messager.css’,  
  58.             dependencies:[‘linkbutton’,‘window’]  
  59.         },  
  60.         layout:{  
  61.             js:‘jquery.layout.js’,  
  62.             css:‘layout.css’,  
  63.             dependencies:[‘resizable’,‘panel’]  
  64.         },  
  65.         form:{  
  66.             js:‘jquery.form.js’  
  67.         },  
  68.         menu:{  
  69.             js:‘jquery.menu.js’,  
  70.             css:‘menu.css’  
  71.         },  
  72.         tabs:{  
  73.             js:‘jquery.tabs.js’,  
  74.             css:‘tabs.css’,  
  75.             dependencies:[‘panel’,‘linkbutton’]  
  76.         },  
  77.         splitbutton:{  
  78.             js:‘jquery.splitbutton.js’,  
  79.             css:‘splitbutton.css’,  
  80.             dependencies:[‘linkbutton’,‘menu’]  
  81.         },  
  82.         menubutton:{  
  83.             js:‘jquery.menubutton.js’,  
  84.             css:‘menubutton.css’,  
  85.             dependencies:[‘linkbutton’,‘menu’]  
  86.         },  
  87.         accordion:{  
  88.             js:‘jquery.accordion.js’,  
  89.             css:‘accordion.css’,  
  90.             dependencies:[‘panel’]  
  91.         },  
  92.         calendar:{  
  93.             js:‘jquery.calendar.js’,  
  94.             css:‘calendar.css’  
  95.         },  
  96.         combo:{  
  97.             js:‘jquery.combo.js’,  
  98.             css:‘combo.css’,  
  99.             dependencies:[‘panel’,‘validatebox’]  
  100.         },  
  101.         combobox:{  
  102.             js:‘jquery.combobox.js’,  
  103.             css:‘combobox.css’,  
  104.             dependencies:[‘combo’]  
  105.         },  
  106.         combotree:{  
  107.             js:‘jquery.combotree.js’,  
  108.             dependencies:[‘combo’,‘tree’]  
  109.         },  
  110.         combogrid:{  
  111.             js:‘jquery.combogrid.js’,  
  112.             dependencies:[‘combo’,‘datagrid’]  
  113.         },  
  114.         validatebox:{  
  115.             js:‘jquery.validatebox.js’,  
  116.             css:‘validatebox.css’  
  117.         },  
  118.         numberbox:{  
  119.             js:‘jquery.numberbox.js’,  
  120.             dependencies:[‘validatebox’]  
  121.         },  
  122.         spinner:{  
  123.             js:‘jquery.spinner.js’,  
  124.             css:‘spinner.css’,  
  125.             dependencies:[‘validatebox’]  
  126.         },  
  127.         numberspinner:{  
  128.             js:‘jquery.numberspinner.js’,  
  129.             dependencies:[‘spinner’,‘numberbox’]  
  130.         },  
  131.         timespinner:{  
  132.             js:‘jquery.timespinner.js’,  
  133.             dependencies:[‘spinner’]  
  134.         },  
  135.         tree:{  
  136.             js:‘jquery.tree.js’,  
  137.             css:‘tree.css’,  
  138.             dependencies:[‘draggable’,‘droppable’]  
  139.         },  
  140.         datebox:{  
  141.             js:‘jquery.datebox.js’,  
  142.             css:‘datebox.css’,  
  143.             dependencies:[‘calendar’,‘validatebox’]  
  144.         },  
  145.         parser:{  
  146.             js:‘jquery.parser.js’  
  147.         }  
  148.     };  
  149.       
  150.     // 国际化资源文件  
  151.     var locales = {  
  152.         ‘af’:‘easyui-lang-af.js’,  
  153.         ‘bg’:‘easyui-lang-bg.js’,  
  154.         ‘ca’:‘easyui-lang-ca.js’,  
  155.         ‘cs’:‘easyui-lang-cs.js’,  
  156.         ‘da’:‘easyui-lang-da.js’,  
  157.         ‘de’:‘easyui-lang-de.js’,  
  158.         ‘en’:‘easyui-lang-en.js’,  
  159.         ‘fr’:‘easyui-lang-fr.js’,  
  160.         ‘nl’:‘easyui-lang-nl.js’,  
  161.         ‘zh_CN’:‘easyui-lang-zh_CN.js’,  
  162.         ‘zh_TW’:‘easyui-lang-zh_TW.js’  
  163.     };  
  164.       
  165.     // 加载队列  
  166.     var queues = {};  
  167.       
  168.     /** 
  169.      * 加载js文件函数,过程就是动态创建一个script标签,然后添加到head标签中去。 
  170.      * 有一个问题是监听了script标签的两个事件函数,一个是onload,另一个是onreadystatechange,这个数要是针对IE和非IE浏览器准备的 
  171.      * 万恶的IE浏览器!!! 
  172.      */  
  173.     function loadJs(url, callback){  
  174.         var done = false;  
  175.         var script = document.createElement(‘script’);  
  176.         script.type = ‘text/javascript’;  
  177.         script.language = ‘javascript’;  
  178.         script.src = url;  
  179.         script.onload = script.onreadystatechange = function(){  
  180.             if (!done && (!script.readyState || script.readyState == ‘loaded’ || script.readyState == ‘complete’)){  
  181.                 done = true;  
  182.                 script.onload = script.onreadystatechange = null;  
  183.                 if (callback){  
  184.                     callback.call(script);  
  185.                 }  
  186.             }  
  187.         }  
  188.         document.getElementsByTagName(“head”)[0].appendChild(script);  
  189.     }  
  190.       
  191.     /** 
  192.      * 执行js文件。就是把js文件加载进来,再remove掉 
  193.      * @param url js的url 
  194.      * @callback 回调函数,执行完js时会调用这个函数 
  195.      */  
  196.     function runJs(url, callback){  
  197.         loadJs(url, function(){  
  198.             document.getElementsByTagName(“head”)[0].removeChild(this);  
  199.             if (callback){  
  200.                 callback();  
  201.             }  
  202.         });  
  203.     }  
  204.       
  205.     /** 
  206.      * 加载css文件。和加载js文件一样,动态创建一个link标签,然后追加到head标签中去 
  207.      * @param url css的url 
  208.      * @param callback 回调函数,加载完成后调用此函数 
  209.      */  
  210.     function loadCss(url, callback){  
  211.         var link = document.createElement(‘link’);  
  212.         link.rel = ‘stylesheet’;  
  213.         link.type = ‘text/css’;  
  214.         link.media = ‘screen’;  
  215.         link.href = url;  
  216.         document.getElementsByTagName(‘head’)[0].appendChild(link);  
  217.         if (callback){  
  218.             callback.call(link);  
  219.         }  
  220.     }  
  221.       
  222.     /** 
  223.      * 加载单独的一个模块 
  224.      */  
  225.     function loadSingle(name, callback){  
  226.           
  227.         // 加载队列存入该模块名,并表示状态为loading。  
  228.         queues[name] = ‘loading’;  
  229.           
  230.         // 根据模块名,取出该模块定义  
  231.         var module = modules[name];  
  232.           
  233.         // js加载状态  
  234.         var jsStatus = ‘loading’;  
  235.           
  236.         // css加载状态,从这里你就可以看出easyloader.css就是一个开关变量,控制是否加载模块相应的css文件  
  237.         var cssStatus = (easyloader.css && module[‘css’]) ? ‘loading’ : ‘loaded’;  
  238.           
  239.         // 是css文件,就使用loadCss来加载之  
  240.         if (easyloader.css && module[‘css’]){  
  241.             if (/^http/i.test(module[‘css’])){  
  242.                 var url = module[‘css’];  
  243.             } else {  
  244.                 var url = easyloader.base + ‘themes/’ + easyloader.theme + ‘/’ + module[‘css’];  
  245.             }  
  246.             loadCss(url, function(){  
  247.                 cssStatus = ‘loaded’;  
  248.                 if (jsStatus == ‘loaded’ && cssStatus == ‘loaded’){  
  249.                     finish();  
  250.                 }  
  251.             });  
  252.         }  
  253.           
  254.         // 是js文件,就是用LoadJs来加载之  
  255.         if (/^http/i.test(module[‘js’])){  
  256.             var url = module[‘js’];  
  257.         } else {  
  258.             var url = easyloader.base + ‘plugins/’ + module[‘js’];  
  259.         }  
  260.         loadJs(url, function(){  
  261.             jsStatus = ‘loaded’;  
  262.             if (jsStatus == ‘loaded’ && cssStatus == ‘loaded’){  
  263.                 finish();  
  264.             }  
  265.         });  
  266.           
  267.         // 最终调用finish函数,来结束加载。并触发onProgress函数,每加载成功一个模块,就调用一次onProgress  
  268.         function finish(){  
  269.             queues[name] = ‘loaded’;  
  270.             easyloader.onProgress(name);  
  271.             if (callback){  
  272.                 callback();  
  273.             }  
  274.         }  
  275.     }  
  276.       
  277.     /** 
  278.      * easyui模块加载函数 
  279.      * @param name 模块名,可以是string,也可以是数组 
  280.      * @param callback 回调函数,当加载结束后会调用此函数 
  281.      */  
  282.     function loadModule(name, callback){  
  283.           
  284.         // 模块名,根据依赖关系,从前到后,依次排开  
  285.         var mm = [];  
  286.           
  287.         // 加载标识,当其值为true时,表示需要加载的模块已经加载好了  
  288.         var doLoad = false;  
  289.           
  290.         // 模块名支持两中,一种是string,一种是数组。这样就可以一次加载多个模块了  
  291.         if (typeof name == ‘string’){  
  292.             // 是string的时候,调用add方法把模块名push到mm数组中去  
  293.             add(name);  
  294.         } else {  
  295.             for(var i=0; i<name.length; i++){  
  296.                 // 是数组的时候,循环调用add方法把模块名统统push到mm数组中去  
  297.                 add(name[i]);  
  298.             }  
  299.         }  
  300.           
  301.         /** 
  302.          * loadModule函数中内嵌的一个函数,用来加载模块名到变量mm数组中去 
  303.          * @param name 模块名,只能是string 
  304.          */  
  305.         function add(name){  
  306.             // 保护措施,如果该模块名不存在,我们就不要加载了  
  307.             if (!modules[name]) return;  
  308.               
  309.             // 否则,就是该模块存在。然后,我们在看看其有没有依赖模块  
  310.             var d = modules[name][‘dependencies’];  
  311.             if (d){  
  312.                 // 如果有依赖模块,我们要先把依赖模块的名字push到mm中去  
  313.                 // 这里用了递归调用  
  314.                 for(var i=0; i<d.length; i++){  
  315.                     add(d[i]);  
  316.                 }  
  317.             }  
  318.               
  319.             // 把模块名放到mm中  
  320.             mm.push(name);  
  321.         }  
  322.           
  323.         /** 
  324.          * 当一个模块及其依赖模块加载完成时,执行回调函数,并且触发onLoad函数 
  325.          */  
  326.         function finish(){  
  327.             if (callback){  
  328.                 callback();  
  329.             }  
  330.             easyloader.onLoad(name);  
  331.         }  
  332.           
  333.         // 加载用时  
  334.         var time = 0;  
  335.           
  336.         /** 
  337.          * 加载所需要的模块,需要的模块,我们已经统计好了,并按依赖关系,先后push到mm中去了 
  338.          */  
  339.         function loadMm(){  
  340.             // 判断mm是不是空的  
  341.             if (mm.length){  
  342.                   
  343.                 // 第一个模块  
  344.                 var m = mm[0];  
  345.                   
  346.                 // 判断加载队列是否包含此模块  
  347.                 if (!queues[m]){  
  348.                       
  349.                     // 加载队列不包含此模块,开始加载该模块  
  350.                     // 把doLoad置成true,表示开始加载  
  351.                     doLoad = true;  
  352.                       
  353.                     // 调用loadSingle方法来加载模块,加载成功后会把此模块从mm中shift掉,然后继续调用loadMM方法,就形成了递归调用  
  354.                     loadSingle(m, function(){  
  355.                         mm.shift();  
  356.                         loadMm();  
  357.                     });  
  358.                 } else if (queues[m] == ‘loaded’){  
  359.                     // 加载队列已经加载过此模块了,不需要在加载了,直接从mm中shift掉即可  
  360.                     mm.shift();  
  361.                     loadMm();  
  362.                 } else {  
  363.                     // 表示正在加载该模块,累计所用时间如果没有超过timeout  
  364.                     // 则过10毫秒再调用一次loadMm函数  
  365.                     if (time < easyloader.timeout){  
  366.                         time += 10;  
  367.                         setTimeout(arguments.callee, 10);  
  368.                     }  
  369.                 }  
  370.             } else {  
  371.                 // 走到这里,表示该加载的模块都已经加载好了  
  372.                 if (easyloader.locale && doLoad == true && locales[easyloader.locale]){  
  373.                     // 如果设置了国际化,并且已经加载好了,而且该国际化资源还存在,那么加载该资源js  
  374.                     var url = easyloader.base + ‘locale/’ + locales[easyloader.locale];  
  375.                       
  376.                     // 执行js完事后,调用finish方法  
  377.                     runJs(url, function(){  
  378.                         finish();  
  379.                     });  
  380.                 } else {  
  381.                     // 没定义国际化文件,那么直接调用finish方法吧  
  382.                     finish();  
  383.                 }  
  384.             }  
  385.         }  
  386.           
  387.         loadMm();  
  388.     }  
  389.       
  390.     /** 
  391.      * easyloader定义为全局变量 
  392.      */  
  393.     easyloader = {  
  394.           
  395.         // 各个模块文件的定义,包括js、css和依赖模块  
  396.         modules:modules,  
  397.           
  398.         // 国际化资源文件  
  399.         locales:locales,  
  400.           
  401.         // jquery-easyui的根目录,在加载easyloader时,会自动根据你放置的位置而改变  
  402.         base:‘.’,  
  403.           
  404.         // 控件的主题,一共就有两个,在theme目录中。还有一个gray主题,浅灰色的,很难看。  
  405.         theme:‘default’,  
  406.           
  407.         // 这是一个开关变量,控制easyloader加载模块时,要不要加载相应的css文件,默认是需要加载的  
  408.         css:true,  
  409.           
  410.         // 国际化语言,可以根据window.navigator.language或者window.navigator.userLanguage来获取当前浏览器的语言。  
  411.         // 有两个属性,主要因为IE浏览器只认识userLanguage和sysLanguage,万恶的IE浏览器啊!  
  412.         locale:null,  
  413.           
  414.         // 加载一个模块的最长时间,超过这个时间,就开始加载下一个模块了。  
  415.         timeout:2000,  
  416.       
  417.         // easyloader就公开了这么一个方法,用来加载模块。  
  418.         // name是模块名,callback是加载成功后执行的函数  
  419.         load: function(name, callback){  
  420.             if (//.css$/i.test(name)){  
  421.                 // 如果模块名是以.css结尾  
  422.                   
  423.                 if (/^http/i.test(name)){  
  424.                     // 如果模块名是以http开头,那么css是一个文件的url  
  425.                     loadCss(name, callback);  
  426.                 } else {  
  427.                     // 否则,说明模块名相对于jquery easyui根目录来说的  
  428.                     loadCss(easyloader.base + name, callback);  
  429.                 }  
  430.             } else if (//.js$/i.test(name)){  
  431.                 // 如果模块名是以.js结尾  
  432.                   
  433.                 if (/^http/i.test(name)){  
  434.                     // 如果模块名是以http开头,那么js是一个文件的url  
  435.                     loadJs(name, callback);  
  436.                 } else {  
  437.                     // 否则,说明模块名相对于jquery easyui根目录来说的  
  438.                     loadJs(easyloader.base + name, callback);  
  439.                 }  
  440.             } else {  
  441.                 // 以上两种都不是,说明是easyui自己的模块,直接使用loadModule来加载,就可以了  
  442.                 loadModule(name, callback);  
  443.             }  
  444.         },  
  445.           
  446.         // 当一个模块加载完会触发此函数  
  447.         onProgress: function(name){},  
  448.           
  449.         // 当一个模块和其依赖都加载完会触发此函数  
  450.         onLoad: function(name){}  
  451.     };  
  452.     /** 
  453.      * 这一小段代码就是查找jquery-easyui的根目录,并赋值给easyloader的base属性上。这样easyloader再加载css文件和js文件就很方便定位了。 
  454.      */  
  455.     var scripts = document.getElementsByTagName(‘script’);  
  456.     for(var i=0; i<scripts.length; i++){  
  457.         var src = scripts[i].src;  
  458.         if (!src) continue;  
  459.         var m = src.match(/easyloader/.js(/W|$)/i);  
  460.         if (m){  
  461.             easyloader.base = src.substring(0, m.index);  
  462.         }  
  463.     }  
  464.     /** 
  465.      * 这个就起一个别名的作用,比如页面中可以想如下这么下: 
  466.      * using(‘window’); 
  467.      * 这样window模块就加载进来了! 
  468.      */  
  469.     window.using = easyloader.load;  
  470.     /** 
  471.      * easyloader.js加载的第一模块是parse模块,parser模块调用parse方法,可以解析页面上的easyui控件 
  472.      */  
  473.     if (window.jQuery){  
  474.         jQuery(function(){  
  475.             easyloader.load(‘parser’function(){  
  476.                 jQuery.parser.parse();  
  477.             });  
  478.         });  
  479.     }  
  480.       
  481. })();  

到这里easyloader就分析结束了,如果你仔细看过了,相信一定会使用easyloader了。有问题可以给我留言。

[转载]关于图片在网络中的传输

mikel阅读(1070)

[转载]关于图片在网络中的传输 – 死在冲锋的路上的兵 – 博客园.

最近学习中学习到关于C#  如何把图片用webservice传输  然后java 端接收保存,或者反之。。。

 

首先:要将图片转换成byte

 

其次:要讲byte进行base64编码 (之前没有编码没有传输成功的)

 

最后:java端接收到进行base64译码

 

下面贴出代码:

 

           c#端
            String imgpath = @"imgPath";
            FileStream file = new FileStream(imgpath,                FileMode.Open, FileAccess.Read);
            byte[] byteArray = new byte[file.Length];
            file.Read(byteArray, 0, byteArray.Length); 
            file.Close();
            String strbaser64 = Convert.ToBase64String(byteArray);

 

java端
byte[] buffer = Base64.decode(bytes);
        File file = new File(SDPATH + imagePath);
        
        FileOutputStream fos = new FileOutputStream(file);

        fos.write(buffer);     
        
        fos.flush();

        fos.close();

 

[转载]ASP.NET之JSONHelper操作

mikel阅读(1431)

[转载]ASP.NET之JSONHelper操作 – PEPE YU – 博客园.

   之前说到了Ext.Net中GridPanel行取值的问题(Ext.Net开发_GridPanel行选中取值),涉及到checkBox操作时,要留个心眼注意下取值的区别!返回值是Json格式。 现在用到了Json,就想自己也整一个Josn帮助类。在线帮助的资料很多,在巨人的身上东凑西凑也凑一个用用。   

 

一、介绍

  JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,基于JavaScript(Standard ECMA-262 3rd Edition – December 1999)的一个子集

 

方法有多种,我这边用到是DataContractJsonSerializer类,官方解释:“NET Framework 4 .NET Framework 3.5 Silverlight 将对象序列化为 JavaScript 对象表示法 (JSON),并将 JSON 数据反序列化为对象”。

 

  其命名空间如下:

 

 

注意:如果是.NET Framework 3.5  光引用了“System.Runtime.Serialization”了这个还不行。运行时会发现:

 

 

 

所以还要引用下“System.ServiceModel.Web”即可。   .NET Framework 4则在System.Runtime.Serialization下。

 

二、对JSON数据操作

 源码:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;
using System.Collections.Generic;
using System.Runtime.Serialization.Json;
namespace WebUI.CommonClass
{
    public class JSONHelper
    { 

          /// <summary>
 /// JSON序列化
 /// </summary>
        public static string JsonSerializer<T>(T t)
        {
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
            MemoryStream ms = new MemoryStream();
            ser.WriteObject(ms, t);
            string jsonString = Encoding.UTF8.GetString(ms.ToArray());
            ms.Close();
            //替换Json的Date字符串
            string p = @"\\/Date\((\d+)\+\d+\)\\/";
            MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertJsonDateToDateString);
            Regex reg = new Regex(p);
            jsonString = reg.Replace(jsonString, matchEvaluator);
            return jsonString;
        }

        /// <summary>
 /// JSON反序列化
 /// </summary>
        public static T JsonDeserialize<T>(string jsonString)
        {
            //将"yyyy-MM-dd HH:mm:ss"格式的字符串转为"\/Date(1294499956278+0800)\/"格式
            string p = @"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}";
            MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertDateStringToJsonDate);
            Regex reg = new Regex(p);
            jsonString = reg.Replace(jsonString, matchEvaluator);
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
            T obj = (T)ser.ReadObject(ms);
            return obj;
        } 

        /// <summary>
 /// 将Json序列化的时间由/Date(1294499956278+0800)转为字符串
 /// </summary>
        private static string ConvertJsonDateToDateString(Match m)
        {
            string result = string.Empty;
            DateTime dt = new DateTime(1970, 1, 1);
            dt = dt.AddMilliseconds(long.Parse(m.Groups[1].Value));
            dt = dt.ToLocalTime();
            result = dt.ToString("yyyy-MM-dd HH:mm:ss");
            return result;
        }

        /// <summary>
 /// 将时间字符串转为Json时间
 /// </summary>
        private static string ConvertDateStringToJsonDate(Match m)
        {
            string result = string.Empty;
            DateTime dt = DateTime.Parse(m.Groups[0].Value);
            dt = dt.ToUniversalTime();
            TimeSpan ts = dt - DateTime.Parse("1970-01-01");
            result = string.Format("\\/Date({0}+0800)\\/", ts.TotalMilliseconds);
            return result;
        }
    }
}

实验下:

Product

    public class Product
    {
        public string proName { get ;set ; }
        public decimal  proPrice { get; set; }
        public string proAttr { get; set; }
        public string proAddres { get; set; } 
    }

操作

1:序列化

Product pro = new Product();
pro.proAddres = "上海";
pro.proAttr = "cpu";
pro.proName = "电脑";
pro.proPrice = 3680;
string josn = JSONHelper.JsonSerializer<Product>(pro);   //序列化
Message.ShowAlert("提示", josn);

效果:


2,反序列化

string json = "{\"proAddres\":\"上海\",\"proAttr\":\"cpu\",\"proName\":\"电脑\",\"proPrice\":3680}";
Product pro = JSONHelper.JsonDeserialize<Product>(json);

 

 

[转载]WCF REST 解决资源并发修改的一个有效的手段:条件更新(Conditional Update)

mikel阅读(951)

[转载][WCF REST] 解决资源并发修改的一个有效的手段:条件更新(Conditional Update) – Artech – 博客园.

条件获取(Conditional Update)可 以避免相同数据的重复传输,进而提高性能。条件更新(Conditional Update)用于解决资源并发操作问题。如果我们预先获取一个资源进行修改或者删除,条件更新检验帮助我们确认资源被获取出来到针对它的修改/删除操作 被提交的这段时间内是否被其他人改动过。[源代码从这里下载]

一、HTTP对条件更新的支持

HTTP 为条件更新提供了相应的报头,我们按照分析条件获取的方式来分析条件更新在HTTP请求/回复过程中的实现。客户端第一次向服务端发起针对某个资源的请 求,服务端除了将资源数据作为回复消息主体返回之外,会将与资源关联并且能够可以用于对其进行对等性判断的某个值作为回复的ETag报头,这与条件获取时 一致的。

客户端通过回复获得请求的资源和ETag报头值。对于资源修改操作,客户端直接针对获取的资源进行相应的修改,并将修改后的资 源以HTTP请求的方式向服务端提交;对于资源删除操作,则可以指定被删除资源的唯一标识直接向服务端发送删除的请求。而之前获取的ETag指将会作为请 求消息的If-Match报头。

服务端接收到资源修改/删除请求后先获取到现有的资源的ETag值,并将此值与请求消息的If- Match报头值进行比较。如果两者不一致,则表明试图被修改/删除的资源已经被修改了,在这种情况下会直接回复一个HTTP状态为“412 (Precondition Failed)”的空消息。条件更新同时支持针对PUT、POST和DELETE这三种方法的HTTP请求。

二、WebOperationContext与条件更新

服 务端进行条件更新检测,以及客户端对If-Match请求报头的设置都可以通过当前的WebOperationContext来完成。如下面的代码片断所 示,表示入栈请求上下文的IncomingWebRequestContext类型具有如下四个CheckConditionalUpdate方法重载用 于进行添加更新检测。

 1: public class IncomingWebRequestContext
 2: {
 3:     //其他成员
 4:     public void CheckConditionalUpdate(Guid entityTag);
 5:     public void CheckConditionalUpdate(int entityTag);
 6:     public void CheckConditionalUpdate(long entityTag);
 7:     public void CheckConditionalUpdate(string entityTag);
 8: }

实现在CheckConditionalUpdate方法中的条件更新检测具有这样的逻辑:对于 HTTP方法为PUT的请求,如果If-Match报头值不为“*”,则直接抛出HTTP状态为PreconditionFailed的 WebFaultException异常;对于HTTP方法为POST和DELETE的请求来说,如果If-Match报头值为“*”或者包含指定的 entityTag则验证通过,否则同样则直接抛出HTTP状态为PreconditionFailed的WebFaultException异常

表示出栈请求上下文的OutgoingWebRequestContext类型具有如下一个IfMatch属性,客户端可以通过该属性对请求消息的If-Match报头进行设置。

 1: public class OutgoingWebRequestContext
 2: {
 3:     //其他成员
 4:     public string IfMatch { get; set; }
 5: }

三、实例演示:通过条件更新解决对相同资源的并发修改

我们同样通过对EmployeesService进行相应的改造来模拟如何通过添加更新实现对相同资源的并发操作问题,这次我们修改的是用于获取指 定ID员工信息的Get操作和用于修改员工信息的Update操作。Get操作在返回与指定员工ID匹配的Employee对象之前我们将该对象的哈希码 作为了回复消息的ETag报头(Employee类型重写了GetHashCode方法)。

 1: public class EmployeesService : IEmployees
 2: {
 3:     //其他成员
 4:     public Employee Get(string id)
 5:     {
 6:         Employee employee = employees.FirstOrDefault(e => e.Id == id);
 7:         if (null == employee)
 8:         {
 9:             throw new WebFaultException(HttpStatusCode.NotFound);
 10:         }
 11:         WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
 12:         return employee;
 13:     }
 14:     public void Update(Employee employee)
 15:     {
 16:         var existing = employees.FirstOrDefault(e => e.Id == employee.Id);
 17:         if (null == existing)
 18:         {
 19:             throw new WebFaultException(HttpStatusCode.NotFound);
 20:         }
 21:         //模拟并发修改
 22:         existing.Name += Guid.NewGuid().ToString();
 23:
 24:         WebOperationContext.Current.IncomingRequest.CheckConditionalUpdate(existing.GetHashCode());
 25:         employees.Remove(existing);
 26:         employees.Add(employee);
 27:         WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
 28:
 29:     }
 30: }

Update方法中我们通过手工修改相应员工的Name属性的方式来模拟针对相同员工信息的并发修改。在真正实施修改之前调用当前 IncomingWebRequestContext的CheckConditionalUpdate方法进行条件更新检测,而作为参数传入的ETag值 为代表目前员工的Employee对象的哈希码。方法的最后我们对回复消息的ETag报头作了更新。

我们通过手工创建HTTP请求的方式对上述的两个服务操作进行调用。如下面的代码片断所示,我们首先通过创建的HttpWebRequest对象调 用Get操作获得ID为001的员工信息并将其打印出来。然后创建调用Update操作的HttpWebRequest,并对HTTP方法(POST)和 内容类型(application/xml)进行了相应的设置。我们之前针对员工获取请求得到ETag报头和员工数据作为本次请求的If-Match报头 和主体。如果调用GetResponse方法抛出WebException异常,并且其回复状态为PreconditionFailed,则表明试图修改 的员工信息已被另一个用户修改过了,所以我么打印“服务端数据已发生变化”字样。

 1: Uri address = new Uri("http://127.0.0.1:3721/employees/001");
 2: var request = (HttpWebRequest)HttpWebRequest.Create(address);
 3: request.Method = "GET";
 4: var response = (HttpWebResponse)request.GetResponse();
 5: string employee;
 6: using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
 7: {
 8:     employee = reader.ReadToEnd();
 9:     Console.WriteLine("获取员工信息:");
 10:     Console.WriteLine(employee + "\n");
 11: }
 12: try
 13: {
 14:     address = new Uri("http://127.0.0.1:3721/employees/");
 15:     request = (HttpWebRequest)HttpWebRequest.Create(address);
 16:     request.Method = "POST";
 17:     request.ContentType = "application/xml";
 18:     byte[] buffer = Encoding.UTF8.GetBytes(employee);
 19:     request.GetRequestStream().Write(Encoding.UTF8.GetBytes(employee), 0, buffer.Length);
 20:     request.Headers.Add(HttpRequestHeader.IfMatch, response.Headers[HttpResponseHeader.ETag]);
 21:     Console.WriteLine("修改员工信息:");
 22:     request.GetResponse();
 23: }
 24: catch (WebException ex)
 25: {
 26:     response = ex.Response as HttpWebResponse;
 27:     if (null == response)
 28:     {
 29:         throw;
 30:     }
 31:     if (response.StatusCode == HttpStatusCode.PreconditionFailed)
 32:     {
 33:         Console.WriteLine("服务端数据已发生变化");
 34:     }
 35:     else
 36:     {
 37:         throw;
 38:     }
 39: }

在服务成功寄宿的情况下调用这段程序会在控制台上输出如下的结果。由于并发错误的发生,员工信息其实并没有被真正修改。

 1: 获取员工信息:
 2: <Employee xmlns="http://www.artech.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Department>开发部</Department><Grade>G7</Grade><Id>001</Id><Name>张三</Name></Employee>
 3:
 4: 修改员工信息:
 5: 服务端数据已发生变化

 

[转载]jQuery UI Autocomplete 体验

mikel阅读(950)

[转载]jQuery UI Autocomplete 体验 – 囧月 – 博客园.

jQuery UI AutocompleteJQuery UI的自动完成组件,是我用过的最强大、最灵活的Autocomplete,它支持本地的Array/JSON数组、通过ajax请求的Array/JSON数组、JSONP、以及Function(最灵活)等方式来获取数据。

支持的数据源

jQuery UI Autocomplete主要支持字符串ArrayJSON两种数据格式。

普通的Array格式没有什么特殊的,如下:

1
["cnblogs","博客园","囧月"]

对于JSON格式的Array,则要求有:labelvalue属性,如下:

1
[{label: "博客园", value: "cnblogs"}, {label: "囧月", value: "囧月"}]

其中label属性用于显示在autocomplete弹出菜单,而value属性则是选中后给文本框赋的值。

如果没有指定其中一个属性则用另一个属性替代(即value和label值一样),如下:

1
2
[{label: "cnblogs"}, {label: "囧月"}]
[{value: "cnblogs"}, {value: "囧月"}]

如果label和value都没有指定,则无法用于autocomplete的提示。

另外需要注意,对于从服务器端输出的JSON的key必须用双引号,如下:

1
[{"label": "博客园", "value": "cnblogs"}, {"label": "囧月", "value": "囧月"}]

否则可能会出现parsererror错误。

主要的参数

jQuery UI Autocomplete常用的参数有:

  1. Source:用于指定数据来源,类型为String、Array、Function
    1. String:用于ajax请求的服务器端地址,返回Array/JSON格式
    2. Array:即字符串数组 或 JSON数组
    3. Function(request, response):通过request.term获得输入的值,response([Array])来呈现数据;(JSONP是这种方式)
  2. minLength:当输入框内字符串长度达到minLength时,激活Autocomplete
  3. autoFocus:当Autocomplete选择菜单弹出时,自动选中第一个
  4. delay:即延迟多少毫秒激活Autocomplete

其他不常用的就不罗列了。

使用方法

假如页面上有以下输入框:

<input type="text" id="autocomp" /> 

AJAX请求

通过指定source为服务器端的地址来实现,如下:

1
2
3
4
$("#autocomp").autocomplete({
    source: "remote.ashx",
    minLength: 2
});

然后在服务器端接收,并输出相应结果,注意默认传递的参数名称为term

public void ProcessRequest(HttpContext context)
{
    // 查询的参数名称默认为term string query = context.Request.QueryString["term"];
    context.Response.ContentType = "text/javascript";
    //输出字符串数组 或者 JSON 数组 context.Response.Write("[{\"label\":\"博客园\",\"value\":\"cnblogs\"},{\"label\":\"囧月\",\"value\":\"囧月\"}]");
}

本地Array/JSON数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 本地字符串数组
var availableTags = [
    "C#",
    "C++",
    "Java",
    "JavaScript",
    "ASP",
    "ASP.NET",
    "JSP",
    "PHP",
    "Python",
    "Ruby"
];
$("#local1").autocomplete({
    source: availableTags
});
// 本地json数组
var availableTagsJSON = [
    { label: "C# Language", value: "C#" },
    { label: "C++ Language", value: "C++" },
    { label: "Java Language", value: "Java" },
    { label: "JavaScript Language", value: "JavaScript" },
    { label: "ASP.NET", value: "ASP.NET" },
    { label: "JSP", value: "JSP" },
    { label: "PHP", value: "PHP" },
    { label: "Python", value: "Python" },
    { label: "Ruby", value: "Ruby" }
];
$("#local2").autocomplete({
    source: availableTagsJSON
});

Callback Function方式

通过指定source为自定义函数来实现自定义数据的获取,函数主要有2个参数(request,response),分别用于获取输入的值、呈现结果

本地Array方式获取数据(模仿新浪微博的登录)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var hosts = ["gmail.com", "live.com", "hotmail.com", "yahoo.com", "cnblogs.com", "火星.com", "囧月.com"];
$("#email1").autocomplete({
    autoFocus: true,
    source: function(request, response) {
        var term = request.term, //request.term为输入的字符串
            ix = term.indexOf("@"),
            name = term, // 用户名
            host = "", // 域名
            result = []; // 结果
        result.push(term);
        // result.push({ label: term, value: term }); // json格式
        if (ix > -1) {
            name = term.slice(0, ix);
            host = term.slice(ix + 1);
        }
        if (name) {
            var findedHosts = (host ? $.grep(hosts, function(value) {
                return value.indexOf(host) > -1;
            }) : hosts),
            findedResults = $.map(findedHosts, function(value) {
                return name + "@" + value; //返回字符串格式
                // return { label: name + " @ " + value, value: name + "@" + value }; // json格式
            });
            result = result.concat($.makeArray(findedResults));
        }
        response(result);//呈现结果
    }
});

JSONP方式获取数据

直接从官方DEMO拿来的,通过发送ajax请求到远程服务器,然后对返回结果进行处理,最后通过response来呈现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$("#jsonp").autocomplete({
    source: function(request, response) {
        $.ajax({
            url: "http://ws.geonames.org/searchJSON",
            dataType: "jsonp",
            data: {
                featureClass: "P",
                style: "full",
                maxRows: 12,
                name_startsWith: request.term
            },
            success: function(data) {
                response($.map(data.geonames, function(item) {
                    return {
                        label: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName,
                        value: item.name
                    }
                }));
            }
        });
    },
    minLength: 2
});

主要的事件

jQuery UI Autocomplete有一些事件,可用于在一些阶段进行额外的控制:

  1. create(event, ui):Autocomplete创建时,可以在此事件中,对外观进行一些控制
  2. search(event, ui): 在开始请求之前,可以在此事件中返回false来取消请求
  3. open(event, ui):Autocomplete的结果列表弹出时
  4. focus(event, ui):Autocomplete的结果列表任意一项获得焦点时,ui.item为获得焦点的项
  5. select(event, ui):Autocomplete的结果列表任意一项选中时,ui.item为选中的项
  6. close(event, ui):Autocomplete的结果列表关闭时
  7. change(event, ui):当值改变时,ui.item为选中的项

这些事件的ui参数的item属性(如果有的话)默认有label和value属性,不管在source中设置的数据是Array还是JSON数组,如下3种:

1
2
3
["cnblogs","博客园","囧月"]
[{label: "博客园", value: "cnblogs"}, {label: "囧月", value: "囧月"}]
[{label: "博客园", value: "cnblogs", id: "1"}, {label: "囧月", value: "囧月", id: "2"}]

假如是第三种的话,还可以得到ui.item.id的值。

这些事件可以通过2种方式来绑定,如下:

1
2
3
4
5
6
7
8
9
10
11
12
// 在参数中
$("#autocomp").autocomplete({
    source: availableTags
    , select: function(e, ui) {
      alert(ui.item.value)
    }
});
// 通过bind来绑定
$("#autocomp").bind("autocompleteselect", function(e, ui) {
    alert(ui.item.value);
});

通过bind来绑定的方式使用的事件名称为”autocomplete”+事件名称,如”select”就是”autocompleteselect”。

多个值的Autocomplete

一般情况下,输入框的autocomplete仅需要一个值就可以(如:javascript);假如需要多个值(如:javascript,c#,asp.net),则需要绑定一些事件来进行额外处理:

  1. 在focus事件中返回false,避免输入框的值被autocomplete的单个值取代
  2. 在select事件中组合多个值
  3. 在元素的keydown事件做一些处理,理由同1
  4. 使用callback function方式的source,来获取最后输入的值,并呈现结果

还是直接拿官方DEMO的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// 按逗号分隔多个值
function split(val) {
    return val.split(/,\s*/);
}
// 提取输入的最后一个值
function extractLast(term) {
    return split(term).pop();
}
// 按Tab键时,取消为输入框设置value
function keyDown(event) {
    if (event.keyCode === $.ui.keyCode.TAB &&
            $(this).data("autocomplete").menu.active) {
        event.preventDefault();
    }
}
var options = {
    // 获得焦点
    focus: function() {
        // prevent value inserted on focus
        return false;
    },
    // 从autocomplete弹出菜单选择一个值时,加到输入框最后,并以逗号分隔
    select: function(event, ui) {
        var terms = split(this.value);
        // remove the current input
        terms.pop();
        // add the selected item
        terms.push(ui.item.value);
        // add placeholder to get the comma-and-space at the end
        terms.push("");
        this.value = terms.join(", ");
        return false;
    }
};
// 多个值,本地数组
$("#local3").bind("keydown", keyDown)
    .autocomplete($.extend(options, {
        minLength: 2,
        source: function(request, response) {
            // delegate back to autocomplete, but extract the last term
            response($.ui.autocomplete.filter(
                availableTags, extractLast(request.term)));
        }
    }));
// 多个值,ajax返回json
$("#ajax3").bind("keydown", keyDown)
    .autocomplete($.extend(options, {
        minLength: 2,
        source: function(request, response) {
            $.getJSON("remoteJSON.ashx", {
                term: extractLast(request.term)
            }, response);
        }
    }));

结尾

最后,放上代码:点击下载

更多的资料请看JQuery UI Autocomplete官方演示:http://jqueryui.com/demos/autocomplete

[转载]SQLite学习手册(数据表和视图)

mikel阅读(1051)

[转载]SQLite学习手册(数据表和视图) – Stephen_Liu – 博客园.

一、创建数据表:

该命令的语法规则和使用方式与大多数关系型数据库基本相同,因此我们还是以示例的方式来演示SQLite中创建表的各种规则。但是对于一些SQLite特有的规则,我们会给予额外的说明。注:以下所有示例均是在SQLite自带命令行工具中完成的。
1). 最简单的数据表:
sqlite> CREATE TABLE testtable (first_col integer);
这里需要说明的是,对于自定义数据表表名,如testtable,不能以sqlite_开头,因为以该前缀定义的表名都用于sqlite内部。

2). 创建带有缺省值的数据表:
sqlite> CREATE TABLE testtable (first_col integer DEFAULT 0, second_col varchar DEFAULT ‘hello’);

3). 在指定数据库创建表:
    sqlite> ATTACH DATABASE ‘d:/mydb.db’ AS mydb;
    sqlite> CREATE TABLE mydb.testtable (first_col integer);
这里先通过ATTACH DATABASE命令将一个已经存在的数据库文件attach到当前的连接中,之后再通过指定数据库名的方式在目标数据库中创建数据表,如 mydb.testtable。关于该规则还需要给出一些额外的说明,如果我们在创建数据表时没有指定数据库名,那么将会在当前连接的main数据库中创 建该表,在一个连接中只能有一个main数据库。如果需要创建临时表,就无需指定数据库名,见如下示例:
    –创建两个表,一个临时表和普通表。
    sqlite> CREATE TEMP TABLE temptable(first_col integer);
    sqlite> CREATE TABLE testtable (first_col integer);    
    –将当前连接中的缓存数据导出到本地文件,同时退出当前连接。
    sqlite> .backup d:/mydb.db
    sqlite> .exit
    –重新建立sqlite的连接,并将刚刚导出的数据库作为主库重新导入。
    sqlite> .restore d:/mydb.db
    –查看该数据库中的表信息,通过结果可以看出临时表并没有被持久化到数据库文件中。
    sqlite> .tables
    testtable

4). “IF NOT EXISTS”从句:
如果当前创建的数据表名已经存在,即与已经存在的表名、视图名和索引名冲突,那么本次创建操作将失败并报错。然而如果在创建表时加上”IF NOT EXISTS”从句,那么本次创建操作将不会有任何影响,即不会有错误抛出,除非当前的表名和某一索引名冲突。
    sqlite> CREATE TABLE testtable (first_col integer);
    Error: table testtable already exists
    sqlite> CREATE TABLE IF NOT EXISTS testtable (first_col integer);

5). CREATE TABLE … AS SELECT:
通过该方式创建的数据表将与SELECT查询返回的结果集具有相同的Schema信息,但是不包含缺省值和主键等约束信息。然而新创建的表将会包含结果集返回的所有数据。
    sqlite> CREATE TABLE testtable2 AS SELECT * FROM testtable;    
    sqlite> .schema testtable2
    CREATE TABLE testtable2(first_col INT);
.schema命令是sqlite3命令行工具的内置命令,用于显示当前数据表的CREATE TABLE语句。

6). 主键约束:
    –直接在字段的定义上指定主键。
    sqlite> CREATE TABLE testtable (first_col integer PRIMARY KEY ASC);
    –在所有字段已经定义完毕后,再定义表的数约束,这里定义的是基于first_col和second_col的联合主键。
    sqlite> CREATE TABLE testtable2 (
       …>     first_col integer,
       …>     second_col integer,
       …>     PRIMARY KEY (first_col,second_col)
       …> );
和其他关系型数据库一样,主键必须是唯一的。

7). 唯一性约束:
    –直接在字段的定义上指定唯一性约束。
    sqlite> CREATE TABLE testtable (first_col integer UNIQUE);
    –在所有字段已经定义完毕后,在定义表的唯一性约束,这里定义的是基于两个列的唯一性约束。
    sqlite> CREATE TABLE testtable2 (
       …>     first_col integer,
       …>     second_col integer,
       …>     UNIQUE (first_col,second_col)
       …> );    
在SQLite中,NULL值被视为和其他任何值都是不同的,这样包括和其他的NULL值,如下例:
    sqlite> DELETE FROM testtable;
    sqlite> SELECT count(*) FROM testtable;
    count(*)
    ———-
    0
    sqlite> INSERT INTO testtable VALUES(NULL);
    sqlite> INSERT INTO testtable VALUES(NULL);
    sqlite> SELECT count(*) FROM testtable;
    count(*)
    ———-
    2    
由此可见,两次插入的NULL值均插入成功。

8). 为空(NOT NULL)约束:
    sqlite> CREATE TABLE testtable(first_col integer NOT NULL);
    sqlite> INSERT INTO testtable VALUES(NULL);
    Error: testtable.first_col may not be NULL
从输出结果可以看出,first_col已经被定义了非空约束,因此不能在插入NULL值了。

9). 检查性约束:
    sqlite> CREATE TABLE testtable (first_col integer CHECK (first_col < 5));
    sqlite> INSERT INTO testtable VALUES(4);
    sqlite> INSERT INTO testtable VALUES(20); — 20违反了字段first_col的检查性约束(first_col < 5)
    Error: constraint failed
–和之前的其它约束一样,检查性约束也是可以基于表中的多个列来定义的。
    sqlite> CREATE TABLE testtable2 (
       …>     first_col integer,
       …>     second_col integer,
       …>     CHECK (first_col > 0 AND second_col < 0)
       …> );

二、表的修改:

SQLite对ALTER TABLE命令支持的非常有限,仅仅是修改表名和添加新字段。其它的功能,如重命名字段、删除字段和添加删除约束等均为提供支持。
1). 修改表名:
需要先说明的是,SQLite中表名的修改只能在同一个数据库中,不能将其移动到Attached数据库中。再有就是一旦表名被修改后,该表已存在的索引将不会受到影响,然而依赖该表的视图和触发器将不得不重新修改其定义。
    sqlite> CREATE TABLE testtable (first_col integer);
    sqlite> ALTER TABLE testtable RENAME TO testtable2;
    sqlite> .tables
    testtable2 
通过.tables命令的输出可以看出,表testtable已经被修改为testtable2。

2). 新增字段:
    sqlite> CREATE TABLE testtable (first_col integer);
    sqlite> ALTER TABLE testtable ADD COLUMN second_col integer;
    sqlite> .schema testtable
    CREATE TABLE “testtable” (first_col integer, second_col integer);  
通过.schema命令的输出可以看出,表testtable的定义中已经包含了新增字段。
关于ALTER TABLE最后需要说明的是,在SQLite中该命令的执行时间是不会受到当前表行数的影响,也就是说,修改有一千万行数据的表和修改只有一条数据的表所需的时间几乎是相等的。

三、表的删除:

在SQLite中如果某个表被删除了,那么与之相关的索引和触发器也会被随之删除。在很多其他的关系型数据库中是不可以这样的,如果必须要删除相关对象,只能在删除表语句中加入WITH CASCADE从句。见如下示例:
    sqlite> CREATE TABLE testtable (first_col integer);
    sqlite> DROP TABLE testtable;
    sqlite> DROP TABLE testtable;
    Error: no such table: testtable
    sqlite> DROP TABLE IF EXISTS testtable;
从上面的示例中可以看出,如果删除的表不存在,SQLite将会报错并输出错误信息。如果希望在执行时不抛出异常,我们可以添加IF EXISTS从句,该从句的语义和CREATE TABLE中的完全相同。

四、创建视图:

我们这里只是给出简单的SQL命令示例,具体的含义和技术细节可以参照上面的创建数据表部分,如临时视图、”IF NOT EXISTS”从句等。
1). 最简单的视图:
    sqlite> CREATE VIEW testview AS SELECT * FROM testtable WHERE first_col > 100;    

2). 创建临时视图:
    sqlite> CREATE TEMP VIEW tempview AS SELECT * FROM testtable WHERE first_col > 100;

3). “IF NOT EXISTS”从句:
    sqlite> CREATE VIEW testview AS SELECT * FROM testtable WHERE first_col > 100;
    Error: table testview already exists
    sqlite> CREATE VIEW IF NOT EXISTS testview AS SELECT * FROM testtable WHERE first_col > 100;

五、删除视图:

该操作的语法和删除表基本相同,因此这里只是给出示例:
    sqlite> DROP VIEW testview;
    sqlite> DROP VIEW testview;
    Error: no such view: testview
    sqlite> DROP VIEW IF EXISTS testview; 

[转载]ASP.NET MVC3中用内置的MEF实现IoC

mikel阅读(1155)

[转载]ASP.NET MVC3中用内置的MEF实现IoC – Mainz – 博客园.

本文讲述关于用Managed Extensibility Framework (MEF) 的方法来实现IoC和ASP.NET的集成。很多人不知道,这个MEF貌似是个大框架,其实已经内置在.NET Framework 4.0里面了,只需要添加引用System.ComponentModel.Composition即 可。MEF在Microsoft的人看来不是一个IoC/DI的工具,而是一个提供轻量级的、可扩展的、类似插件式的系统架构的、且无需配置的 (Attribute Based)框架。虽然微软的人极力否认MEF是一个IoC/DI的工具,但事实是它的确可以实现Ioc/DI。而且相对于Spring.net这样的框架来说,它的优势就是首先它是.NET Framework内置的,你无需添加第三方的引用,担心第三方组件的更新等问题;其次它是免配置的,对Spring.net这样的庞然大物来说免配置很有诱惑力。对Unity来 说,它的优势是一样的,.NET Framework内置,无需配置,无需hard code的声明。当然更无需直接引用了,这是所有IoC都做到的。MEF还可以通过metadata自动发现Parts而无需获取parts的 assembly/dll。有关MEF的完整的介绍,请移步MSDN:http://msdn.microsoft.com/en-us/library/dd460648.aspx。

这里给出一个例子,用在ASP.NET MVC3里面,主要场景是在Controller里通过接口获取中间层的实例,本文主要是演示MEF在ASP.NET MVC3中的应用,其它丰富的应用完全可以发挥你自己的想象力。本文源码下载这里

整个项目的结构如下图:

在Controller中需要调用IBookService与IPhoneService:

Controller的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Service.Interface;

namespace Mvc3_MEF_WebApplication.Controllers
{
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller
{
private readonly IBookService _bookService;
private readonly IPhoneService _phoneService;

[ImportingConstructor]
public HomeController(IBookService bookService, IPhoneService phoneService)
{
_bookService = bookService;
_phoneService = phoneService;
}

public ActionResult Index()
{
ViewBag.Message = Welcome to ASP.NET MVC! +
_bookService.GetAllBooks().ToList()[0].Name +
_phoneService.GetAllPhones().ToList()[0].SerialNumber;

return View();
}

public ActionResult About()
{
return View();
}
}
}

BookService的实现:

BookService的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using Data.Model;
using Service.Interface;

namespace Service.Implement
{
[Export(typeof(IBookService))]
public class DefaultBookService : IBookService
{
public IEnumerable<Book> GetAllBooks()
{
yield return new Book
{
ID = 1,
Name = a
};

yield return new Book
{
ID = 2,
Name = b
};
}
}
}

在Global.asax.cs里面需要设置MEF dependency resolver,自动加载所有bin目录下面的assembly/dll

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);

//Set MEF dependency resolver
var catalog =
new DirectoryCatalog(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, bin));
var container =
new CompositionContainer(catalog);
container.ComposeParts(this);

var mefDependencySolver = new MefDependencySolver(container);
DependencyResolver.SetResolver(mefDependencySolver);
}

MefDependencySolver的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Web.Mvc;

namespace Mvc3_MEF_WebApplication.Extension
{
public class MefDependencySolver : IDependencyResolver
{
public MefDependencySolver(CompositionContainer compositionContainer)
{
_compositionContainer = compositionContainer;
}

private readonly CompositionContainer _compositionContainer;

public object GetService(Type serviceType)
{
var name = AttributedModelServices.GetContractName(serviceType);
return _compositionContainer.GetExportedValueOrDefault<object>(name);
}

public IEnumerable<object> GetServices(Type serviceType)
{
return _compositionContainer
.GetExportedValues<object>(serviceType.FullName);
}
}
}

最后系统运行的结果如下图:

小结

总结一下所有的步骤:

1. 项目添加引用: System.ComponentModel.Composition

2. 为需要的Parts标注[Import] [Export] 等attribute

3. 创建一个CompositionContainer实例

4. 实现IDependencyResolver接口

5. 注册到DependencyResolver

更多资源

本文的实现很简单,抛砖引玉,更多内容可以参考以下资料:

1. MSDN: MEF Overview

2. MEF Programming Guide

3. MSDN Magazine: Building Composable Apps in .NET 4 with the Managed Extensibility Framework

另外StackOverflow还有很多针对MEF高级议题(importMany集合导入, lazy惰性导入, composition/AllowMultiple复合,  metaData, lifetime等高级议题。)的讨论,可以参考下。

此外,用MEF为ASP.NET MVC 创建一个ControllerFactory可以参考这篇文章。 (用Unity的可以参考Artech这篇文章。)

用MEF实现ASP.NET MVC的模块化开发有兴趣可以参考 这篇文章

本文源码下载这里

mikel阅读(1039)

[转载]淘宝API开发系列—淘宝API的测试及使用

在很久之前,由于对淘宝的API开发比较感兴趣,写了几篇关于淘宝API开发方面的随笔《淘宝API开发系列–开篇概述》和《淘宝API开发系列–商家的绑定》等文章,近期由于一客户需要一些淘宝API的例子,而我原来开发的例子已经过去两年了,之前我是基于一个中间组件top4net来进行开发的,这个模块就是在淘宝API SDK的基础上做了一些封装,不过原来的例子确已经不能运行了。

因此重新捡起行头,继续研究有啥变化的地方,不过发现虽然时间过去已经快两年了,淘宝API的使用模式,一直没有变化过,可能变化的就是API的一些细微的地方吧,因此这次,就摒弃了中间组件的方式,就直接使用淘宝官方提供的taobao-sdk-net.zip(http://dl.open.taobao.com/sdk/taobao-sdk-net.zip) 来进行开发,发现其实模式一样,操作也差不多而已,但是处理起来的细节有很多不同的地方。

为了进行淘宝的API开发,首先我们需要做下面几件事情。

1)
开发者注册一个账号,

2)然后为每个淘宝应用注册一个应用程序键(App Key) 。

3)下载淘宝API的SDK并掌握基本的API基础知识和调用,具体可以参考论坛的信息(http://dev.open.taobao.com/bbs/forum.php )里面的技术分享区等。

4)利用SDK接口和对象,传入AppKey或者必要的时候获取并传入SessionKey来进行程序开发

5)利用淘宝平台的文档中心和API测试工具,对接口进行测试。从而了解返回信息,方便程序获取。

以上是一般淘宝API应用开发的关键流程,其中通过淘宝文档中心和API测试工具,进行概念了解和接口信息查询很重要。因为这些数据就是我们需要在逐步显示出来的。淘宝的API很多,不过都分为了好几个领域,慢慢就会了解深入了。

然后我们也可以通过淘宝平台的API测试工具来了解返回的数据信息,每个淘宝API最下面一般都有一个API工具的内容,如下所示。其中我们选择【API Tools在线测试工具】就可以测试返回的接口数据了。

对于以上这些淘宝API接口,不需要Session就可以访问的,就直接利用【系统分配】的内容就可以访问并获取到数据了。注意其中红色圈中部分即可。

对于有一些用户方面的私密数据,如交易数据,买入或者卖出的数据,我们就要自定义指定自己的SessionKey了,如下所示。

卖出的信息,也需要传入SessionKey的信息,在程序中处理,得到下面的结果。

[转载]Jquery固定表头插件

mikel阅读(1183)

[转载]Jquery固定表头插件,兼容IE6.7.8.9 ,Chrome ,FF – FaceSun – 博客园.

JQuery固定表头插件,兼容IE6.7.8.9 ,Chrome ,FF  国外的哦
引入文件
<script src="jquery.min.js" type="text/javascript"> </script> 
<script src="jquery.fixedtableheader.min.js" type="text/javascript"> </script>
绑定表格,headerrowsize 后面的参数是绑定需要固定的表头的行数
<script type="text/javascript">
$(document).ready(function() { 
   $('.tbl').fixedtableheader({ 
     highlightrow: true, headerrowsize: 4
   }); 
}); 
</script>

效果:

Demo :点鸡下崽