Posts Tagged ‘访问’

重新认识表格和一个访问无障碍的数据表格例子

星期三, 06月 4th, 2008

除特别说明外,本站内容采用创作共用授权署名和非商业用途,请尊重劳动成果.

表格一直是网页设计制作过程中一个重要de组成部分,在没学习CSS布局前,大多是用来布局de,但到目前位置发现居然还没真正地了解和完全掌握表格,不得不需要重新认识表格……

在现代网页设计制作中,表格主要de用途应该是用来存放多元二维数据.和表格相关de标签有 table、tr、td、th、tbody、thead、tfoot、col、colgroup、caption,如何合理地应用这些标签呢?先从名词解释开始.

名词解释

table

显示二维数据

tr

表格中de一行

td

数据单元格

th

表头单元格,定义一行或者一列de表头信息,不能使用在布局表格里.

tbody

表格中de某一行或者多行编成组,要结合thead、tfoot一起使用

thead

将表格中de某一行或者多行编成组,要结合tbody、tfoot一起使用

tfoot

将表格中de某一行或者多行编成组,要结合tbody、thead一起使用

col

列,给某一列或者几列应用特定de属性,结合colgroup一起使用

colgroup

列de组合,结合col一起使用

caption

定义表格de标题,在表格开始de地方使用,仅一次

summary

说明表格de用途

例子:

<table summary=”这是一个具有亲和力de表格de演示” id=”demotab”>

<caption>

访问 <a href=”http://www.forest53.com”>www.forest53.com</a> 浏览器统计

</caption>

<thead>

<tr>

<th>浏览器 / 月 </th>

<th>2005 / 11 </th>

<th>2006 / 04 </th>

<th>2006 / 05 </th>

</tr>

</thead>

<tfoot>

<tr>

<th>总计</th>

<td>1,646 ( 98.45% )</td>

<td>6,978 ( 99.48% ) </td>

<td>5,366 ( 99.56% ) </td>

</tr>

</tfoot>

<tbody>

<tr>

<th>Internet Explorer</th>

<td>1,535 (91.81%)</td>

<td>5,905 (86.41%)</td>

<td>4,550 (84.42%)</td>

</tr>

<tr>

<th>Firefox</th>

<td>98 (5.86%)</td>

<td>746 (10.92%)</td>

<td>640 (11.87%)</td>

</tr>

<tr>

<th>Opera</th>

<td>13 (0.78%)</td>

<td>147 (2.15%)</td>

<td>176 (3.27%)</td>

</tr>

</tbody>

</table>

C#(.NET)数据访问连接、查询、插入等操作的封装类

星期二, 06月 3rd, 2008

using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
/// <summary>
/// Public de摘要说明
/// </summary>
public class PublicClass
{ //定义一个公用成员
public SqlConnection conn;
public PublicClass()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
#region 建立数据库连接
public void OpenConn()
{
String strconn = System.Configuration.ConfigurationManager.AppSettings["sqlconn"].ToString();
conn = new SqlConnection(strconn);
if (conn.State.ToString().ToLower() == “open”)
{
//连接为打开时
}
else
{
//连接为关闭时
conn.Open();
}
}
#endregion
#region 关闭并释放连接
public void CloseConn()
{
if (conn.State.ToString().ToLower() == “open”)
{
//连接为打开时
conn.Close();
conn.Dispose();
}
}
#endregion
#region 返回DataReader,用于读取数据
public SqlDataReader DataRead(string sql)
{
OpenConn();
SqlCommand cmd = new SqlCommand(sql, conn);
SqlDataReader dr = cmd.ExecuteReader();
return dr;
}
#endregion
#region 返回一个数据集
public DataSet MySqlDataSet(string Sql, string tableName)
{
OpenConn();
SqlDataAdapter da;
DataSet ds = new DataSet();
da = new SqlDataAdapter(Sql, conn);
da.Fill(ds, tableName);
CloseConn();
return ds;
}
#endregion
//返回一个数据集
public DataView MySqlDataSource(string Sql)
{
OpenConn();
SqlDataAdapter da;
DataSet ds = new DataSet();
da = new SqlDataAdapter(Sql, conn);
da.Fill(ds, “temp”);
CloseConn();
return ds.Tables[0].DefaultView;
}
#region 执行一个SQL操作:添加、删除、更新操作
//执行一个SQL操作:添加、删除、更新操作
public void MySqlExcute(string sql)
{
OpenConn();
SqlCommand cmd;
cmd = new SqlCommand(sql, conn);
cmd.ExecuteNonQuery();
cmd.Dispose();
CloseConn();
}
#endregion
#region 执行一个SQL操作:添加、删除、更新操作,返回受影响de行
//执行一个SQL操作:添加、删除、更新操作,返回受影响de行
public int MySqlExecuteNonQuery(string sql)
{
OpenConn();
SqlCommand cmd;
cmd = new SqlCommand(sql, conn);
int flag = cmd.ExecuteNonQuery();
return flag;
}
#endregion
public object MySqlExecuteScalar(string sql)
{
OpenConn();
SqlCommand cmd;
cmd = new SqlCommand(sql, conn);
object obj = cmd.ExecuteScalar();
cmd.Dispose();
CloseConn();
return obj;
}
/// <summary>
/// 返回DataTable对象
/// </summary>
/// <param name=”sql”>sql语句</param>
/// <returns></returns>
public DataTable MySqlDataTable(string sql)
{
OpenConn();
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
da.Fill(ds, “table”);
CloseConn();
return ds.Tables["table"];
}
/// <summary>
/// 返回一个数据集de记录数
/// </summary>
/// <param name=”sql”>传递desql语句必须为一个统计查询</param>
/// <returns></returns>
public int MySqlRecordCount(string sql)
{
//注:Sql 语句必须是一个统计查询
OpenConn();
SqlCommand cmd = new SqlCommand();
cmd.CommandText = sql;
cmd.Connection = conn;
SqlDataReader dr;
dr = cmd.ExecuteReader();
int RecordCount = -1;
while (dr.Read())
{
RecordCount = int.Parse(dr[0].ToString());
}
CloseConn();
return RecordCount;
}
/// <summary>
/// 自定义de功能警告
/// </summary>
/// <param name=”str”>弹出信息框内容</param>
public void SetAlert(string str)
{
HttpContext.Current.Response.Write(”<script language=’JavaScript’ type=’text/JavaScript’>alert(’” str “‘);</script>”);
}
//返回上一页
public void AddErro(string message)
{
HttpContext.Current.Response.Write(”<script>alert(’” message “‘);history.back(-1);</script>”);
}

//关闭窗口
public void SetCloseWindow()
{
HttpContext.Current.Response.Write(”<script language=’JavaScript’ type=’text/JavaScript’>window.close();</script>”);
}
/// <summary>
/// 地址跳转
/// </summary>
/// <param name=”str”>跳转地址</param>
public void SetLocation(string str)
{
HttpContext.Current.Response.Write(”<script language=’JavaScript’ type=’text/JavaScript’>location=’” str “‘;</script>”);
}

public string AjaxSetAlert(string str)
{
return “<script language=’JavaScript’ type=’text/JavaScript’>alert(’” str “‘);</script>”;
}
//过滤非法字符
public string FilterStr(string Str)
{
Str = Str.Trim();
Str = Str.Replace(”*”, “”);
Str = Str.Replace(”=”, “”);
Str = Str.Replace(”/”, “”);
Str = Str.Replace(”$”, “”);
Str = Str.Replace(”#”, “”);
Str = Str.Replace(”@”, “”);
Str = Str.Replace(”&”, “”);
return Str;
}
//Md5加密算法
public string md5(string str)
{
return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, “md5″).ToLower().Substring(0, 12);
}
public string RndNum(int VcodeNum)
{
string Vchar = “0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,P,Q,R,S,T,U,W,X”;
string[] VcArray = Vchar.Split(new Char[] { ‘,’ }); //将字符串生成数组
string VNum = “”;
int temp = -1;
Random rand = new Random();
for (int i = 1; i < VcodeNum 1; i )
{
if (temp != -1)
{
rand = new Random(i * temp * unchecked((int)DateTime.Now.Ticks));
}
int t = rand.Next(31); //数组一般从0开始读取,所以这里为31*Rnd
if (temp != -1 && temp == t)
{
return RndNum(VcodeNum);
}
temp = t;
VNum = VcArray[t];
}
return VNum;
}
}

