Home 博客 Category 软件开发

知力企业博客

上善若水 厚德载物

Category >> 软件开发

TalkOne即时通讯开发之编码

Posted by: admin in Untagged  on

这几天一直被编码的事搞的头大,今天算是彻底解决,TalkOne即时通讯的后台是采用Erlang开发的,前端管理采用Ruby On Rails,因为会涉及到数据通讯的问题,考虑到性能或和扩展性方面,两者之间采用JSON进行的数据通讯,Erlang采用是的rfc4627,编码是utf-8的,但是在前两个这两个0字节,在ROR这边不能直接解码。因为涉及到utf-8和unicode的转化问题。

UTF-8编码字符理论上可以最多到6个字节长,然而16位BMP(Basic Multilingual Plane)字符最多只用到3字节长。下面看一下UTF-8编码表:

        U-00000000 - U-0000007F: 0xxxxxxx
        U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
        U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
        U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
        U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

 

当然在UTF-8到Unicode的转换也是通过移位等来完成的,就是把UTF-8那些格式相应的位置的二进制数给揪出来。在上述例子中"你"为三个字节,因此要每个字节进行处理,有高位到低位进行处理。在UTF-8中"你"为11100100,10111101,10100000。从高位起即第一个字节11100100就是把其中的"0100"给取出来,这个很简单只要和11111(0x1F)取与(&),由三字节可以得知最到位肯定位于12位之前,因为每次取六位。所以还要将得到的结果左移12位,最高位也就这样完成了0100,000000,000000。而第二位则是要把"111101"给取出来,则只需将第二字节10111101 和111111(0x3F)取与(&)。在将所得到的结果左移6位与最高字节所得的结果取或(|),第二位就这样完成了,得到的结果为 0100,111101,000000。以此类推最后一位直接与111111(0x3F)取与(&),再与前面所得的结果取或(|)即可得到结果 0100,111101,100000

因此用Ruby可以写出utf8转成unicode的主要代码
irb(main):023:0> irb
irb#1(main):001:0> a=0xE4
=> 228
irb#1(main):002:0> a & 0x1F
=> 4
irb#1(main):003:0> unicode =  ( a & 0x1F) << 12
=> 16384
irb#1(main):004:0> unicode |= ( 0xBD & 0x3F) << 6
=> 20288
irb#1(main):005:0> unicode |= ( 0xA0 & 0x3F)
=> 20320
irb#1(main):006:0>

上面是模拟验证运算,有了这个以后,就是分析json的字符串,通过正则表达式来匹配,注意utf-8过来有3个连接的编码,通过上述的转化,用过unpack("U")返回字符,这样的就页面就能显示正常中文了。


Ruby On Rails发送邮件的配置

Posted by: bin in Untagged  on

ruby on rails 发送邮件配置

一、环境
  ubuntu 9.0.4  ruby 1.8.7 (2008-08-11) [i486-linux]  Rails 2.3

二、目的
   给注册发送激活邮件

三、实现过程
   本想考虑用sendmail,因为RubyOnRails默认情况下就是用sendmail来发送。不过sendmail需要一些复杂的配置,而且人员和系统的用户绑定(也可分开,没有去研究)。
所以,干脆实现用stmp来实现,采用Gmail邮件。
  因为gmail用tls,用先安装插件
  ruby script/plugin install http://svn.xlsuite.org/trunk/vendor/plugins/action_mailer_tls/
  在environment.rb中加入
 config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
   :enable_starttls_auto => true,
:address => "smtp.gmail.com",
:port => 587,
#:domain => "mycompany.com",
:authentication => :plain,
:user_name => "xxx@gmail.com",
:password => "xxx"
}
config.action_mailer.raise_delivery_errors = true
config.action_mailer.perform_deliveries = true
config.action_mailer.default_charset = 'utf-8'

千万要注意这句,:enable_starttls_auto => true, 不然会出现如下错误
530 5.7.0 Must issue a STARTTLS command first. i6s

因为Rails中具体应用Mail,请参考文档
http://guides.rubyonrails.org/action_mailer_basics.html


