ssy1990 21:08:05
有没有人?
青润 21:14:50
??
ssy1990 21:16:50
java编写的,那两个应用程序可以可以连接,但就是没有显示要求接收的字符

青润 21:17:55
你的表达,我看不懂。
苦行憎  21:19:38
说的详细点,是socke连接吗,还是webservices,说不清楚,青润大哥没有办法帮你解决哈
ssy1990 21:19:51
socket
ssy1990 21:19:54

苦行憎  21:20:00
否则就是浪费时间
ssy1990 21:22:49
就是客户机通过输出流对象把字符串”hello“发送到服务器
然后服务器通过输入流对象接收到”hello“,在服务器窗口显示出来,并向客户机发出确认的字符串”ok”,但是这个都没有

青润 21:24:48
这个只能看代码,你说的都是可以实现的东西,不是不可以实现的,所以,没办法帮你。
ssy1990 21:25:36
代码方面是不是缓冲区的问题?
青润 21:26:09
从这里看不出来问题。
苦行憎  21:26:25
客户端和服务端的控制台都打印了那些东西,是不是控制台没有切换,这方面的知识网上很多哈
青润 21:26:57
建议你考虑调试方式,进行单步打印,看看控制台输出信息,来判断问题在哪里
苦行憎  21:27:08
 
ssy1990 21:27:22
恩,好的,我试试,谢谢指教哈
青润 21:27:43
这是代码出现问题时侯,最常用的办法。
ssy1990 21:28:23
嗯嗯.....
谢谢了
青润 21:28:23
除非你自己分析不出来,逻辑判断出现错误,否则,一般情况下都能找到问题所在。
ssy1990 21:29:05
一般调试的好少,一遇到问题就上网查了
青润 21:29:40
调试,是程序员的基本功,这个都不做,我可以认为,你根本不会写程序。
ssy1990 21:30:32
恩恩.....
知道了,今后努力提高

 

后记:

调试的手段有很多种,这个网络上可以查到很多,就不赘述了。

很多人遇到代码问题就到处找人问,找人看代码,其实,至少百分之七八十是因为他不懂得如何调试。而且,调试是需要部署同样的环境,还需要花费大量时间,所以,我一般都拒绝给别人看代码。

另外,调试和测试不同,也有些人拿调试来替代测试,这也是常遇到的一些严重问题。

 

唐月华

posted @ 2009-04-05 23:31 silverPerson 阅读(90) 评论(1) 编辑

现在距离gmail改变大家对使用网页应用程序的方式,已经有一年多了。但是目前很多网页应用程序,并没有使用充满活力的Ajax的优势,来代替以前沉闷的html功能。

下面是当前网页应用程序应该出现的地方:

  • 基于表单的交互

表单是很慢的,非常慢。尝试编辑位于del.icio.us上面的一个书签?点击编辑链接打开一个编辑书签的表单页面,然后编辑你的内容并点击提交按钮等待整个提交过程结束,最后返回上一页并向下滚动到你刚才编辑的书签那里查看内容是否已经正确更改。那AJAX呢?点击编辑链接马上开始更改标签内容,点击提交按钮开始异步传输标签编辑的内容并立即看到更改后的内容而无需重载整个页面。

  • 深层树状导航

总而言之,带有深层树状导航的应用程序通常是一个噩梦。在大多数情况中简单平直的拓扑结构以及搜索/标记可以很好的工作。但是如果一个应用程序真正使用深层树状导航,使用JavaScript来管理拓扑ui(user interface用户接口),则使用Ajax懒加载深层数据可以降低服务器的负载。举例来说,为了阅读一个只有一行的结果来加载整个一个新页面是非常耗时的。

  • 实时用户对用户通讯

在一个允许用户创建实时讨论的信息公告系统中,迫使用户一次又一次的更新完页面看到答复是非常愚蠢的。回复应该是实时的,用户不应被迫总是去痴迷于刷新操作。即使是gmail这个已经对以前像hotmail/yahoo mail的收件箱刷新,刷新收件箱标记的操作有所改进,也并没有充分的使用Ajax的功能来提示有新邮件到达。

  • 投票、是否选择、等级评价

如果Ajax提交过程没有一个协调的UI提示是非常糟糕的,通过使用Ajax来提交一个调查或是否选择可以减少提交过程等待的痛苦。通过减少点击的等待时间,Ajax应用程序变得越来越有交互性-如果要用40秒来提交一个投票,除非非常在意的话大多数人会选择放弃。如果只花1秒呢,非常大比例的人会乐于参加投票的。(我在Netflix versus有2008张电影投票在IMDb.com有210张电影投票)

  • 过滤和复杂数据操作

应用一个过滤、按日期排序、按日期和姓名排序、打开或关闭过滤器等等。任何一种高交换型操作应该交给JavaScript来处理而不是通过向服务器来提交一系列的请求。在查找或者操作大量数据的时候带来的视图上的改变最多不会超过30秒,Ajax真的使这些操作加速了。

  • 普通录入时的提示/自动补齐

一些软件/JavaScript是擅长于帮助用户完成键入相同的文字或可以预测的文字的工作的。在del.icio.us 和 Gmail 中该功能是非常有益的,可以用来快速增加标记/email等。

对于一个频繁使用的应用程序诸如网页邮件客户端或博客阅读器来说,用户有充足的时间来学习如何使用新的UI概念但是他们却无法接受一个非常缓慢 的反应速度。这种应用为Ajax变的更加普及起到了一个完美的杠杆作用。随着用户使用频率的增加,更多的Ajax部件应该加强用户的使用体验。