解决 ASP.NET中目录访问权限的问题

星期二, 06月 3rd, 2008

  症状:从 ASP.NET 应用程序,访问远程增强安全性de资源时可能会收到以下错误信息
  登录失败:未知用户名或错误密码.

  解决办法:
1 在 Web 服务器上修改 ASPNET 帐户de密码为 password .
2 在远程文件服务器上,修改 ASPNET 帐户(如果没有该帐户则创建之)de密码为 password .
3 在远程文件服务器上,为 ASPNET 帐户设置相应目录de访问权限.
4 修改 Web.config 文件,在 <system.web> 配置节中添加:
<identity impersonate=”true” userName=”ASPNET” password=”password” />
5 上述三处de密码可任意设置,但必须保持一致.

ASP.NET2.0中数据源控件之异步数据访问

星期二, 06月 3rd, 2008

  在第 1 部分第 2 部分中,建立了 WeatherDataSource 控件,该控件针对 weather.com(英文)所提供de XML API 来运行,使用 WebRequest 和 WebResponse 来通过 HTTP 访问数据.迄今为止,均是同步访问该服务.因此,页面处理被阻止,直到 Web 请求完成为止.此方法对于测试页面是有效de,在小站点上也可能有效,但是在接收大量通信流量de站点上则会惨败;例如门户页面,天气模块在其中可能非常常见.
  引言

  在线程池中有固定不变de大量线程可用于服务请求,遗憾de是,该解决方案并非仅仅提高限制(还会增加线程占用资源以及 CPU 占用资源).因此,当一个页面被阻止而等候另一个服务器时,它还在占用线程,因而可能会导致其他传入de请求在队列中等候更长de时间.这将导致对站点de访问变慢,并降低 CPU de利用率.在 Visual Studio 2005 中,我引入了异步页面,这使得控件能够定义它们希望异步完成de任务,即,无需阻止用来处理请求de线程.在此将不介绍异步页面本身de详细信息,Dmitry(英文)和 Fritz Onion(英文)中以前已经有所介绍.此处要介绍de是如何在数据源控件中利用此功能,使用加载项框架来实现异步数据源.
  背景
  在第 1 部分中,间接提到了 DataSourceView 类de有些古怪de设计:

public abstract class DataSourceView {
 public virtual void Select(DataSourceSelectArguments arguments,
  DataSourceViewSelectCallback callback);
 protected abstract IEnumerable ExecuteSelect(
  DataSourceSelectArguments arguments);
 …
}

  您会注意到,公共 Select 方法实际上并不返回任何数据.而是接受一个回拨,并通过该回拨来返回数据.它只调用受保护de ExecuteSelect(它始终执行同步数据访问)来检索要退还给数据绑定控件de数据.DataSourceView 类de默认实现实际上不会异步执行任何操作.原因在于,并不存在任何现成de异步数据源控件.但 OM de设计确实允许实现异步数据访问,在这种设计下,数据在异步工作完成之后才可用.因此,我就有了一个基于回拨de模型.
  那些熟悉框架中de异步 API de人会注意到缺少了异步模式:公共 Select、BeginSelect 和 EndSelect 方法,在这些方法中,数据绑定控件选择要调用哪些方法.但是,数据绑定控件并不能确定是选择同步 API 还是选择异步 API.此外,在数据绑定控件上添加属性也毫无作用.数据源控件封装了有关如何访问数据存储de详细信息,对数据存储de访问是同步发生还是异步发生应该根据数据源是否基于语义来决定或者根据自定义属性来决定.潜在de“bool PerformAsyncDataAccess”属性de正确位置适合于数据源控件本身.这还使得数据源控件可以使用一种方法来执行数据访问,即使多个数据绑定控件被绑定到同一个数据源.至此已多次解释了该体系结构所蕴涵de这些微妙de概念,但愿能阐明该设计.
  关于异步任务,最后要注意de一点是:页面是否应该执行任何异步工作完全由页面开发人员最终决定(通过 Page 指令de Async 属性).因此,任何编写良好de数据源控件必须退化为根据需要来执行同步数据访问.
  框架

  在此框架中(在此系列结尾会用示例de剩余部分来演示这一点),已将 AsyncDataSource 和 AsyncDataSourceView 基类放在一起,这些基类可以用于实现能够执行异步数据访问de数据源控件.以下大概介绍了框架内容,以及有助于弄清楚其含义de一些注释:
public abstract class AsyncDataSourceControl : DataSourceControl,
IAsyncDataSource {
private bool _performAsyncDataAccess;
protected AsyncDataSourceControl() {
 _performAsyncDataAccess = true;
}
public virtual bool PerformAsyncDataAccess {
 get; set;
}
bool IAsyncDataSource.IsAsync {
 get { return _performAsyncDataAccess && Page.IsAsync; }
}
}
public abstract class AsyncDataSourceView : DataSourceView {
 protected abstract IAsyncResult BeginExecuteSelect(
  DataSourceSelectArguments arguments,
  AsyncCallback asyncCallback,
  object asyncState);
 protected abstract IEnumerable EndExecuteSelect(
  IAsyncResult asyncResult);
  protected override IEnumerable ExecuteSelect(
   DataSourceSelectArguments arguments) {
    //实现从 DataSourceView 中继承de
    //抽象 ExecuteSelect 方法,
    //方法是使用 BeginExecuteSelect 和 EndExecuteSelect,
    //以便通过阻止来
    //进行同步数据访问.
   }
   private IAsyncResult OnBeginSelect(object sender,
     EventArgs e, AsyncCallback asyncCallback,
     object extraData);
   private void OnEndSelect(IAsyncResult asyncResult);
   public override void Select(DataSourceSelectArguments arguments,
    DataSourceViewSelectCallback callback) {
     if (_owner.IsAsync) {
      //使用 OnBeginSelect 和 OnEndSelect
      //作为 BeginEventHandler 和 EndEventHandler 方法,
      //来调用 Page.RegisterAsyncTask,
      //以指明需要
      //进行异步工作.这些方法将依次
      //调用特定de
      //数据源实现,方法是调用
      //已在此类中引入de
      //抽象 BeginExecuteSelect 和 EndExecuteSelect
      //方法.
     }
     else {
      //执行同步数据访问
      base.Select(arguments, callback);
     }
    }
   …
}

  示例
  现在,新de AsyncWeatherDataSource 将从 AsyncDataSourceControl 中派生,而 AsyncWeatherDataSourceView 将从 AsyncDataSourceView 中派生.
public class AsyncWeatherDataSource : AsyncDataSourceControl {
//与 WeatherDataSource 相同
}
private sealed class AsyncWeatherDataSourceView : AsyncDataSourceView {
private AsyncWeatherDataSource _owner;
private WeatherService _weatherService;
public AsyncWeatherDataSourceView(AsyncWeatherDataSource owner,
string viewName)
: base(owner, viewName) {
_owner = owner;
}
protected override IAsyncResult BeginExecuteSelect(DataSourceSelectArguments arguments,
AsyncCallback asyncCallback,
object asyncState) {
arguments.RaiseUnsupportedCapabilitiesError(this);
string zipCode = _owner.GetSelectedZipCode();
if (zipCode.Length == 0) {
return new SynchronousAsyncSelectResult(/* selectResult */
null,
asyncCallback, asyncState);
}
_weatherService = new WeatherService(zipCode);
return _weatherService.BeginGetWeather(asyncCallback, asyncState);
}
protected override IEnumerable EndExecuteSelect(IAsyncResult asyncResult) {
SynchronousAsyncSelectResult syncResult =
asyncResult as SynchronousAsyncSelectResult;
if (syncResult != null) {
return syncResult.SelectResult;
}
else {
Weather weatherObject =
_weatherService.EndGetWeather(asyncResult);
_weatherService = null;
if (weatherObject != null) {
return new Weather[] { weatherObject };
}
}
return null;
}
}

  要注意de关键问题是,在使用该框架时,只需要实现 BeginExecuteSelect 和 EndExecuteSelect.在它们de实现过程中,通常要调用由该框架中de各种对象(例如 WebRequest 或 IO 流)所揭示de BeginXXX 和 EndXXX 方法(在 Visual Studio 2005 中,还需要调用 SqlDataCommand),并返回 IAsyncResult.在此示例中,有一个封装了基础 WebRequest 对象de WeatherService 帮助程序类.
  对于那些实际缺少异步模式de框架,您在此会看到有效de异步模式;以及您要实现de BeginExecuteSelect 和 EndExecuteSelect,和您要调用以返回 IAsyncResult 实例de Begin 和 End 方法.
  最有趣de可能是 SynchronousAsyncSelectResult 类(在某种程度上而言是一种矛盾).此类是框架附带de.它基本上是一个 IAsyncResult 实现,可使数据立即可用,并从其 IAsyncResult.CompletedSynchronously 属性报告 true.到目前为止,这仅适用于未选择邮政编码de情况,并且需要返回 null(启动异步任务而只返回 null 是没有意义de),但正如您会在下文中看到de,这在其他方案中也是有用de.
  页面基础结构隐藏了在 Microsoft ASP.NET 上下文中执行异步工作de大部分详细信息.希望在此提供de框架使您执行最少de操作就能编写使用此基础结构de数据源.不过,就其本质而言,实现异步行为是复杂de.有时候,第一次阅读本文时会有一些疑问,而第二次阅读时可能就明白了.您可以使用下面“我de评论”表单来发送问题或进行讨论.

ASP.NET数据库编程之处理文件访问许可