Erlang知识-变量及数据类型

Posted by: bin in erlang on

公司里有项目要用到Erlang,关于Erlang的介绍,这里先简单交代一下

Erlang是一个丹麦的数学家,他搞出来的一个概率分布Erlan分布,并且用这个分布开创一们学科排队理论,电信上经常用这个分布来测算话务量,因此在电信界比较有名.当年Joe Amstrong把他的语言命名为Erlang也是为了纪念这个为电信领域作出过卓越贡献的人.
   Erlang是Ericsson和Ellemtel Computer ScientceLaboratories为解决电信领域中的并发和分布式问题,设计的语言;从理论应用于实践的角度讲,主要探索的是函数式语言能否应用到通信领域的大型交换机上,从Erlang的实践效果来看,答案是肯定的。
    Erlang的优点:
    (1) Code Loading Primitives允许在系统运行过程中升级代码。
    (2) Erlang的轻量级进程可以支持极高的并发性,而且在高并发的情况下内存使用相当的少。Erlang的并发性并不会受到宿主操作系统并发性的限制。Erlang的原子操
作是一个压栈级别的,而C语言是指令级别的。
   (3)最开始Erlang的设计目标就是实现分布式环境,一个Erlang的虚拟机就是一个Erlang网络上的节点。一个Erlang节点可以在另一个-Erlang节点上创建自己的并发进程,而子进程所在的节点可能是运行其他的操作系统的服务器。不同节点的之间的可以进行极为高效而又精确的通信,就像它们运行-在同一个节点一样。
    (4)Erlang内部建设有多种错误检测原语。我们可以通过这些原语来架设高容错性的系统。例如,一个进程可以监视其他进程的状态和活动,即使那些被监 -控的进程处于其他节点。在分布式状态下,我们可以把系统配置成具有Fail-over功能的分布式系统。当有其他节点出错的时候,系统会把他的运行场景自动快速-的切换备份节点上。
    (5) Erlang是一个"软"实时系统(Soft Real Time),它可以提供毫秒级别的响应。

变量
所有的变量都必须以大写字母开头。
X = 12832.
如果再执行 X=1244.则报错了。
注意:在Erlang中,X不是一个变量,至少不是你在Java或C中的那种变量。
另外,=不是赋值操作符。而模式匹配,变量只能被赋值一次。当我们第一次输入X=12832时,Erlang会问自己,"要怎么做才能让这样语句的值变是true?"(注:erlang的每一个语句都会有值),由于X没有被赋值,因此可以把12832绑定到X上。同时也使得语句有效。


浮点数
1> 5/3.
1.66667
2> 4/2.
2.00000
3> 5 div 3.
1
"/"永远返回浮点数。

原子
用来表示不同的非数字常量值。类似于java/c中的枚举类型。原子是一串以小写字母开头、后跟数字、字母或下划线(_)或邮件符号(@)的字符。而且原子是全局有效的,而且无需使用宏定义或者包含文件。
比如,red、december、a_login_name
使用单引号引起来的字符也是原子,一个原子的值就是原子自身。比如,'a'就等同于a

元组
将一定数量的项目组成单一的实体,那么就可以使用元组(tuple)。将若干个以逗号分割的值用一对花括号括起来,就形成了一个元组。如{ supercode, 1.75}.这个元组就包括了一个原子和一个浮点数。 元组类似于C语言中的结构。

  • 创建元组
    在声明元组时,就自动创建了元组,不需要时,元组也自动销毁。因为erlang有垃圾回收。

2> F = {firstName, joe}.
{firstName,joe}
3> L = {lastName, armstrong}.
{lastName,armstrong}
4> P = {person, F, L}.
{person,{firstName,joe},{lastName,armstrong}}


  • 从元组中提取字段值
    1> Point = {point, 10, 45}.
    {point, 10, 45}.
    2> {point, X, Y} = Point. 
    {point,10,45}
    3> X.
    10
    4> Y.
    45

注意
{my,X,Y}=Point, 将出错,因为my与point不匹配,如果{Mypoint,X,Y}=Point. 那么是正确的.