但是对于网页应用程序来说,把每件事甚至任何事都用JavaScript来实现也是没有意义的。Ajax只是针对一些特定的环境才能带来显著的 帮助。在Ajax出现之前网页应用程序已经可以工作的很好了并且目前在网页开发中Ajax还存在着许多的缺陷和缺点。就算不从服务器端取得一个异步的信息 数据流一个平直的html网页日志也可以工作的很好。对于文档或文档之间的跳转来说,老旧的纯HTML仍然是最好的选择。简单或很少使用的应用程序就算不 用JavaScript同样可以很好的工作。

下面是一些不应该用到Ajax的地方:

  • 简单的表单

就算表单是Ajax技术的最大受益人,一个简单内容的表单,或提交订货单,或一次性的很少用到的表单都不应该使用以Ajax驱动的表单提交机制。总的来说,如果一个表单不是很长用,或已经工作的很好,那么就算使用Ajax也没有什么帮助。

  • 搜索

实时搜索带来的痛苦要远大于他带来的帮助。这就是为什么Google Suggest还处于beta测试而并没有放在主页上的原因。在Start.com Live.com上搜索的时候你是不能使用返回按钮来查看上一次搜索或返回上一页的。或许还没有人来完成这项工作,但是完成这个工作应该是很困难的至少是不太明知的或者会因此带来更多的麻烦。(译注:现在已经有很多开源的框架可以实现历史记录功能)

  • 基本导航

总的来说,使用Ajax为一个基础的网站/程序做导航是一个可怕的念头。谁会把用来使自己的程序变的更好的时间花在编写代码模仿浏览器的行为上面?在基础页面中导航的操作中JavaScript是没有用的。

  • 替换大量的信息

Ajax可以不用整页刷新来动态更新页面中改变的一小部分。但是如果一页上的大部分内容都需要更新,那为什么不从服务器那里获得一个新页面呢?

  • 显示操作

虽然看上去Ajax是一个纯UI技术,其实不是这样的。他实际上是一个数据同步、操作、传输的技术。要想得到一个稳定的干净的网页程序,不使用Ajax/JavaScript来直接完成用户接口是明智的。JavaScript可以分散分布并简单的操作XHTML/HTML DOM,根据CSS规则来决定如何让UI显示数据。查看

这里http://www.sourcelabs.com/blogs/ajb/2005/08/powering_javascript_ui_with_cs.html

来查看如何使用CSS来替代JavaScript来控制数据的显示。

  • 无用的网页小部件

滑块选择控件、拖拽控件、弹性控件(此处原文为bouncies,不知指为何物?)、鼠标样式、天气预报控件,这些小部件应该可以被更直接的控件代替或者为了整洁干脆整个去掉。为了选择一种颜色,也许滑块选择控件可以选择一个正确的阴影颜色,但是在一个商店中选择一个价格,使用滑块选择控件选到分这个单位对于用户来说有点过分。

 

唐月华