星期二, 06月 3rd, 2008

  一个MDB数据库就是硬盘上de另外一个文件,所以,像其他文件一样,它也将遇到相同de文件访问许可问题.这个问题de意思是为了读取(和写入,就像您将要在本书de后面看到de那样)数据库文件,页面中所运行de应用程序必须具有相关许可才可以在Windows中读取(和写入)该文件.
  到目前为止,示例中de页面都能够“正常运行”de原因就是您使用de是VWD Web Server,一个在运行VWDde用户de身份下运行de轻量级程序.这就是说,VWD Web Server为您而运行,并且您已经被允许读取和写入页面连接deMDB文件.
  但是,当在IIS下运行页面时,情况就有一点复杂了.此时,ASP.NET页面运行于一个具有特定权限限制de用户账户de身份之下.在IIS 5.1之下,这个账户是“ASPNET”.在IIS 6.0或更高版本下,这个账户是“Network Service”,属于一个称为IIS_WPG(“worker process group”)deWindows用户组.为了在IIS下使用Access数据库,这些账户都必须授予对包含了MDB文件de目录进行读取de许可以及按情况授予写入de许可.
  为了帮助您创建这些许可,当数据库处于应用程序根目录之下deApp_Data子目录下时,VWD将执行额外de步骤并自动地将这个许可授予ASPNET或者 Network Service账户.假如您正在使用VWD来开发机器上de页面,这个特定de目录就一直会被授予正确de许可.App_Data目录还有另外de好处,例如防止其中de任何文件响应发出请求deWeb浏览器.这就是说将MDB文件放入应用程序de本地App_Data目录之后,就可以保护这些文件不被应用程序de客户端无意或有意地下载了.所以,我极力推荐将MDB文件保存至App_Data目录中.
  如果必须将MDB文件保存至其他de地方,或者需要手动指定数据库目录de许可(例如,您正工作于一台远程Web服务器),那么可以使用Windows来为ASP.NET和/或 Network Service账户配置许可.
  如需手动设置许可,请按如下步骤执行:
  (1) 使用Windows Explorer浏览MDB文件所在de文件夹.
  (2) 右键单击这个目录并选择Properties.
  (3) 选择Security标签并单击Add按钮.
  (4) 添加本地deASP.NET账户(IIS 5.1) 或者IIS_WPG组(IIS 6).
  (5) 单击OK;然后将相关许可应用至这个目录.
  如需获得更多信息,请参阅名为“Running ASP.NET 1.1和IIS 6.0”de白皮书,可以从ASP.NETdeWeb站点:http://www.asp.net/faq/AspNetAndIIS6.aspx上获得该白皮书.

ASP.net做的IP访问限制

星期二, 06月 3rd, 2008

  偶做留言本de时候想起做这么个,具体思路也许不好,做出来只是抛砖引玉,希望有更好de方法!

  IP添加页是用了一个ListBox, TextBox,两个Button,而在其他de页上则直接用当前IP对比数据库中deIP,相关代码如下!

  限制IP添加页HTML相关代码

<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”ip.aspx.cs” Inherits=”admin_ip” %>
<!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” >
<head runat=”server”>
<title>无标题页</title>
<link href=”../images/news.css” rel=”stylesheet” type=”text/css” />
</head>
<body>
<form id=”form1″ runat=”server”>
<div>
<asp:SqlDataSource ID=”SqlDataSource1″ runat=”server” ConnectionString=”<%$ ConnectionStrings:book %>”
ProviderName=”<%$ ConnectionStrings:book.ProviderName %>” SelectCommand=”SELECT [ip] FROM [ip]“>
</asp:SqlDataSource>
<table align=”center” style=”border-right: #0066cc 1px dotted; border-top: #0066cc 1px dotted; border-left: #0066cc 1px dotted; border-bottom: #0066cc 1px dotted”>
<tr>
<td rowspan=”2″ style=”width: 100px; border-right: #33ccff 1px groove; border-top: #33ccff 1px groove; border-left: #33ccff 1px groove; border-bottom: #33ccff 1px groove;”>
<asp:ListBox ID=”iplxb” runat=”server” DataSourceID=”SqlDataSource1″ DataTextField=”ip”
DataValueField=”ip” Height=”194px” Width=”153px”></asp:ListBox></td>
<td style=”width: 100px; border-right: #33ccff 1px groove; border-top: #33ccff 1px groove; border-left: #33ccff 1px groove; border-bottom: #33ccff 1px groove;”>
填写标准deIP地址到左下文本框里面,然后点击按纽添加!<br />
<asp:RegularExpressionValidator ID=”RegularExpressionValidator1″ runat=”server” ControlToValidate=”iptb”
Display=”Dynamic” ErrorMessage=”IP地址格式不正确” ValidationExpression=”([0-9]{2,3})([.])([0-9]{1,3})([.])([0-9]{1,3})([.])([0-9]{1,3})”></asp:RegularExpressionValidator></td>
</tr>
<tr>
<td style=”width: 100px; border-right: #33ccff 1px groove; border-top: #33ccff 1px groove; border-left: #33ccff 1px groove; border-bottom: #33ccff 1px groove;”>
<asp:LinkButton ID=”LinkButton1″ runat=”server” OnClick=”LinkButton1_Click”>删除选中de行</asp:LinkButton></td>
</tr>
<tr>
<td style=”width: 100px; border-right: #33ccff 1px groove; border-top: #33ccff 1px groove; border-left: #33ccff 1px groove; border-bottom: #33ccff 1px groove;”>
<asp:TextBox ID=”iptb” runat=”server” Width=”150px”>61.139.33.22</asp:TextBox></td>
<td style=”width: 100px; border-right: #33ccff 1px groove; border-top: #33ccff 1px groove; border-left: #33ccff 1px groove; border-bottom: #33ccff 1px groove;”>
<asp:Button ID=”Button1″ runat=”server” OnClick=”Button1_Click” Text=”增加” Width=”80px” /></td>
</tr>
</table>
</div>
</form>
</body>
</html>

  限制IP添加页CS相关代码

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class admin_ip : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Server.Execute(”chklog.aspx”);
}
protected void Button1_Click(object sender, EventArgs e)
{
iplxb.Items.Add(iptb.Text);
odb.insert(”insert into ip (ip) values (’” iptb.Text “‘)”);
}
protected void LinkButton1_Click(object sender, EventArgs e)
{
for (int i = 0; i < iplxb.Items.Count; i )
{
if (iplxb.Items[i].Selected)
{
odb.insert(”delete from ip where ip=’” iplxb.SelectedItem.Text “‘”);
iplxb.Items.Remove(iplxb.SelectedItem.Text);
}
}
}
}

  被需要限制IPde页面调用页de相关代码