列表
列表用来存储数目可变的东西,如在商店里买到的商品。将若干个以逗号分割的值用一对方括号括起来,就形成了一个列表。
1> ThingsToBuy = [{apples,10},{pears,6},{milk,3}].
[{apples,10},{pears,6},{milk,3}]

列表之中的各个元素可以有各自不同的类型。
2> [1+7,hello,2-2,{cost, apple, 30-20},3].
[8,hello,0,{cost,apple,10},3]

列表的第一个元素称为列表的头(head),除去头,剩下的东西称为列表的尾。注意,列表的头可以是任意东西,但列表的尾通常还是一个列表。

3> ThingsToBuy1 = [{oranges,4},{newspaper,1}|ThingsToBuy].
[{oranges,4},{newspaper,1},{apples,10},{pears,6},{milk,3}]

4> [Buy1|ThingsToBuy2] = ThingsToBuy1.
[{oranges,4},{newspaper,1},{apples,10},{pears,6},{milk,3}]
绑定结果如下
Buy1 7→ {oranges,4}


字符串
严格地讲,Erlang中并没有字符串,字符串实际上也就是一个整数列表。
1> Name = "Hello".
"Hello"

可以用$符号来表示字符中整数值。
5> I = $s.
115
6> [I-32,$u,$r,$p,$r,$i,$s,$e].
"Surprise"


Nodepad++的美中不足

Posted by: bin in Untagged  on

      一直在用Notepad++,做为一款开源而免费的文本编辑器,它还是不错的,我偶尔用它快速查看一些文件,比如html,php,python,ruby,txt等等.我的机子上装了MyEclipse,VS2008,NetBeans,Aptana,所以开发是不会用Notepad++的,用它主要是快速,不想用这些超重的IDE拖我的笔记本,虽然有3G的内存.不过这两天用NotePad++,发现有个不太如意的地方.当打开多个文件时,注意是同时打开50个文件以上,而且涉及到查找,替换等.偶尔会没有响应,要比较内容太多了.UltraEditb也是如此,查找时窗口刷的厉害,默认的情况,语言的高亮支持没有nodepad++多, 另外,打开这么多的文件,在找文件时,比较麻烦,因为它的选择窗口,连首字母定位的功能都没有,不过这个功能UltraEdit倒是有的. 另外一直看到国外的ruby开发人员一直用TextMate,不过windows上没有这东东.不过有E - TextEditor号称是The power of TextMate on Windows.当然其他的编辑器还有Emacs,Vim,TextPad这些也都非常有名.后面这几款对键盘的掌握度要高些,而如果鼠标做大多数人的选择,面向的对象群体也相对少了,不过掌握后,效率也更高.


ASP.NET Forms验证(自定义、角色提供程序)

Posted by: bin in Untagged  on


一、普通实现方式

这种方式是最简单的,只需要配置一下就可以了。

1、执行aspnet_regsql命令建立数据库

aspnet_regsql命令在C:WINDOWSMicrosoft.NETFrameworkv2.0.50727目录下,按提示运行就可以了

2、新建一个web网站

在Web.Config中加入配置:
<code>
  <connectionStrings>
    <add name="MySqlConnection" connectionString="Data Source=dbserver;Initial Catalog=database;user id=userid;password=****;" />
  </connectionStrings>

  <system.web>
        <authorization>
            <deny users="?"/>
        </authorization>
        <authentication mode="Forms">
            <forms loginUrl="login.aspx" name=".ASPXAUTH"/>
        </authentication>

    <membership defaultProvider="SqlProvider">
      <providers>
        <clear />
        <add connectionStringName="MySqlConnection" applicationName="MyApplication"
          enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true"
          requiresUniqueEmail="true" passwordFormat="Hashed" name="SqlProvider"
          type="System.Web.Security.SqlMembershipProvider" />
      </providers>
    </membership>

  </system.web>
</code>
主要就是指定Forms验证使用的数据库,如果不指定数据库会使用本机默认的aspnetdb 数据库。