posted @ 2009-04-05 23:30 silverPerson 阅读(65) 评论(0) 编辑
  1. $() = $(document)  
  2. //实现window.onload()效果  
  3. $().ready(  
  4.     function(){  
  5.         //需要执行的内容  
  6.     }  
  7. );  
  8. //获取DOM元素(返回值为jQuery对象)  
  9. $("element"//相应元素名的  
  10. $(".classname"//class值匹配的  
  11. $("element.classname"//相应元素中,class值匹配的  
  12. $("#id"//id匹配的  
  13. $("element#id"//相应元素中,id匹配的  
  14. $("element1 > element2"//元素一 下 的所有元素二(只包括儿子)  
  15. $("element1 element2")      //元素一 中 的所有元素二(包括子孙等)  
  16. $("element1 + element2")    //元素一 后 的所有元素二(代码后)  
  17. $("element1 ~ element2")    //与元素一 并列 的所有元素二(兄弟元素二)  
  18. $("#id").html("")   //设置 getElementById("id").innerHTML = ""  
  19. $("#id").html()     //取出 getElementById("id").innerHTML  
  20. //动画出现效果  
  21. $("#id").show(speed, [callback])  
  22. $("#id").slideDown(speed, [callback])  
  23. ……  
  24.   
  25. /*========= 
  26.  2009-1-16 
  27. =========*/  
  28. //在<p>外面包围另一个结构(html代码/元素)  
  29. $("p").wrap("<div class='wrap'></div>")  
  30. $("p").wrap(document.getElementById('content'))  
  31. $("p").append("<b>Hello</b>");  //<p>I would like to say: <b>Hello</b></p>  
  32. $("p").prepend("<b>Hello</b>"); //<p><b>Hello</b>I would like to say: </p>  
  33. $("p").before("<b>Hello</b>");  //<b>Hello</b><p>I would like to say: </p>  
  34. $("p").after("<b>Hello</b>");   //<p>I would like to say: </p><b>Hello</b>   
  35. //【删除相应class的p元素】  
  36. //<p class="classname">AAA</p> BBB <p>CCC</p>  
  37. //BBB <p>CCC</p>  
  38. $("p").remove(".classname");  
  39. /*========= 
  40.  2009-1-18 
  41. =========*/  
  42. //获取具有某属性值的相应元素  
  43. $("input[name=qq]"//获取<input name="qq" type="text" />元素  
  44. //属性与值关系  
  45. =   //等于  
  46. *=  //包含该值  
  47. !=  //不包含该值  
  48. ^=  //以该值开头  
  49. $=  //以该值结尾  
  50. //为每一个匹配的元素执行该函数  
  51. $("element").each(function(){  
  52.     //需要执行的内容  
  53. })    
  54. /*========= 
  55.  2009-1-19 
  56. =========*/  
  57. /* 
  58. jQuery中用post和get方法 
  59. (ajax高层抽象方法,对ajax方法进行了封装) 
  60. 【当JQ中用post方式】 
  61. PHP用$_POST接收时,只有n2 
  62. PHP用$_GET接收时,只有n1 
  63. 【当JQ中用get方式】 
  64. PHP用$_GET接收,n1 n2都有 
  65. PHP用$_POST接收时,都没有 
  66. */  
  67. $.post("do.php?n1=a", {n2: "b"},      
  68.     function(data){  
  69.         ;  
  70.     }  
  71. );  
  72. /*========= 
  73.  2009-1-20 
  74. =========*/  
  75. //DOM对象 -> jQuery对象  
  76. //$(DOM对象)  
  77. var v = document.getElementById("id");  //DOM对象 v   
  78. var $v = $(v); //jQuery对象 $v  
  79. //jQuery对象 -> DOM对象  
  80. //jQuery对象.get(0) 或者 jQuery对象[0]  
  81. var $v = $("#id");  //jQuery对象 $v  
  82. var v = $v.get(0); //DOM对象 v  
  83. var v = $v[0]; //DOM对象 v  
  84. $("element").get(); //获取指定元素的集合  
  85. //jQuery用ajax方法(ajax低层方法)  
  86. $.ajax({  
  87.     type:   "POST"//POST时PHP中用$_POST接收,GET反之。  
  88.     url:    "do.php",  
  89.     data:   "n1="+x+"&n2="+y,  
  90.     success: function(data){ ; }   
  91. });  
  92. /*========= 
  93.  2009-1-21 
  94. =========*/  
  95. //序列表表格内容为请求字符串  
  96. //返回值:(例)name=linvo&age=22  
  97. $("form").serialize() //序列化整个表单元素内容  
  98. $("input[type=text]").serialize() //序列化指定元素内容(例)  
  99. $("element").empty(); //移除指定元素下所有元素  
  100. /* 
  101.  CSS设置 
  102. */  
  103. $("element").addClass("classname"); //为指定元素添加css样式  
  104. $("element").removeClass("classname"//移除指定元素的css样式  
  105. $("element").toggleClass("classname"//指定元素的css样式,有则删除,无则添加  
  106. $("element").css("attname"); //获取指定元素相应属性的值(attname例:color)  
  107. $("element").css("attname","value"); //设置……属性值(例:"color","#FF0000")  
  108. $("element").css({ "margin-left""10px""background-color""blue" });   
  109. //使用“名/值对”进行批量设置……(例子见自身)  
  110. /*========= 
  111.  2009-1-22 
  112. =========*/  
  113. $("element1").next(element2) //与指定元素一 紧邻 的指定元素二  
  114. $("element1").parent().is(element2) //元素一的父元素在元素二的集合中吗   
  115. //模仿鼠标悬停事件  
  116. //hover(over,out)  
  117. //over:在上方执行 | out:移出时执行  
  118. $("element").hover(  
  119.     function(){  
  120.         //在上方执行  
  121.     }, function(){  
  122.         //移出时执行  
  123.     }  

Lad.li
posted @ 2009-04-05 23:29 silverPerson 阅读(50) 评论(0) 编辑
大多数IT安全事件(如补丁程序或网络攻击等)都与软件编程错误有关,在过去的三年中,非赢利调研机构MITRE和美国系统网络安全协会(SANSInstitute)发现了700多处常见的软件编程错误,经过安全专家的筛选,最终于周一公布了以下25大软件编程错误:

  1. 错误的输入验证

  2. 不正确的编码或转义输出

  3. 维持SQL查询结构(SQL注入)错误

  4. 维持网页结构(跨站点脚本)错误

  5. 维持操作系统命令结果(操作系统命令注入)错误

  6. 明文传送敏感信息

  7. 跨站点请求伪造

  8. 资源竞争(Race condition)

  9. 错误信息泄露

  10. 限定缓冲区内操作失败

  11. 外部控制重要状态数据

  12. 外部控制文件名或路径

  14. 不可信搜索路径

  15. 控制代码生成错误(代码注入)

  15. 下载未经完整性检查的代码

  16. 错误的资源关闭或发布

  17. 不正确的初始化

  18. 错误计算

  19. 可渗透防护

  20. 使用被破解的加密算法

  21. 硬编码密码

  22. 对核心资源的错误权限分配

  23. 随机值的错误利用

  24. 滥用特权操作

  25. 客户端执行服务器端安全
From:http://news.cnblogs.com/n/44418/
Lad.li
posted @ 2009-04-05 23:28 silverPerson 阅读(46) 评论(0) 编辑

昨天看Scott Guthrie在博客上去.net 3.5和Vs2008的介绍.我看国内已经有人翻译过来哦.我把相关的地址和资料发上和大家分享

这里我主要想谈的是Asp.net AJAX在.net 3.5中的安装,在.net 3.5中自己就带有AJAX Extensions 1.0中的的几个控件的模版,而没有控件,所以就不能在Vs2008的Toolbox中显示.但如果要在工具箱中将这几个控件显示出来,如原来在 vs2005中一样,就要像以前添加AJAX toolkit一样将System.Web.Extensions.dll添加进来.如下
(1)打开一个Web Form
(2)在工具箱点Right-click选择"Add Tab0"
(3)给你新名字如"AJAx Extensions 1.0"
(4)Right click 选者"Choose Item"

(5)点浏览..位置是\Program Files\Microsoft ASP.NET\ASP.NET 2.0 AJAX Extensions\v1.0.61025下,选择System.Web.Extensions.dll,打开

(6)选中这些控件点"OK";


最后就是这样..但你要注意你要下支持.net 3.5 AJAX Extensions1.0;

 

 

而AJAX toolkit就要从新下载安装方法和以前一样如:只是下载时候要注意下的是:

 AjaxControlToolkit-Framework3.5.zip

AjaxControlToolkit-Framework3.5-NoSource.zip
 
这个是一些资料:
http://blogs.msdn.com/webdevtools/archive/2007/07/30/using-vs-2008-to-target-asp-net-ajax-1-0.aspx
http://dev.yesky.com/topic/484/7623484.shtml
http://weblogs.asp.net/scottgu/archive/2007/07/26/vs-2008-and-net-3-5-beta-2-released.aspx

转自:works guo!
posted @ 2009-04-05 23:27 silverPerson 阅读(163) 评论(0) 编辑

<%@ Page language="C#" MasterPageFile="~/MasterPage.master" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
  <ajax:ajaxpanel ID="Ajaxpanel1" runat="server">
  <fieldset>
    <legend>Windows Processes (list is updated every 10 seconds using Callback Timer)</legend>
    <i>This example demonstrates the use of the MagicAjax CallbackTimer. <br />For this example we've set the Callback timer in the Page_Load event (hint: click 'View Source' at the bottom of this page to see the complete source of this aspx file).</i><br /><br />
    <div style="overflow:auto;height:400px;width:325px">
    <asp:DataGrid AutoGenerateColumns="false" AllowSorting="True" OnSortCommand="grid_SortCommand" runat="server" ID="DataGrid1" BackColor="White" BorderColor="#E7E7FF" BorderStyle="None" BorderWidth="1px" CellPadding="5" GridLines="Horizontal" >
      <FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" />
      <SelectedItemStyle BackColor="#738A9C" Font-Bold="True" ForeColor="#F7F7F7" />
      <PagerStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Right" Mode="NumericPages" />
      <AlternatingItemStyle BackColor="#F7F7F7" />
      <ItemStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" />
      <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#F7F7F7" />
      <Columns>
        <asp:BoundColumn DataField="ProcessName" SortExpression="ProcessName" HeaderText="Image Name" />
        <asp:BoundColumn DataField="PhysicalMemory" SortExpression="PhysicalMemory" HeaderText="Mem Usage" DataFormatString="{0:###,###,###} K" />
        <asp:BoundColumn DataField="HandleCount" SortExpression="HandleCount" HeaderText="Handles" DataFormatString="{0:###,###}" />
      </Columns>
    </asp:DataGrid>
    </div>
  </fieldset>
  </ajax:ajaxpanel>
</asp:Content>

<script language="C#" runat="server">
  private void Page_Load(object sender, EventArgs e)
  {
    if (!IsPostBack)
    {
      // For automatic CallBack every 10 seconds.
      MagicAjax.AjaxCallHelper.SetAjaxCallTimerInterval(10000);
    }
    ShowProcesses();
  }

  private void ShowProcesses()
  {
    System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcesses();

    System.Data.DataTable dt = new System.Data.DataTable("Processes");
    dt.Columns.Add("ProcessName");
    dt.Columns.Add("PhysicalMemory", typeof(Int64));
    dt.Columns.Add("HandleCount", typeof(Int32));

    foreach (System.Diagnostics.Process process in processes)
    {
      dt.Rows.Add(new object[] {process.ProcessName, process.WorkingSet64 /1000, process.HandleCount });
    }

    System.Data.DataView dv = dt.DefaultView;

    //sort data
    dv.Sort = SortExpression;

    //bind data
    DataGrid1.DataSource = dv;
    DataGrid1.DataBind();
  }

   /// <summary>
   /// SortExpression of the grid (stored in ViewState!)
   /// </summary>
   private string SortExpression
   {
     get
     {
       if (ViewState["_grid_SortExpression"] != null)
       {
         return (string)ViewState["_grid_SortExpression"];
       }
       else
       {
            return "PhysicalMemory desc"; //default
       }
     }
     set
     {
       ViewState["_grid_SortExpression"] = value;
     }
   }

   private void grid_SortCommand(object source, DataGridSortCommandEventArgs e)
   {
      string[] currentSort = SortExpression.Split(' ');
     
      if (currentSort[0] == e.SortExpression)
      {
        SortExpression = string.Format("{0} {1}", e.SortExpression, currentSort[1] == "desc" ? "asc" : "desc");
      }
      else
      {
        SortExpression = e.SortExpression + " asc";
      }

     //refill datagrid
    ShowProcesses();
   }
</script>

 

Lad.li

posted @ 2009-04-05 23:25 silverPerson 阅读(47) 评论(0) 编辑
   假设我们公司有两种程序员:VB程序员,指的是用VB写程序的程序员,用clsVBProgramer这个类表示;Delphi程序员指的是用Delphi写程序的程序员,用clsDelphiProgramer这个类来表示。 每个类都有一个WriteCode()方法。定义如下:

class clsVBProgramer()
{
  ....
  WriteCode()
  {
     //用VB语言写代码;
  }
  ....
}

class clsDelphiProgramer()
{
  ....
  WriteCode()
  {
    //用Delphi语言写代码;
  }
   ....
}

现在公司来了一个项目,要求派某个程序员写一个程序。
class clsProject()
{
  ....
  WritePrograme(clsVBProgramer programer)//用VB写代码
  {
    programer.WriteCode();
  }
  WritePrograme(clsDelphiProgramer programer)//重载方法,用Delphi写代码
  {
    programer.WriteCode();
  }
 ......
}
在主程序中我们可以这样写:
main()
{
   clsProject proj=new  clsProject;
   //如果需要用VB写代码
   clsVBProgramer programer1=new clsVBProgramer;
   proj.WritePrograme(programer1);
   //如果需要用Delphi写代码
   clsDelphiProgramer programer2=new clsDelphiProgramer;
   proj.WritePrograme(programer2);
}

但是如果这时公司又来了一个C#程序员,我们怎么改这段程序,使它能够实现用C#写程序的功能呢?我们需要增加一个新类clsCSharpProgramer,同时在此clsProject这个类中要再次重载WritePrograme(clsCSharpProgramer programer)方法。这下麻烦多了。如果还有C程序员,C++程序员,JAVA程序员呢。麻烦大了!

但是如果改用接口,就完全不一样了:
首先声明一个程序员接口:
interface IProgramer()
{
  WriteCode();
}
然后声明两个类,并实现IProgramer接口:
class clsVBProgramer():IProgramer
{
  ....
  WriteCode()
  {
     //用VB语言写代码;
  }
  ....
}

class clsDelphiProgramer():IProgramer
{
  ....
  WriteCode()
  {
    //用Delphi语言写代码;
  }
   ....
}
对clsProject这个类进行一下修改:
class clsProject()
{
  ....
  WritePrograme(IProgramer programer)
  {
    programer.WriteCode();//写代码
  }
  ......
}

main()
{
   clsProject proj=new  clsProject;
   IProgramer programer;
   //如果需要用VB写代码
   programer=new clsVBProgramer;
   proj.WritePrograme(programer);
   //如果需要用Delphi写代码
   programer=new clsDelphiProgramer;
   proj.WritePrograme(programer);    
}
如果再有C#,C,C++,JAVA这样的程序员添加进来的话,我们只需把它们相关的类加进来,然后在main()中稍做修改就OK了。扩充性特别好!

另外我们如果把clsProject这个类封成一个组件,那么当我们的用户需要要扩充功能的时候,我们只需要在外部做很小的修改就能实现,可以说根本就用不着改动我们已经封好组件!是不是很方便,很强大!
Lad.li
posted @ 2009-04-05 23:21 silverPerson 阅读(51) 评论(0) 编辑

在开发Web应用时,无一例外地需要访问数据库,以完成对数据的查询、插入、更新、删除等操作。受应用逻辑的影响,有时需要将多条数据库操作指令组成一个工作单元(事务)。在数据库中,所谓事务是指一组逻辑操作单元,它使数据从一种状态变换到另一种状态。为确保数据库中数据的一致性,应当用离散的成组的逻辑单元操作数据:当它全部完成时,数据的一致性可以保持;而当单元中的一部分操作失败时,整个事务会被全部忽略,所有从起始点以后的操作全部退回到开 始状态。
实际上,在默认方式下对数据库的每一次操作都是隐含的事务处理。本文以一个典型的用户注册程序为例,介绍三种利用 ASP实现事务处理的方法:基于ASP数据库组件的解决方法、基于数据库内部的事务处理机制的解决方法和基于MTS组件的解 决方法。

程序功能
在SQL Server数据库中建立两个表:USER表和USERDOC表。其中USER表中存放的是注册用户的用户名和密码,USERDOC表中存放的是该注册用户的个人资料,并且以用户名为索引。下面是表USER和USERDOC的定义:
Create Table USER(userName varchar(30),userPasswd varchar(30))
Create Table USERDOC(userName varchar(30),Age int,Sex int,PhoneNumber varchar(20),Address varchar(50))
当用户请求注册时,ASP脚本先将用户名和密码插入到USER表中,然后在USERDOC表中插入用户个人信息(年龄、性别、联系电话和家庭住址等)。同时,应用程序还必须保证USER表中的每一条记录在USERDOC表中都有相应的记录。
方法一
利用ASP内置ADO组件中的Connection对象可以实现对数据库操作的事务性处理。Connection对象的部分方法如下:
●Connection.BeginTrans方法:启动一个事务;
●Connection.CommitTrans方法:完成/提交一个事务;
●Connection.RollBackTrans方法:撤消/放弃一个事务。
//启动一个事务操作
<% Conn.BeginTrans %>
<% sqlText=“Insert into USER(userName,userPasswd) values(‘” %>
<% sqlText=sqlText & request(“usrName”) & “’,‘”&request(“usrPasswd”)&“’) ” %>
<% conn.execute(sqlText) %>
<% if conn.Errors.Count>0 then %>
<% conn.Errors.Clear %>
//如果插入数据操作失败,则事务向前回滚
<% conn.RollBackTrans %>
<% response.Redirct RegisterFail.html %>
<% end if %>
<% sqlText=“Insert into USERDOC(userName,Age,Sex,PhoneNumber,Address) ”%>
<% sqlText=sqlText & “values(‘”& request
(“usrName”) & “’, ” & request(“Age”) %>
<% sqlText=sqlText & “,‘” & request
(“PhoneNum”) & “’,‘” %>
<% sqlText=sqlText & request(“Address”) & “’) ” %>
//执行事务单元中的第二条插入语句
<% conn.execute(sqlText) %>
<% if conn.Errors.Count>0 then %>
<% conn.Errors.Clear %>
//如果操作失败,则事务向前回滚
<% conn.RollBackTrans %>
<% response.Redirct RegisterFail.html %>
<% end if %>
//如果整个事务操作执行正确,则提交事务
<% Conn.CommitTrans %>
//转向注册成功处理页面
<% response.Redirct RegisterOk.html %>
方法二
可以利用数据库系统内部的事务处理机制,通过在数据库服务器中编写包含事务的存储过程,完成对数据操作的事务处理。同时,利用ADO组件调用存储过程,还可以根据存储过程的返回代码判断事务处理是否执行成功。
在数据库系统中,每一条SQL语句都是一个事务。因此可以保证每条语句要么完成,要么退回到开始之处。但是如果希望一组SQL语句的操作要么全部完成,要么全部无效,就需要利用数据库的事务处理机制来实现。
在数据库中生成存储过程的主要代码如下:
Create proc RegisterUser
(@usrName varchar(30), @usrPasswd varchar(30),@age int, @PhoneNum varchar(20), @Address varchar(50) )
as
begin
//显示定义并开始一个事务
begin tran
insert into USER(userName,userPasswd) values(@usrName,@usrPasswd)
if @@error<>0
begin
//操作失败,则事务回滚
rollback tran
//返回存储过程,并设置返回码为事务操作失败
return -1
end
insert into USERDOC(userName,age,sex,PhoneNumber,Address)
values(@Usrname,@age,@PhoneNum,@Address)
if @@error<>0
begin
//操作失败,则事务回滚
rollback tran
return -1
end
//如果操作执行正确,则提交事务
commit tran
return 0
end
在ASP脚本中调用数据库存储过程的主要代码如下:
<% Set Comm=server.CreateObject
(“ADODB.Command”) %>
<% Set Comm.ActiveConnection=conn %>
<% Comm.CommandType=adCmdStoredProc %>
<% Comm.CommandText=“RegisterUser” %>
//创建存储过程返回参数对象
<% Set RetCode=Comm.CreateParameter
(“RetCode”,adInteger,adParamReturnValue) %>
//创建存储过程输入参数对象
<% Set usrName=Comm.CreateParameter
(“usrName”,adVarchar,adParamInput,30) %>
<% Set usrPwd=Comm.CreateParameter
(“usrPasswd”,adVarchar,adParamInput,30) %>
<% Set age=Comm.CreateParameter(“age”,adInteger,adParamInput) %>
<% Set PhoneNum=Comm.CreateParameter
(“PhoneNum”,adVarchar,adParamInput, 20) %>
<% Set Address=Comm.CreateParameter(“Address”,adVarchar,adParamInput,50) %>
<% Comm.Parameters.Append usrName %>
<% Comm.Parameters.Append usrPwd %>
<% Comm.Parameters.Append age %>
<% Comm.Parameters.Append PhoneNum %>
<% Comm.Parameters.Append Address %>
<% Comm.Parameters(“usrName”)=request
(“usrName”) %>
<% Comm.Parameters(“usrPasswd”)=request
(“usrPasswd”) %>
<% Comm.Parameters(“age”)=request(“age”) %>
<% Comm.Parameters(“PhoneNum”)=request
(“PhoneNum”) %>
<% Comm.Parameters(“Address”)=request
(“Address”) %>
<% Comm.Execute %>
<% RetValue=Cint(Comm(“RetCode”)) %>
//根据数据库存储过程返回代码判断注册是否成功
<% if RetValue< 0 then %>
<% response.Redirect RegisterFail.html %>
<% else %>
<% response.Redirect RegisterOk.html %>
<% end if %>
方法三
利用MTS(Microsoft Transaction Server)组件的事务处理机制实现事务处理时,需要特别注意的是,这种机制下的事务不能跨越多个ASP页,如果一个事务处理需要来自多个组件的对象,则须将对这些对象的操作组合在一个ASP页中。
首先需要在页首添加指令@TRANSACTION,将一个ASP页面声明为事务性。@TRANSACTION指令必须在一页中的第一行,否则将产生错误。当页面中ASP脚本处理结束时,当前事务即告结束。
<%@ TRANSACTION=Required Language=
VB Script %>
//事务执行成功触发事件
<% Sub OnTransactionCommit() %>
<% response.Redirect RegisterOk.html %>
<% End Sub %>
//事物执行失败触发事件
<% Sub OnTransactionAbort() %>
<% response.Redirect RegisterFail.html %>
<% End Sub %>
<% sqlText=“Insert into USER(userName,userPasswd) values(‘” %>
<% sqlText=sqlText & request(“usrName”) & “’,‘” &request(“usrPasswd”)&“’) ” %>
<% conn.execute(sqlText) %>
<% if conn.Errors.Count>0 then %>
<% conn.Errors.Clear %>
<% ObjectContext.SetAbort %>
<% end if %>
<% sqlText=“Insert into USERDOC(userName,Age,Sex,PhoneNumber,Address) ”%>
<% sqlText=sqlText & “values(‘” & request
(“usrName”)& “’, ” & request(“Age”) %>
<% sqlText=sqlText & “,’” & request
(“PhoneNum”) & “’,‘” %>
<% sqlText=sqlText & request(“Address”) & “’) ” %>
<% conn.execute(sqlText) %>
<% if conn.Errors.Count>0 then %>
<% conn.Errors.Clear %>
<% ObjectContext.SetAbort %>
<% end if %>
<% ObjectContext.SetComplete %>
方案比较
从灵活的角度考虑,选择采用ASP数据库组件的方法具有一定的优势:既可以选用ADO数据库组件完成事务处理,同时还可以根据实际需要,定制自己的数据库组件(只要满足ASP组件编写规范即可)。如果从数据库事务处理的可靠性等角度考虑,则采用数据库内部的事务处理存储过程更好。这样可以直接利用数据库事务机制完成应用程序的逻辑事务处理,安全可靠,并且减少了Web服务器与数据库服务器之间的数据交互。这一点对分布式数据库系统尤为重要。采用MTS组件的事务处理方法的优势在于:由MTS服务器直接控制和管理组件(在MTS中注册的组件)操作的完成和撤消,具有良好的扩展空间和应用前景,可以充分发挥MTS的技术优势,增强网络应用的容错性能,提高IIS Web服务器的动态性能。

张海

posted @ 2009-04-05 23:00 silverPerson 阅读(75) 评论(0) 编辑

6个你必须用到AJAX的地方与6个不必用到的地方

现在距离gmail改变大家对使用网页应用程序的方式,已经有一年多了。但是目前很多网页应用程序,并没有使用充满活力的Ajax的优势,来代替以前沉闷的html功能。

下面是当前网页应用程序应该出现的地方:

  • 基于表单的交互

表单是很慢的,非常慢。尝试编辑位于del.icio.us上面的一个书签?点击编辑链接打开一个编辑书签的表单页面,然后编辑你的内容并点击提交按钮等待整个提交过程结束,最后返回上一页并向下滚动到你刚才编辑的书签那里查看内容是否已经正确更改。那AJAX呢?点击编辑链接马上开始更改标签内容,点击提交按钮开始异步传输标签编辑的内容并立即看到更改后的内容而无需重载整个页面。

  • 深层树状导航

总而言之,带有深层树状导航的应用程序通常是一个噩梦。在大多数情况中简单平直的拓扑结构以及搜索/标记可以很好的工作。但是如果一个应用程序真正使用深层树状导航,使用JavaScript来管理拓扑ui(user interface用户接口),则使用Ajax懒加载深层数据可以降低服务器的负载。举例来说,为了阅读一个只有一行的结果来加载整个一个新页面是非常耗时的。

  • 实时用户对用户通讯

在一个允许用户创建实时讨论的信息公告系统中,迫使用户一次又一次的更新完页面看到答复是非常愚蠢的。回复应该是实时的,用户不应被迫总是去痴迷于刷新操作。即使是gmail这个已经对以前像hotmail/yahoo mail的收件箱刷新,刷新收件箱标记的操作有所改进,也并没有充分的使用Ajax的功能来提示有新邮件到达。

  • 投票、是否选择、等级评价

如果Ajax提交过程没有一个协调的UI提示是非常糟糕的,通过使用Ajax来提交一个调查或是否选择可以减少提交过程等待的痛苦。通过减少点击的等待时间,Ajax应用程序变得越来越有交互性-如果要用40秒来提交一个投票,除非非常在意的话大多数人会选择放弃。如果只花1秒呢,非常大比例的人会乐于参加投票的。(我在Netflix versus有2008张电影投票在IMDb.com有210张电影投票)

  • 过滤和复杂数据操作

应用一个过滤、按日期排序、按日期和姓名排序、打开或关闭过滤器等等。任何一种高交换型操作应该交给JavaScript来处理而不是通过向服务器来提交一系列的请求。在查找或者操作大量数据的时候带来的视图上的改变最多不会超过30秒,Ajax真的使这些操作加速了。

  • 普通录入时的提示/自动补齐

一些软件/JavaScript是擅长于帮助用户完成键入相同的文字或可以预测的文字的工作的。在del.icio.us 和 Gmail 中该功能是非常有益的,可以用来快速增加标记/email等。

对于一个频繁使用的应用程序诸如网页邮件客户端或博客阅读器来说,用户有充足的时间来学习如何使用新的UI概念但是他们却无法接受一个非常缓慢 的反应速度。这种应用为Ajax变的更加普及起到了一个完美的杠杆作用。随着用户使用频率的增加,更多的Ajax部件应该加强用户的使用体验。

但是对于网页应用程序来说,把每件事甚至任何事都用JavaScript来实现也是没有意义的。Ajax只是针对一些特定的环境才能带来显著的 帮助。在Ajax出现之前网页应用程序已经可以工作的很好了并且目前在网页开发中Ajax还存在着许多的缺陷和缺点。就算不从服务器端取得一个异步的信息 数据流一个平直的html网页日志也可以工作的很好。对于文档或文档之间的跳转来说,老旧的纯HTML仍然是最好的选择。简单或很少使用的应用程序就算不 用JavaScript同样可以很好的工作。

下面是一些不应该用到Ajax的地方:

  • 简单的表单

就算表单是Ajax技术的最大受益人,一个简单内容的表单,或提交订货单,或一次性的很少用到的表单都不应该使用以Ajax驱动的表单提交机制。总的来说,如果一个表单不是很长用,或已经工作的很好,那么就算使用Ajax也没有什么帮助。

  • 搜索

实时搜索带来的痛苦要远大于他带来的帮助。这就是为什么Google Suggest还处于beta测试而并没有放在主页上的原因。在Start.com Live.com上搜索的时候你是不能使用返回按钮来查看上一次搜索或返回上一页的。或许还没有人来完成这项工作,但是完成这个工作应该是很困难的至少是不太明知的或者会因此带来更多的麻烦。(译注:现在已经有很多开源的框架可以实现历史记录功能)

  • 基本导航

总的来说,使用Ajax为一个基础的网站/程序做导航是一个可怕的念头。谁会把用来使自己的程序变的更好的时间花在编写代码模仿浏览器的行为上面?在基础页面中导航的操作中JavaScript是没有用的。

  • 替换大量的信息

Ajax可以不用整页刷新来动态更新页面中改变的一小部分。但是如果一页上的大部分内容都需要更新,那为什么不从服务器那里获得一个新页面呢?

  • 显示操作

虽然看上去Ajax是一个纯UI技术,其实不是这样的。他实际上是一个数据同步、操作、传输的技术。要想得到一个稳定的干净的网页程序,不使用Ajax/JavaScript来直接完成用户接口是明智的。JavaScript可以分散分布并简单的操作XHTML/HTML DOM,根据CSS规则来决定如何让UI显示数据。查看

这里http://www.sourcelabs.com/blogs/ajb/2005/08/powering_javascript_ui_with_cs.html

来查看如何使用CSS来替代JavaScript来控制数据的显示。

  • 无用的网页小部件

滑块选择控件、拖拽控件、弹性控件(此处原文为bouncies,不知指为何物?)、鼠标样式、天气预报控件,这些小部件应该可以被更直接的控件代替或者为了整洁干脆整个去掉。为了选择一种颜色,也许滑块选择控件可以选择一个正确的阴影颜色,但是在一个商店中选择一个价格,使用滑块选择控件选到分这个单位对于用户来说有点过分。

 

_cedar.zhao

posted @ 2009-04-05 19:23 silverPerson 阅读(8) 评论(0) 编辑

转载自:http://zhidao.baidu.com/question/8980561.html

MVC本来是存在于Desktop程序中的,M是指数据模型,V是指用户界面,C则是控制器。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据你可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。

模型-视图-控制器(MVC)是Xerox PARC在八十年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已被广泛使用。最近几年被推荐为Sun公司J2EE平台的设计模式,并且受到越来越多的使用 ColdFusion 和 PHP 的开发者的欢迎。模型-视图-控制器模式是一个有用的工具箱,它有很多好处,但也有一些缺点。
MVC如何工作

MVC是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。

视图
视图是用户看到并与之交互的界面。对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括Macromedia Flash和象XHTML,XML/XSL,WML等一些标识语言和Web services.

如何处理应用程序的界面变得越来越有挑战性。MVC一个大的好处是它能为你的应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。

模型
模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。例如它可能用象EJBs和ColdFusion Components这样的构件对象来处理数据库。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。

控制器
控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后用确定用哪个视图来显示模型处理返回的数据。

现在我们总结MVC的处理过程,首先控制器接收用户的请求,并决定应该调用哪个模型来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层呈现给用户。
为什么要使用 MVC

大部分Web应用程序都是用像ASP,PHP,或者CFML这样的过程化语言来创建的。它们将像数据库查询语句这样的数据层代码和像HTML这样的表示层代码混在一起。经验比较丰富的开发者会将数据从表示层分离开来,但这通常不是很容易做到的,它需要精心的计划和不断的尝试。MVC从根本上强制性的将它们分开。尽管构造MVC应用程序需要一些额外的工作,但是它给我们带来的好处是无庸质疑的。

首先,最重要的一点是多个视图能共享一个模型,正如我所提及的,现在需要用越来越多的方式来访问你的应用程序。对此,其中一个解决之道是使用MVC,无论你的用户想要Flash界面或是 WAP 界面;用一个模型就能处理它们。由于你已经将数据和业务规则从表示层分开,所以你可以最大化的重用你的代码了。

由于模型返回的数据没有进行格式化,所以同样的构件能被不同界面使用。例如,很多数据可能用HTML来表示,但是它们也有可能要用Macromedia Flash和WAP来表示。模型也有状态管理和数据持久性处理的功能,例如,基于会话的购物车和电子商务过程也能被Flash网站或者无线联网的应用程序所重用。

因为模型是自包含的,并且与控制器和视图相分离,所以很容易改变你的应用程序的数据层和业务规则。如果你想把你的数据库从MySQL移植到Oracle,或者改变你的基于RDBMS数据源到LDAP,只需改变你的模型即可。一旦你正确的实现了模型,不管你的数据来自数据库或是LDAP服务器,视图将会正确的显示它们。由于运用MVC的应用程序的三个部件是相互对立,改变其中一个不会影响其它两个,所以依据这种设计思想你能构造良好的松偶合的构件。

对我来说,控制器的也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择模型进行处理,然后选择视图将处理结果显示给用户。

MVC的缺点
MVC的缺点是由于它没有明确的定义,所以完全理解MVC并不是很容易。使用MVC需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。

你将不得不花费相当可观的时间去考虑如何将MVC运用到你的应用程序,同时由于模型和视图要严格的分离,这样也给调试应用程序到来了一定的困难。每个构件在使用之前都需要经过彻底的测试。一旦你的构件经过了测试,你就可以毫无顾忌的重用它们了。

根据我个人经验,由于我们将一个应用程序分成了三个部件,所以使用MVC同时也意味着你将要管理比以前更多的文件,这一点是显而易见的。这样好像我们的工作量增加了,但是请记住这比起它所能带给我们的好处是不值一提。

MVC并不适合小型甚至中等规模的应用程序,花费大量时间将MVC应用到规模并不是很大的应用程序通常会得不偿失。

MVC是一条创建软件的好途径
MVC设计模式是一个很好创建软件的途径,它所提倡的一些原则,像内容和显示互相分离可能比较好理解。但是如果你要隔离模型、视图和控制器的构件,你可能需要重新思考你的应用程序,尤其是应用程序的构架方面。如果你肯接受MVC,并且有能力应付它所带来的额外的工作和复杂性,MVC将会使你的软件在健壮性,代码重用和结构方面上一个新的台阶。
Candy.zhai

posted @ 2009-04-05 19:08 silverPerson 阅读(53) 评论(0) 编辑