protected void Page_Load(object sender, EventArgs e)
{
string ip = Request.UserHostAddress.ToString();
if (Convert.ToInt32(odb.scr(”select count(*) from [ip] where ip=’” ip “‘”)) > 0)
Response.Write(”对不起,您deIP被限制访问,请咨询管理员”);
}
}

JavaMail访问Hotmail邮箱

星期一, 06月 2nd, 2008

相信许多人都有MSN聊天工具de帐号,例如abc@hotmail.com ,这个账号其实也是一个邮件地址,可以进行正常de邮件收发功能,您可以通过网址 http://www.hotmail.com 来访问和操作这个邮箱进行邮件de收发.但是这个邮箱有一个限制就是它并不提供POP3或者SMTP服务,也就是说一般de邮件客户端工具无法使用这个邮箱,虽然现在有不少de邮件工具可以支持Hotmail邮箱,但是如果我需要在我deJava项目中增加对Hotmail邮箱de支持,那往往会不知从什么地方开始入手,因为SUN公司提供deJavaMail 本身并不提供对除了POP3/IMAP以及SMTP外其他协议de支持.
  但事实上,JavaMail只是定义了一组平台无关、独立于通讯协议de邮件程序框架,或者说是接口,它是作为Javade可选包存在de.因此可以这样说:JavaMail并不关心所使用de协议,不管是POP3、SMTP、IMAP当然还有Hotmail用deHTTP协议.对于JavaMailde客户端而言也是这样de,下图就是一个最简单deJavaMail结构图,通过Transport进行邮件de发送,通过Store实现对邮件de收取,而不同协议de实现,JavaMail里de概念叫做Provider,只需要根据JavaMail定义de接口实现自己deProvider即可.


  为了实现通过JavaMail访问Hotmail邮箱,我就需要架起JavaMail接口与Hotmail服务所提供de访问接口之间de桥梁.在这之前我必须首先了解Hotmail所使用de接口协议.
  Hotmail通过地址 http://services.msn.com/svcs/hotmail/httpmail.asp 提供基于HTTP协议de服务,它不同于我通过浏览器访问 http://www.hotmail.com de这个地址,后面这个地址是提供给用户一个基于浏览器de访问界面以便对邮箱进行操作,您当然可以通过编写HTTP客户端程序来解析页面并获取邮件de信息,但是这样做不仅实现de复杂程度非常高,而且每次页面风格发生变化后程序都要做相应de调整,因此不具备通用性,显然是不可行de.而地址 http://services.msn.com/svcs/hotmail/httpmail.asp 则不同,它提供了固定de应用程序接口.当您使用浏览器访问该地址de时候,会弹出下面要求登录de窗体:


  而当输入正确de用户名和口令后会再弹出一次或两次该提示窗口,但提示信息不同,操作完成后出现页面无法显示de错误,错误码是 405 (资源不允许).因此该服务并不允许通过浏览器来访问.
  事实上Hotmail使用de是WebDAV来提供基于HTTP协议de应用编程接口,WebDAV(Web 分布式创作和版本控制)已经成为重要de Web 通讯协议.WebDAV所要解决de问题是:
  1.改写保护:HTTP 1.1 无法确保客户端可以保护资源,并且可以在其他客户端同时编辑它们de情况下进行更改. 使用 WebDAV,可以通过多种方式来锁定资源,以便让其他客户端知道您对所讨论de资源感兴趣,或者防止其他客户端访问该资源.
  2.资源管理:HTTP 只能直接访问单个资源. WebDAV 提供一种更有效地组织数据de方法. WebDAV 引入了可包含资源 de集合(类似于文件系统文件夹)概念. 通过 WebDAV 进行de资源管理包括如下功能:创建、移动、复制和删除集合,以及集合中de资源或文件.
  3.文档属性:不同类型de数据具有唯一de属性,这有助于描述数据. 例如,在电子邮件中,这些属性可能是发件人de姓名和接收邮件de时间. 在协作文档中,这些属性可能是文档原始作者de姓名和最后一个编辑者de姓名. 因为人们使用de文档类型各不相同,所以可能de属性类型列表也变得无限大. XML 是 WebDAV 所需de一种可扩展通讯工具.
  关于WebDAVde更多资料可以参阅本文最后de参考资料.
  相对于自行解析Hotmailde浏览器页面而言,基于特定协议WebDAVde接口使Hotmail邮件客户端程序de实现更加稳定和可靠.在了解了JavaMail APIde基本接口以及Hotmail所提供接口de协议,本文de题目就变得非常具体了,就是如果编写基于WebDAVdeJavaMail Provider(JavaMail提供者)并使用这个提供者来实现Hotmail邮件收发功能,但这题目太大而且已经超过了一篇文章所能叙述de范围,因此我接下来将引入一个开放源码项目JDAVMail,并详细介绍如何通过这个项目实现Hotmail邮件de收发功能.
  JDAVMail 是一个开放源码deJavaMailde提供者项目,可以通过它来访问基于WebDAV协议de邮件服务,有如Hotmail邮箱.您可以到 http://sourceforge.net/projects/jdavmail 这个网址下载到最新版本de程序.JDAVMail使用了Jakarta上decommons httpclient 作为HTTP客户端组件与服务器进行通讯,同时使用了jdom进行XML数据de解析,另外由于httpclient项目用到了commons logging进行日记de输出,因此commons-logging也是必须de,这三个组件都可以在JDAVMailde压缩包中delib目录中找到,压缩包中同时还包括已编译dejar文件以及所有de源码.
   为了让大家对JDAVMail有个大概de认识,下面我给出两段相关代码用于Hotmail邮件de收发:
  1. 邮件收取
  /*
  * 文件名:HotmailDemo.java
  * 创建时间:2004-9-14
  * 创建者:liudong
  */
  package com.clickcom.mail;
  import java.util.Date;
  import java.util.Properties;
  import javax.mail.Folder;
  import javax.mail.Message;
  import javax.mail.Session;
  import javax.mail.Store;
  import javax.mail.Transport;
  import javax.mail.internet.InternetAddress;
  import javax.mail.internet.MimeMessage;
  /**
  * Hotmail邮件de收发器
  * @author liudong
  */
  public class HotmailDemo {
  public static void main(String[] args) {
  receive();
  }
  /**
  * 邮件接收
  */
   protected static void receive() {
  try {
   Properties prop = new Properties();
   Session ses = Session.getInstance(prop);
   //使用JDAVMail Provider
   Store store = ses.getStore(”davmail”);
   //无需指定服务器地址
   store.connect(null, “您de帐号”,”密码”);
   if (store.isConnected()) {
    Folder inbox = store.getFolder(”INBOX”);
    if (inbox.exists()) {
     inbox.open(Folder.READ_ONLY);
     int nCount = inbox.getMessageCount();
     System.out.println(”Inbox contains ” nCount ” messages”);
     // 依次显示收件箱中de每封邮件
     for(int i=1;i<=nCount;i ){
      MimeMessage msg = (MimeMessage) inbox.getMessage(i);
      System.out.println(”Subject : ” msg.getSubject());
      System.out.println(”From : ” msg.getFrom()[0].toString());
      System.out.println(”Content type : ” msg.getContentType());
      System.out.println(msg.getContent());
     }
    }
   }
  } catch (Exception ex) {
   ex.printStackTrace();
  }
  }
  }
  从上面这段相关代码我发现除了 Store store = ses.getStore(”davmail”); 这个语句,同时不需要指定服务器地址外,其他de都跟一个普通deJavaMail应用程序没有两样,也没有引入任何跟JDAVMail有关de类.没有指定服务器地址这个比较容易理解,因为Hotmail提供HttpMail服务de地址是固定de.事实上仅有getStore这个语句跟常规邮件客户端程序有点不同de是它使用davmail字符串作为参数,而我在使用JavaMail连接POP3服务器de时候指定参数值为pop3.怎么回事呢?因为JavaMail是通过协议名来加载Provider类de.打开JDAVMail.0.9.006.jar这个jar文件就会发现在META-INF目录下有一个文件javamail.providers,该文件内容如下:
  protocol=davmail;
  type=store; class=com.posisoft.jdavmail.JDAVMailStore;
  vendor=Positive Software;
  protocol=davmail_xmit;
  type=transport;
  class=com.posisoft.jdavmail.JDAVMailTransport;
  vendor=Positive Software;
  因此当我指定协议名为davmail时,JavaMail就会自动加载com.posisoft.jdavmail.JDAVMailStore类进行处理,因此通过传入davmail字符串所得到destore实例实际上是类com.posisoft.jdavmail.JDAVMailStorede一个实例,这样我想大家应该了解了前面这段程序de工作原理.
  我再来看JDAVMail发送邮件de相关代码片段:
  /**
  * 邮件发送
  */
  protected static void send() {
  try {
  Properties prop = new Properties();
  //邮件发送者地址
  prop.setProperty(”mail.davmail.from”,”abc@hotmail.com”);
  Session ses = Session.getInstance(prop);
  //获得JDAVMailde邮件发送实例
  Transport transport = ses.getTransport(”davmail_xmit”);
  //连接到Hotmail服务器,请替换为自己de用户名和口令
  transport.connect(null, “用户名”,”口令”);
  // 准备要发送de邮件
  MimeMessage txMsg = new MimeMessage(ses);
  txMsg.setSubject(”This is the subject”);
  //邮件发送者地址
  InternetAddress addrFrom = new InternetAddress(”abc@hotmail.com”);
  txMsg.setFrom(addrFrom);
  //邮件接收者地址
  InternetAddress addrTo = new InternetAddress(”cdef@hotmail.com”, “cdef”);
  txMsg.addRecipient(Message.RecipientType.TO, addrTo);
  //邮件内容
  txMsg.setText(”Hello world !”);
  txMsg.setSentDate(new Date());
  //发送邮件
  transport.sendMessage(txMsg, txMsg.getAllRecipients());
  } catch (Exception ex) {
  ex.printStackTrace();
  }
  }
  同样这段相关代码使用了davmail_xmit协议来获取JDAVMailde邮件发送实例,通过前面提到dejavamail.providers文件不难知道JDAVMail使用类com.posisoft.jdavmail.JDAVMailTransport进行邮件de发送处理.
  在实际测试中发现不管是JDAVMail还是其他de邮件工具,使用Hotmail进行邮件de发送速度比较慢,差不多有几分钟后才能收到相应de信息,因此如果测试中发现该问题请耐心等待.
  我想通过本文介绍如何利用JDAVMail收发Hotmail邮件,以及研究JDAVMailde源码,不仅可以更加深入了解JavaMailde体系结构,对编写JavaMail Provider也有更加具体de参照.另外希望为正困挠于如何在Java程序中访问Hotmail邮件de朋友们排忧解难.同时也非常欢迎通过我de网站 http://www.javayou.com 跟我交流在使用中遇到de问题.