deny users="?"表示不允许匿名用户访问,也就是说当匿名用户访问时自动跳转到下面配置的login.aspx页面。
至于authorization和authentication节的其他属性可以参考MSDN,里面有很详细的介绍。

3、在网站里创建Default.aspx和Login.aspx页面

在Login.aspx页面里面放入Login和CreateUserWizard控件(因为我们新建的库中一个用户也没有,CreateUserWizard控件只是用来建立测试用户的,建好用户后可以把这个控件删除)
在Default.aspx页面中随便放入一些内容。

当我们访问Default.aspx时就会自动转入Login.aspx进行验证了。

二、自定义实现方式

采用第一种方式时会要求建立一个数据库,很多表,可能并不符合我们自己的业务要求。可以使用以下的自定义方式

1、利用Login控件的Authenticate事件

这个事件就是用来进行验证的,可以通过指定true值表示验证通过:
    protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
    {
        //判断用户名密码是否正确
        //
        e.Authenticated = true;
    }

2、完全抛开Login等控件,自己写代码

其实Login控件的核心主要也就是往Cookie里面放入一些值,那么我们可以在自己的代码中来进行这个操作:

    protected void Button1_Click(object sender, EventArgs e)
    {
        //判断用户名密码是否正确
        //.
        FormsAuthentication.SetAuthCookie(userName, false);
        if (Context.Request["ReturnUrl"] != null)
        {
            Response.Redirect(Context.Request["ReturnUrl"]);
        }
        else
        {
            Response.Redirect(FormsAuthentication.DefaultUrl);
        }
    }

采用以上两种方式就不用建立默认的数据库了,直接使用我们的逻辑进行验证操作

三、自定义角色提供程序

以上说的都是用户级别的验证,在有的情况下需要根据角色来进行验证,比如指定某个目录或某个aspx文件只能让哪几个角色的用户访问,根据角色来控制的话比较方便灵活。

1、在登录验证的时候把角色信息也保存到Cookie中去:
    protected void Button1_Click(object sender, EventArgs e)
    {
        //判断用户名密码是否正确
        //.

        //得到用户的角色,测试时暂时写死
        string userRoles = "Admins,testst";
        FormsAuthenticationTicket Ticket = new FormsAuthenticationTicket(1, user, DateTime.Now, DateTime.Now.AddMinutes(30), false, userRoles, "/");
        string HashTicket = FormsAuthentication.Encrypt(Ticket);

        //把角色信息保存到Cookie中去
        HttpCookie UserCookie = new HttpCookie(FormsAuthentication.FormsCookieName, HashTicket);
        Response.Cookies.Add(UserCookie);

        if (Context.Request["ReturnUrl"] != null)
        {
            Response.Redirect(Context.Request["ReturnUrl"]);
        }
        else
        {
            Response.Redirect(FormsAuthentication.DefaultUrl);
        }
    }

把角色信息加密成特定的格式保存。

2、自定义角色提供程序

如果要按照角色进行验证的话,肯定要涉及到角色提供程序,在默认情况下也是会去连接默认的数据库的,我们可以自己写一个角色提供程序来实现自己的逻辑。
首先在web.config中加入配置:
<code>
    <roleManager defaultProvider="MyRoleProvider"
      enabled="true"
      cacheRolesInCookie="true"
      cookieName=".ASPROLES"
      cookieTimeout="30"
      cookiePath="/"
      cookieRequireSSL="false"
      cookieSlidingExpiration="true"
      cookieProtection="All" >
      <providers>
        <clear />
        <add name="MyRoleProvider"
          type="MyRoleProvider"
          writeExceptionsToEventLog="false" />
      </providers>
    </roleManager>
</code>
这个就是指定我们的角色提供类MyRoleProvider。

这个类必须从System.Web.Security.RoleProvider继承,只要重载实现一个方法就可以了(其他方法返回异常):
<code>

    public override string[] GetRolesForUser(string username)
    {
        FormsIdentity Id = HttpContext.Current.User.Identity as FormsIdentity;
        if (Id != null)
        {
            return Id.Ticket.UserData.Split(new Char[] { ',' });
        }
        return null;
    }</code>