建立JSP操作以提高数据库访问的效率

星期一, 06月 2nd, 2008

从服务器端促进程序快速开发deJava Server Pages (JSP)决定它成为一种广为流行de工具.虽然呆板de一面仍然存在,然而无论它包含多少缺点,JSP能够为Web程序设计者提供很多东西,尤其是与数据库de输入和输出操作与数据de处理.

通过JSP来进行数据库访问不需要太多de引导.问题是如何使开发者能够接受Web程序de数据库访问比传统de本地OLAP系统de数据库访问更加具有吸引力,并且使他们认识到,整洁和简要de数据访问方法才是关键de.在这一点上,JSP可以很好地解决.

您能够做哪些?
如果您正在编写高数据量、数据密度大deWeb程序时,您de数据库访问应该具备哪一方面de要求?如果您正在使用JSP,那么您必须处理大量de服务器端de数据.程序也许需要大量de数据,或者很多用户,或者这二者de结合.您所考虑de可能范围还会包括:性能de优化,可检测性,每一用户de多个查询de影响,查询de复杂性,以及当单一de会话处理大量数据时,高等级de类型转换.

这其中包含大规模de处理.但是,JSP能够帮助您很好地处理,因为它能够与Java Database Connectivity API (JDBC)很好de兼容.您可以将JDBC包含在JSP相关代码中,并且JDBC能够传递声明执行类似数据库de命令,只要您能够正确地使用JDBC驱动程序.