也就是从我们之前保存到Cookie中的值取得用户角色(FormsAuthentication会自动把保存的cookie转化成User内的值)

之后我们就可以在web.config中配置角色验证规则了:
<code>
  <location path="admin">
    <system.web>
      <authorization>
        <allow roles="Admins"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location></code>

或者也可以在代码中判断:
bool a = User.IsInRole("testt");

判断起来还是很方便的。

四、单点登录

使用Forms的单点登录主要是通过machineKey的配置,machineKey 元素对密钥进行配置,以便将其用于对 Forms 身份验证 Cookie 数据和视图状态数据进行加密和解密,并将其用于对进程外会话状态标识进行验证

使用这种方式的单点登录目前只能实现相同主机或相同子域站点之间的同步登录,比如www.cnblogs.com和firstyi.cnblogs.com可以实现,但是www.cnblogs.com和www.sina.com.cn就不能实现了,对于非同一父域名下的域名间不能跨站登录

主要配置如下:
<code>
  <machineKey validationKey="282487E295028E59B8F411ACB689CCD6F39DDD21E6055A3EE480424315994760ADF21B580D8587DB675FA02F79167413044E25309CCCDB647174D5B3D0DD9141" decryptionKey="8B6697227CBCA902B1A0925D40FAA00B353F2DF4359D2099" validation="SHA1"/>
  <authentication mode="Forms">
      <forms loginUrl="login.aspx" name=".ASPXAUTH1" domain=".cnblogs.com" />
  </authentication>
</code>
要实现单点登录的多个web站点的machineKey必须一样,forms里面的name和domain也必须一样

这样配置好之后,在其中一个站点登录后再调转到另一个站点就不需要再次登录了。

注:如果MOSS网站采用Forms验证方式的话,只要把MOSS站点的对应配置改成和自己的Asp.Net站点一致,那么可以从自己的站点直接进入MOSS站点,也不需要重新登录(MOSS站点和自己的站点要有相同的用户名)

其他:

Forms验证之后可以使用以下方法退出登录:
FormsAuthentication.SignOut();


另外这些登录的后台Module是配置在C:WINDOWSMicrosoft.NETFrameworkv2.0.50727CONFIGweb.config文件中的:
<code>

      <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule"/>
      <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule"/>
      <add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule"/>

</code>
附:
最后的web.config文件
<code>
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <system.web>
        <authorization>
            <deny users="?"/>
        </authorization>
        <authentication mode="Forms">
      <forms loginUrl="login.aspx" name=".ASPXAUTH1" domain=".cnblogs.com" />
    </authentication>
    <machineKey validationKey="F9A61F796A204D9945889B64D9DA5086E89CEC5200F0CED4" decryptionKey="D679BCF2A76DEBB04D7FED5E5967F46C92FEF2B31AD5D7C9" validation="SHA1" />
    <compilation debug="true"/>
   
    <roleManager defaultProvider="MyRoleProvider"
      enabled="true"
      cacheRolesInCookie="true"
      cookieName=".ASPROLES"
      cookieTimeout="30"
      cookiePath="/"
      cookieRequireSSL="false"
      cookieSlidingExpiration="true"
      cookieProtection="All" >
      <providers>
        <clear />
        <add name="MyRoleProvider"
          type="MyRoleProvider"
          writeExceptionsToEventLog="false" />
      </providers>
    </roleManager>

  </system.web>
  <location path="admin">
    <system.web>
      <authorization>
        <allow roles="Admins"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>
</configuration></code>


JAVA中的数据库连接池

Posted by: 快乐的小鱼 in Untagged  on

问题提出

应用系统中频繁的对数据库进行操作,每次操作都要进行“建立,操作,释放”等过程,导致性能低下,资源浪费。

数据库连接池(connection pool)的工作原理

对于共享资源,有一个很著名的设计模式:资源池(Resource Pool)。该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接 建立一个缓冲池。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从缓冲池中取出一个,使用完毕之后再放回去。 

 

  服务器自带的连接池

  JDBCAPI中没有提供连接池的方法。一些大型的WEB应用服务器如BEAWebLogicIBMWebSphere等提供了连接池的机制,但是必须有其第三方的专用类方法支持连接池的用法。

  连接池关键问题分析

  1、并发问题

  为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题。这个问题相对比较好解决,因为Java语言自身提供了对并发管理的 支持,使用synchronized关键字即可确保线程是同步的。使用方法为直接在类方法前面加上synchronized关键字,如:

public synchronized Connection getConnection()

  2、多数据库服务器和多用户

  对于大型的企业级应用,常常需要同时连接不同的数据库(如连接OracleSybase)。如何连接不同的数据库呢?我们采用的策略是: 设计一个符合单例模式的连接池管理类,在连接池管理类的唯一实例被创建时读取一个资源文件,其中资源文件中存放着多个数据库的url地址 ()﹑用户名()﹑密码 ()等信息。

  3、事务处理

  我们知道,事务具有原子性,此时要求对数据库的操作符合“ALL-ALL-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。

  在Java语言中,Connection类本身提供了对事务的支持,可以通过设置ConnectionAutoCommit属性为 false,然后显式的调用commitrollback方法来实现。但要高效的进行Connection复用,就必须提供相应的事务支持机制。可采用 每一个事务独占一个连接来实现,这种方法可以大大降低事务管理的复杂性。

  4、连接池的分配与释放

  连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。

  5、连接池的配置与维护

  连接池中到底应该放置多少连接,才能使系统的性能最佳?系统可采取设置最小连接数(minConn)和最大连接数(maxConn)来控制 连接池中的连接。

  

具体的实现

javax.sql.RowSet 包添加了对缓冲数据源的支持,即可以将缓冲池缓冲的数据库连接看作是一个是实实在在的数据源服务来使用。RowSet 包提供了好几个接口用于处理数据库缓冲池,主要的接口有:
1
DataSource 接口:DataSource 接口的实例对象代表了存在于中间层服务器中的缓冲数据源服务。使用它可以返还数据库缓冲池中现存的数据库连接,DataSource 接口的实例对象实际上是某个JNDI 服务的提供者,在使用它之前,该JNDI 服务对象必须先在中间层服务器环境中注册,并且和某个服务名绑定在一起,然后它才能被别的Java 应用程序调用。
2
ConnectionPoolDataSource 接口:该接口可以用于创建一个被缓冲于缓冲池的数据库物理连接,它有可能会被DataSource 接口的实例对象调用。
3
PooledConnection 接口:该接口代表被缓冲的数据库连接,它定义了一个getConnection()方法使用这个方法可以返回java.sql.Connection 接口的实例对象。

 

在继续连接池之前,先讲一下JNDI概述 

 
  我们大家每天都不知不觉地使用了命名服务。例如,当你在web浏览器输入URL,http://java.sun.com 时,DNS(Domain Name System,域名系统)将这个符号URL名转换成通讯标识(IP地址)。命名系统中的对象可以是DNS记录中的名 称、应用服务器中的EJB组件(Enterprise JavaBeans Component) LDAP(Lightweight Directory Access Protocol)中的用户Profile 

  目录服务是命名服务的自然扩展。两者之间的关键差别是目录服务中对象可以有属性(例如,用户有email地址),而命名服务中对象没有属性。因此,在 目录服务中,你可以根据属性搜索对象。JNDI允许你访问文件系统中的文件,定位远程RMI注册的对象,访问象LDAP这样的目录服务,定位网络上的 EJB组件。 

  对于象LDAP 客户端、应用launcher、类浏览器、网络管理实用程序,甚至地址薄这样的应用来说,JNDI是一个很好的选择。 

 

JAVAtomcat应用。

JAVA中代码

Context ic = new InitialContext();

DataSource source = (DataSource) ic .lookup("java:comp/env/jdbc/books");

connection = source.getConnection();

 

Tomcatconf/context.xml中的配置,在根节点Context中加入

  

   <Resource name="jdbc/books"  auth="Container" type="javax.sql.DataSource"  maxActive="100"     maxIdle="30" maxWait="10000"    username="admin"   password="admin"     driverClassName="com.microsoft.jdbc.sqlserver.SQLServerDriver"      url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=books" />

 