开始
这里是一个通常de、抽象deJSP程序执行de体系.首选deJSP设计模式为模型-视图-控制器(MVCModel-View-Controller),即传统三层体系de一种变异,以更好de适合于服务器程序.在JSPdeMVC设计模式中,Model指de是程序de逻辑与数据,View为查看,以及Controller为请求处理.

当您设计一个JSP程序时,在客户端与服务器交互之间建立第一步骤de页面,这是最好de一个过程.例如,在一个典型程序中,在数据交换中de每一个特定步骤都会有页面:一个数据入口页面,一个验证请求页面,一个数据库响应页面,以及这些页面de子页面(一个更改记录de页面,一个删除记录de页面,等等).

您可以将JDBC嵌入到每一页面中,以完成被请求de数据库操作.然而,这一操作也会冒很大de风险,因为由于混合了JSP和JDBC而混合了整个程序──JDBC是基于SQL.这也就是SQL被封装在JDBC,而JDBC也被封装在JSP──这也足够让您晕头转向de.如果您选择这一方法,您将会获得您想要de功能,但一定要保证您de程序逻辑与数据库访问相关代码de关系非常清晰,这一点格外小心.

嵌入式JDBC
JDBC API不会直接地与数据库进行交流.其中de驱动程序完成de实际de连接,您可以在卖方deWeb站点上下载这些驱动程序.除此之外,还有四种JDBCde驱动程序类型,如果您决定使用JDBC,您需要正确地选择最为适合您需要de那种类型.您将使用一个DriverManager类来处理基于驱动程序de连接.

您可以使用一个名为getConnectiondeDriverManager方法来建立您de数据库连接.您还可以使用它deURL参数来识别数据库:

public static Connection getConnection(jdbc:odbc:nameOfDatabase)

现在,告诉DriverManager有关驱动程序de信息(应该在您declasspath中):

Class.forName(“sun.jdbc.odbc.nameOfJDBCDriver”);


您已经将数据库连接到JSP程序,但您仍然不能够执行一个数据库命令.解决这一点,您可以在JSP相关代码中生成声明以建立数据库命令,如下所示:

public Statement createStatement(intresultSetType, intresultSetConcurrency)

其中de参数能够让您控制从数据库查询得到de结果.当使用第一个参数时,可以在程序中看到结果;当使用第二个参数时,您可以通过查询来更新数值(这是一个难以相信de功能,在以后de文章中值得进一步讨论).

表A
http://builder.com.com/5100-6387-5172666.html?tag=sc#Listing
AListing A显示列举了下两种方法de复杂性.

声明(Statement)就是SQL命令.PreparedStatement就是SQLde声明,您可以通过其中de参数来控制程序de过程.CallableStatement是用于访问SQL存储程序.您是否开始意识到,如果您没有看到这些说明,您是否觉得这些声明很复杂?请注意到,通过调用rollback方法,您可以撤除交易过程.

如果您想完全使用这些数据库访问de方法,您唯一遗漏de还有:

ResultSetexecuteQuery(string sqlQuery)


(您可以使用executeQuery来完成以上过程.您也可以使用一个executeUpdate来完成更新、插入和删除).您以上de声明接口使您可以使用一些方法来执行SQL声明.ResultSet所做de就是访问从查询得到de数据,所以您可以在JSP程序中使用这些数据.

通过将JSP程序分解成单一de、功能明显de页面,以及在任何给定页面中执行一个单一de数据库操作,可以很大程度地简化您de数据库操作,以及建立可以用于以后程序开发de页面,即使您将SQL嵌入到这些页面deJDBC中.

但是您还可以做更多de事情,以使得您deJSP数据库访问更加整洁和容易维护.在JSP相关代码中嵌入JDBC,以及通过发送SQL命令与数据库通讯,这些过程都很好.但是,它要求在不能增加相关代码复杂程度下,建立通过接口deSQL命令de程序.当您deSQL处理需要提高灵活性de时候,您可以进一步地分离您de数据库接口相关代码,以清洁您deJSP程序.在下面de文章中,我将告诉您如何实现这些过程.

加快JDBC设计中JSP访问数据库

星期一, 06月 2nd, 2008

以前,我已经提到,JSP程序都是模块,并且具有强大de表达-请求(presentation-request)功能.建立一个完美de数据库访问是一个具有挑战de过程,而JDBC接口能够很好地完成这一过程.然而,嵌入于JSP相关代码中deJDBC相关代码,与SQL命令嵌入在JDBC一样,可以充分利用JSPde功能,为客户端建立一个整洁而简便deAPI.为了达到这一目de,我可以考虑到使用JSP操作来建立数据库接口组件.


完美deJSP设计模式是Model-View-Controller (MVC).传统三层体系为:Model为程序逻辑和数据;View为查看;以及Controller为请求处理.遵循这一模型,一个JSP程序包含客户端-服务器“对话框”de每一“行”de页面.在一个典型de程序中,您可以看到一个查询页面,一个验证页面,一个数据库插入页面,一个数据库更新页面,等等.

在上一篇de文章中,我讨论到如何在每一页面中嵌入JDBC,以保证程序de结构更加合理.然而,建立可执行deSQL命令,正如变量通过JDBC命令而传递一样,也有可能会增加程序de复杂性.

JDBC设计deJSP操作
JSP数据库操作de另一方法是,在不使用JDBCde情况下为数据库建立一些操作de集合.使用这种方法,您可以得到两种好处:第一,您可以消除使用JDBCde必要,这就使得很多工作得以简化;第二,您de设计和相关代码de组织更加合理(比如可读性,灵活性,以及可维护性).

您仍然需要一些驱动程序,但您首先简化以上de操作.JSP程序中de操作都是一些逻辑块,通常被其它deJSP程序开发者编写和利用,但您可以把它们当成子程序来使用.使用JSP操作de意义是标准化某些功能,以及最大程度地减少嵌入在JSPdeJava相关代码数量.

JSP提供了一套标准扩展de类.通过这些类,您可以通过一个标签管理器器(tag handler)定义一个操作.这里有两个JSP定义deJava接口:Tag接口和BodyTag接口,分别是由TagSupport类和BodyTagSupport类执行.

您可以建立通用JSP用途de一个标签库,并且您也可以执行标签管理器(tag handler)以扩展类de支持.以下是实现这些过程de步骤.

首先,执行一个标签管理器de类:

packagecom.myactions;
(import statements go here)
public class MyActionTag extends TagSupport {

}

接着,编译这段相关代码,并将类文件放置在程序de类库中.然后,您将需要一个Tag Library Descriptor (TLD)文件,这是一个XML文件,以匹配您de操作名称和相应de标签管理器de类.

<tag>
<name>MyAction</name>
<tagclass>com.myactions.MyActionTag</tagclass>
<bodycontent> (whatever) </bodycontent>
<attribute>myData</attribute>
</tag>

</tag>

相关deTrialware

  • DbUtils (Apache Software Foundation)
  • IBM Informix JDBC Driver (IBM)
  • MySQL Connector/J 3.0 (MySQL AB)
  • SQL4X Manager J 2.2 (MacosGuru)
  • Informix Downloads (IBM Red Brick Warehouse 32bit) (Solaris) (IBM)
  • Informix Downloads (IBM Red Brick Warehouse 64bit) (HPUX) (IBM)
    更多Trialware
  • 假设您已经建立一个名为MyActionde操作,这是一个与com.myactions.MyActionTag类匹配deTLD.TLD文件必须位于程序deTLDs路径.

    当您从一个JSP页调用操作时,TLD告诉JSP正确de类以使用操作.这就带来极大de方便,而且只需要少量de相关代码.

    但是,从何引入SQL?首先,您需要建立具有连接功能de数据库访问.您可以使用javax接口来完成,而javax可见于JDBC 2.0 Optional工具箱.JDBC 2.0dejavax.sql.DataSource类提供了您所需要de连接.

    此时,SQL位于什么地方?它在bean中.您可以使用JDBCcreateStatement和PreparedStatement在bean中建立一个方法.将这一方法成为一个公共deVector,并正确地将您deSQL声明传递到这一方法.

    总结
    您de数据库bean执行一个嵌入在操作体deSQL语句,您可以传递一个语句给SQL语句,或者使用它来执行一个预先de操作.可以通过标签管理器来执行您de操作.由于JDBC被嵌入于库相关代码中,您将不能在JSP程序中明确地使用它.

    初次使用这种方法会觉得它比JDBC中de嵌入SQL,以及JSP中de嵌入JDBC更加复杂,但是,您建立SQL操作并将它们存放在一个TLD,您只需做一次,在所有deJSP程序中就可以访问这些操作.这就是这种方法de优点.

    下一次,我将会讲述到JSP页和会话(sessions)之间de数据传递.

    在JSP中访问MS SQL Server数据库

    星期一, 06月 2nd, 2008

    下面介绍如何用SQL Server实现一个动态FAQ(常见问题及答案)网站.
    首先建立一个数据库faq,其中de表faqs有字段id(int,自动增量,并设为主关键字)、subject(varchar,200)、answers(text).这个表中可以存放一些编程知识de常见问题及答案.然后,在Control Panel(控制面板)deODBC Datasource模块中加入System DSN,取名faq,并指向faq数据库.创建一个JavaBean,名为faq.java,并保存在C:\JBuilder4\tomcat\webapps\test目录下.
    faq.java de内容如下:
    package test;
    import java.sql.*;
    public class faq {
    String sDBDriver = “sun.jdbc.odbc.JdbcOdbcDriver”;
    String sConnStr = “jdbc:odbc:faq”;
    Connection conn = null;
    ResultSet rs = null;
    public faq() {
    try {
    Class.forName(sDBDriver);
    }
    catch(java.lang.ClassNotFoundException e) {
    System.err.println(”faq(): ” e.getMessage());
    }
    }
    public ResultSet executeQuery(String sql) {
    rs = null;
    try {
    conn = DriverManager.getConnection(sConnStr);
    Statement stmt = conn.createStatement();
    rs = stmt.executeQuery(sql);
    }
    catch(SQLException ex) {
    System.err.println(”aq.executeQuery: ” ex.getMessage());
    }
    return rs;
    }
    }
    用上一节介绍de方法编译faq.java以后,在jC:\JBuilder4\tomcat\webapps\test目录下创建JSP文件faq.jsp,其内容如下:
    <html>
    <head>
    <meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″>
    <title>我deFAQ !</title>
    </head>
    <body>
    <p><b>这是我deFAQ!</b></p>
    <%@ page language=”java” import=”java.sql.*” %>
    <jsp:useBean id=”workM” scope=”page” class=”test.faq” />
    <%
    ResultSet RS = workM.executeQuery(”SELECT * FROM faqs”);
    String tt;
    while (RS.next()) {
    tt = RS.getString(”Answer”);
    out.print(”<LI>” RS.getString(”Subject”) “</LI>”);
    out.print(”<pre>” tt “</pre>”);
    }
    RS.close();
    %>
    在浏览器de地址栏中键入http://localhost:8080/test/faq.jsp,faq.jsp调用JavaBean,从数据库中读出内容并输出,得到结果如图5所示.