属性名称

说明

name

指定ResourceJNDI名称

auth

指定管理ResourceManagerContainer:由容器创建和管理|Application:由Web应用创建和管理)

type

指定Resource所属的Java

maxActive

指定连接池中处于活动状态的数据库连接的最大数目

maxIdle

指定连接池中处于空闲状态的数据库连接的最大数目

maxWait

指定连接池中的连接处于空闲的最长时间,超过这个时间会抛出异常,取值为-1,表示可以无限期等待

 

补充:如果是Mysql的数据库

  
              username="ccs" password="secret" url="jdbc:mysql://localhost:3306/ccs"
              driverClassName="com.mysql.jdbc.Driver"
              maxActive="20" maxIdle="10"/>

 

把数据库驱动(mssqlserver2.jar).jar文件,加入到Tomcatcommonlib

 

注意:在Tomcate5.5以下的版本,还需要项目工程的web.xml中添加,资源引用

    jdbc/books

    javax.sql.DataSource

    Container

 

 

getClass()

 

这是java 中的反射机制,当一个class生成实例的时候JVM中都会有一个class来描述这个class的属性,你可以通过实例的.getclass()这个方法来拿到这个class

 

    InputStream is = getClass().getResourceAsStream("/db.properties");

 

  这个方法实际上是通过ClassLoader来工作的      所以要把db.properties   放到ClassPath里面去  

 

注意:src/目录下的文件,部署后,会放到WEB-INFclasses

 

Class

forName(className)这个名为className的类装入JVM  
 
这样就可以动态的加载类,通过Class的反射机制可以获得此类的一些信息

 

Class.forName(); 的好处在于你不用编译/运行时依赖于特定的 JDBC Driver , 也就减少了项目代码的依赖性. 而且也很容易改造成从配置文件读取JDBC配置, 从而可以在运行时动态更换JDBC/DB.

实际上这样也可以的。

com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();

//or

//new com.mysql.jdbc.Driver();   

String url = "jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8";

String user = "";

String psw = "";

Connection con = DriverManager.getConnection(url,user,psw);

 

ResultResultSet的区别

 在开发过程中,我们不能返回ResultSet对象,连接一旦断开,在连接上建立的会话和在会话上建立的结果集都会自动关闭.所以我们必须开发类似于返 回List的接口.但是针对通用函数,List是无能为力的,我们要返回比List更通用的,jstl中的Result可以完成此任务.

 

解析Java对象的equals()hashCode()的使用。

Java语言中,equals()hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,就要设计另外一个。在多数情况 下,这两个函数是不用考虑的,直接使用它们的默认设计就可以了。但是在一些情况下,这两个函数最好是自己设计,才能确保整个程序的正常运行。

需要自己设计的场合:当一个对象(比如,自定义的类)加入到一个集合中时,并且要对集合中的对象进行添加,搜索,删除等操作时。可能需要重写这两个方法。

equals():

它是用于进行两个对象的比较的,是对象内容的比较,当然也能用于进行对象参阅值的比较。

对象内容的比较才是设计equals()的真正目的,Java语言对equals()的要求如下,这些要求是必须遵循的。否则,你就不该浪费时间:

·         对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”

·         反射性:x.equals(x)必须返回是“true”

·         类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”

·         还有一致性:如果x.equals(y)返回是“true”,只要xy内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”

·         任何情况下,x.equals(null),永远返回是“false”x.equals(x不同类型的对象)永远返回是“false”

hashCode():
JDK API 1.6.0的解释:
hashCodepublic int hashCode()
返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。 hashCode 的常规协定是:

·         如果x.equals(y)返回“true”,那么xyhashCode()必须相等。

·         如果x.equals(y)返回“false”,那么xyhashCode()有可能相等,也有可能不等。

 第二规则,可能是由于hash冲突造成的。




友情链接: 100分教育社区 上海市企业信息化促进中心 国家工业和信息化部 中国信息安全评测认证中心 中国教育网 多特软件站 天空软件站 华军软件园 上海西楚礼仪