??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲AV人无码激艳猛片,亚洲男人电影天堂,亚洲一区免费视频http://www.tkk7.com/yanzhou/喂马, 劈柴, 周游世界zh-cnSat, 10 May 2025 16:07:24 GMTSat, 10 May 2025 16:07:24 GMT60HTML控g的方法和属?/title><link>http://www.tkk7.com/yanzhou/archive/2006/12/30/91030.html</link><dc:creator>周游世界</dc:creator><author>周游世界</author><pubDate>Sat, 30 Dec 2006 08:57:00 GMT</pubDate><guid>http://www.tkk7.com/yanzhou/archive/2006/12/30/91030.html</guid><wfw:comment>http://www.tkk7.com/yanzhou/comments/91030.html</wfw:comment><comments>http://www.tkk7.com/yanzhou/archive/2006/12/30/91030.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yanzhou/comments/commentRss/91030.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yanzhou/services/trackbacks/91030.html</trackback:ping><description><![CDATA[     摘要: API 参? 对象参? 此部分显CZ Google Gadgets API 中与脚本相关的不同对象,包括它们的属性、方法和相关事g。注意,许多对象l承?basicElement 的属性、方法和事g? 同样Q如果说一个方法返回了一个元素,q意味着在小工具?XML 定义中定义了一个元素,它承自 ...  <a href='http://www.tkk7.com/yanzhou/archive/2006/12/30/91030.html'>阅读全文</a><img src ="http://www.tkk7.com/yanzhou/aggbug/91030.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yanzhou/" target="_blank">周游世界</a> 2006-12-30 16:57 <a href="http://www.tkk7.com/yanzhou/archive/2006/12/30/91030.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>几种证书格式说明及Keytool命ohttp://www.tkk7.com/yanzhou/archive/2006/12/12/87208.html周游世界周游世界Tue, 12 Dec 2006 04:50:00 GMThttp://www.tkk7.com/yanzhou/archive/2006/12/12/87208.htmlhttp://www.tkk7.com/yanzhou/comments/87208.htmlhttp://www.tkk7.com/yanzhou/archive/2006/12/12/87208.html#Feedback0http://www.tkk7.com/yanzhou/comments/commentRss/87208.htmlhttp://www.tkk7.com/yanzhou/services/trackbacks/87208.html.keystore 证书库,包含用户的公钥、私钥和证书?br />
 1            FileInputStream in = new FileInputStream(Path +"RGCA.keystore");
 2            KeyStore ks = KeyStore.getInstance("JKS");
 3            ks.load(in, pwd.toCharArray());
 4            Certificate certificate = ks.getCertificate(alias);
 5            System.out.println("从证书库中取?"+RadiusUtil.getHexString(certificate.getEncoded()));
 6            System.out.println("从证书库中取得PublicKeyQ?/span>"+RadiusUtil.getHexString(certificate.getPublicKey().getEncoded()));
 7            X509Certificate x = (X509Certificate)certificate;
 8            System.out.println("从证书库中取得SignatureQ?/span>"+RadiusUtil.getHexString(x.getSignature()));
 9            PrivateKey caprk = (PrivateKey)ks.getKey(alias, pwd.toCharArray());
10            System.out.println("U钥:"+RadiusUtil.getHexString(caprk.getEncoded()));


周游世界 2006-12-12 12:50 发表评论
]]>
[ZZ]认证方式探讨 EAP-MSCHAPV2http://www.tkk7.com/yanzhou/archive/2006/11/12/80703.html周游世界周游世界Sun, 12 Nov 2006 07:24:00 GMThttp://www.tkk7.com/yanzhou/archive/2006/11/12/80703.htmlhttp://www.tkk7.com/yanzhou/comments/80703.htmlhttp://www.tkk7.com/yanzhou/archive/2006/11/12/80703.html#Feedback0http://www.tkk7.com/yanzhou/comments/commentRss/80703.htmlhttp://www.tkk7.com/yanzhou/services/trackbacks/80703.html 认证方式探讨 EAP-MSCHAPV2

MSCHAP方式?首先服务器发一个challengel用?用户向RADIUS发一个用MD4加密?password,challenge)lRADIUS(叫response),radius的MSCHAP模块向LDAP询问NTPASSWORD,然后自己再用challenge和NTPASSWORD,来计一个response,两个response相比较完成验?如果LDAP无法l出NTPASSWORD或送出SHA加密的NTPASSWORD,MS-CHAP无法验证了.唯一可行的办法是把LDAP的SCHEMA中加入NTPASSWORD?q明文存?才能满MS-CHAP的要?


PEAP-MSCHAPV2程Q?
  1、创Z个连接后QAP发送一个EAP-Request/Identity消息l客L(fng)?br />  2、客L(fng)回复一个EAP-Response/Identity消息Q包含客L(fng)的标识,通常是名字?br />  3、AP把这个消息传递给Radius服务器。从现在开始,逻辑通信׃Radius服务器到无线客户端了QAP,AC是一个中介设备?br />  4、Radius服务器发送一个EAP-Request/Start PEAP消息l客L(fng)?br />  5、无U客L(fng)和Radius服务器发送一pd的TLS消息通过协商建立的隧道。Raiuds服务器发送一个证书链让客L(fng)认证。最后,Radius服务器已l认证了无线客户端。两端都军_使用的加密信息?br />  在PEAP TLS隧道创徏后,采用MS-CHAPV2认证?br />  6、Radius服务器发送一个EAP-Request/Identity消息?br />  7、无U客L(fng)发送一个EAP-Response/Identity 消息Q消息包用户名?br />  8、Radius服务器发送一个EAP-Request/EAP-MS-CHAP-V2挑战消息Q包含挑战字W串?br />  9、无U客L(fng)回复一个EAP-Response/EAP-MS-CHAPV2回复消息Q包含对q个挑战的应{和一个自q挑战?br />  10、Radius服务器发送一个EAP-Request/EAP-MS-CHAPV2成功的消息,指出无线客户端的回应是正的Q且包含无线客户端的挑战字符丌Ӏ?br />  11、无U客L(fng)回应一个EAP-Response/EAP-MS-CHAPV2的ACK消息Q指CRadius服务器的回应消息是正的?br />  12、Radius服务器发送一个EAP-Success消息?/p>

EAP -TLS是一个IETF标准。TLS即传输层安全QTransport Layer SecurityQ,也称为SSL。它原本是一U传输层的安全协议,主要实现两个功能Qn份鉴别与信息加密。TLS可实现基于证书的单向w䆾鉴别Q只鉴别服务器)和双向n份鉴别(同时鉴别客户端与服务器)。TLS在完成n份鉴别的同时Q还交换密钥信息Q通过密钥信息可导Z话密钥用于信息加密?br />需要指出的是,在这里TLSq不是作Z个安全传输层协议跑在TCP/IP层之上,而是TLS的Handshake Record直接嵌套在EAP数据包中Q作为EAP Request/Response的数据来传送,通过TLS的Handshake Record完成单向或双向的w䆾鉴别。EAPQTLS只利用了TLS的n份鉴别功能,q没有利用TLS建立的加密通道?br />Z能够q一步利?TLS建立的安全通道交换EAPw䆾鉴别信息QIETF随后出台了PEAPQProtected EAP ProtocolQ标准草案。PEAP不但通过EAP Request/Response数据包传送TLS的Handshake Record完成w䆾鉴别Qƈ且完成n份鉴别后q一步通过TLS的Data Record再传送EAPw䆾鉴别协议?/p>

对于密钥Q?br />der  “专有编码规则”文件?der 文g包含证书的二q制表示Q包含其公共密钥Q但不包含其专用密钥。它?.arm 文g非常怼Q除了表C是二进制的Q而非 ASCII?
.p12  "PKCS 12" 文gQ其?PKCS 代表“公共密钥密码术标准 (Public-Key CryptographyStandards)”?p12 文g包含证书的二q制表示Q包含其公共密钥和专用密钥。一?.p12 文g中也可能包含多个证书Q例如,证书、发书的 CA 的证书、CA 证书的发以及他的发等{。因?.p12 文g包含专用密钥Q它是受口o保护的?br />



周游世界 2006-11-12 15:24 发表评论
]]>
x的CVS, SVN http://www.tkk7.com/yanzhou/archive/2006/11/06/79471.html周游世界周游世界Mon, 06 Nov 2006 12:56:00 GMThttp://www.tkk7.com/yanzhou/archive/2006/11/06/79471.htmlhttp://www.tkk7.com/yanzhou/comments/79471.htmlhttp://www.tkk7.com/yanzhou/archive/2006/11/06/79471.html#Feedback0http://www.tkk7.com/yanzhou/comments/commentRss/79471.htmlhttp://www.tkk7.com/yanzhou/services/trackbacks/79471.html:pserver:anonymous@cvs.sourceforge.net:/cvsroot/hibernate 模块Hibernate3

Spring
:pserver:anonymous@cvs.sourceforge.net:/cvsroot/springframework 模块spring

Groovy
http://svn.codehaus.org/groovy/

Grails
http://svn.codehaus.org/grails/

Seam
:pserver:anonymous@anoncvs.forge.jboss.com:/cvsroot/jboss 模块jboss-seam-head

MyFaces
https://svn.apache.org/repos/asf/myfaces/current

Taconite
:pserver:anonymous@cvs.sourceforge.net:/cvsroot/taconite 模块taconite

Liferay
:pserver:anonymous@cvs.sourceforge.net:/cvsroot/lportal 模块portal

XFire
:pserver:anonymous@cvs.xfire.codehaus.org:/home/projects/xfire/scm 模块xfire

GlassFish
:pserver:guest@cvs.dev.java.net:/cvs 模块glassfish

Roller
:pserver:guest@cvs.dev.java.net:/cvs 模块roller

SpringModules
:pserver:guest@cvs.dev.java.net:/cvs 模块springmodules

周游世界 2006-11-06 20:56 发表评论
]]>
JAVA教程 W八?Java|络~程(?http://www.tkk7.com/yanzhou/archive/2006/11/05/79186.html周游世界周游世界Sun, 05 Nov 2006 04:36:00 GMThttp://www.tkk7.com/yanzhou/archive/2006/11/05/79186.htmlhttp://www.tkk7.com/yanzhou/comments/79186.htmlhttp://www.tkk7.com/yanzhou/archive/2006/11/05/79186.html#Feedback0http://www.tkk7.com/yanzhou/comments/commentRss/79186.htmlhttp://www.tkk7.com/yanzhou/services/trackbacks/79186.html
8.3.10 据报Datagram通讯

  前面在介lTCP/IP协议的时候,我们已经提到Q在TCP/IP协议的传输层除了TCP协议之外q有一个UDP协议Q相比而言UDP的应用不如TCPq泛Q几个标准的应用层协?HTTPQFTPQSMTP…用的都是TCP协议。但是,随着计算机网l的发展QUDP协议正越来越来显C出其威力,其是在需要很强的实时交互性的场合Q如|络游戏Q视频会议等QUDP更是昄出极强的威力Q下面我们就介绍一下Java环境下如何实现UDP|络传输?

  8.3.11 什么是Datagram

  所谓数据报QDatagramQ就跟日常生zM的邮件系l一P是不能保证可靠的寄到的,而面向链接的TCP好比电(sh)话,双方能肯定对Ҏ(gu)受到了信息。在本章前面Q我们已l对UDP和TCPq行了比较,在这里再E作节Q?

  TCPQ可靠,传输大小无限Ӟ但是需要连接徏立时_差错控制开销大?
  UDPQ不可靠Q差错控制开销较小Q传输大限制在64K以下Q不需要徏立连接?

  MQ这两种协议各有特点Q应用的场合也不同,是完全互补的两个协议Q在TCP/IP协议中占有同样重要的CQ要学好|络~程Q两者缺一不可?

  8.3.12 Datagram通讯的表C方法:DatagramSocketQDatagramPacket

  包java.net中提供了两个cDatagramSocket和DatagramPacket用来支持数据报通信QDatagramSocket用于在程序之间徏立传送数据报的通信q接Q?DatagramPacket则用来表CZ个数据报。先来看一下DatagramSocket的构造方法:
   DatagramSocketQ)Q?
   DatagramSocketQint protQ?
   DatagramSocket(int port, InetAddress laddr)
  
  其中Qport指明socket所使用的端口号Q如果未指明端口P则把socketq接到本CZ一个可用的端口。laddr指明一个可用的本地地址。给出端口号时要保证不发生端口冲H,否则会生成SocketExceptioncM外。注意:上述的两个构造方法都声明抛弃非运行时例外 SocketExceptionQ程序中必须q行处理Q或者捕莗或者声明抛弃?

  用数据报方式~写client/serverE序Ӟ无论在客hq是服务方,首先都要建立一个DatagramSocket对象Q用来接收或发送数据报Q然后用DatagramPacketcd象作Z输数据的载体。下面看一下DatagramPacket的构造方?Q?
   DatagramPacketQbyte buf[],int lengthQ;
   DatagramPacket(byte buf[], int length, InetAddress addr, int port);
   DatagramPacket(byte[] buf, int offset, int length)Q?
   DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)Q?

  其中Qbuf中存放数据报数据Qlength为数据报中数据的长度Qaddr和port旨明目的地址Qoffset指明了数据报的位U量?

  在接收数据前Q应该采用上面的W一U方法生成一个DatagramPacket对象Q给出接收数据的~冲区及光度。然后调用DatagramSocket 的方法receive(){待数据报的到来Qreceive()一直等待,直到收到一个数据报为止?
  DatagramPacket packet=new DatagramPacket(buf, 256);
  Socket.receive (packet);

  发送数据前Q也要先生成一个新的DatagramPacket对象Q这时要使用上面的第二种构造方法,在给出存攑֏送数据的~冲区的同时Q还要给出完整的目的地址Q包括IP地址和端口号。发送数据是通过DatagramSocket的方法send()实现的,send()Ҏ(gu)数据报的目的地址来寻径,以传递数据报?
  DatagramPacket packet=new DatagramPacket(buf, length, address, port);
  Socket.send(packet)Q?

  在构造数据报Ӟ要给出InetAddresscd数。类InetAddress在包java.net中定义,用来表示一个Internet地址Q我们可以通过它提供的cL法getByNameQ)从一个表CZ机名的字W串获取该主机的IP地址Q然后再获取相应的地址信息?

  8.3.13 ZUDP的简单的Client/ServerE序设计

  有了上面的知识,我们可以来构g一个基于UDP的C/S |络传输模型

  1. 客户方程?QuoteClient.java

  import java.io.*;
  import java.net.*;
  import java.util.*;
  public class QuoteClient {
   public static void main(String[] args) throws IOException
   {
    if(args.length!=1) {
    //如果启动的时候没有给出Server的名字,那么出错退?
     System.out.println("Usage:java QuoteClient ");
     //打印出错信息
     return; //q回
    }

    DatagramSocket socket=new DatagramSocklet();
    //创徏数据报套接字

    Byte[] buf=new byte[256]; //创徏~冲?
    InetAddress address=InetAddress.getByName(args [0]);
  //由命令行l出的第一个参数默认ؓServer的名字,通过它得到Server的IP信息
    DatagramPacket packet=new DatagramPacket (buf, buf.length, address, 4445);
    //创徏DatagramPacket对象
    socket.send(packet); //发?
    packet=new DatagramPacket(buf,buf.length);
    //创徏新的DatagramPacket对象Q用来接收数据报
    socket.receive(packet); //接收
    String received=new String(packet.getData());
    //Ҏ(gu)接收到的字节数组生成相应的字W串
    System.out.println("Quote of the Moment:"+received );
    //打印生成的字W串

    socket.close(); //关闭套接?
   }
  }

  2. 服务?/font>方程?QuoteServer.java

  public class QuoteServer{
   public static void main(String args[]) throws java.io.IOException
   {
    new QuoteServerThread().start();
    //启动一个QuoteServerThreadU程
   }
  }

  3. E序QuoteServerThread.java

  import java.io.*;
  import java.net.*;
  import java.util.*;
  //服务器线E?
  public class QuoteServerThread extends Thread
  {
  protected DatagramSocket socket=null;
  //记录和本对象相关联的DatagramSocket对象
  protected BufferedReader in=null;
  //用来L件的一个Reader
  protected boolean moreQuotes=true;
  //标志变量Q是否l操?

  public QuoteServerThread() throws IOException {
  //无参数的构造函?
    this("QuoteServerThread");
    //以QuoteServerThread为默认D用带参数的构造函?
  }
  public QuoteServerThread(String name) throws IOException {
    super(name); //调用父类的构造函?
    socket=new DatagramSocket(4445);
    //在端?445创徏数据报套接字
    try{
      in= new BufferedReader(new FileReader(" one-liners.txt"));
      //打开一个文Ӟ构造相应的BufferReader对象
    }catch(FileNotFoundException e) { //异常处理
      System.err.println("Could not open quote file. Serving time instead.");
       //打印出错信息
    }
  }
  public void run() //U程M
  {
    while(moreQuotes) {
     try{
       byte[] buf=new byte[256]; //创徏~冲?
       DatagramPacket packet=new DatagramPacket(buf,buf.length);
       //q冲区构造DatagramPacket对象
       socket.receive(packet); //接收数据?
       String dString=null;
       if(in= =null) dString=new Date().toString();
       //如果初始化的时候打开文gp|了,
       //则用日期作传送的字符?
       else dString=getNextQuote();
       //否则调用成员函数从文件中d字符?
       buf=dString.getByte();
       //把String转换成字节数l,以便传?

       InetAddress address=packet.getAddress();
       //从Client端传来的Packet中得到Client地址
       int port=packet.getPort(); //和端口号
       packet=new DatagramPacket(buf,buf.length,address,port);
       //Ҏ(gu)客户端信息构建DatagramPacket
       socket.send(packet); //发送数据报
      }catch(IOException e) { //异常处理
       e.printStackTrace(); //打印错误?
       moreQuotes=false; //标志变量|falseQ以l束循环
      }
    }
    socket.close(); //关闭数据报套接字
  }

  protected String getNextQuotes(){
  //成员函数Q从文g中读数据
    String returnValue=null;
    try {
       if((returnValue=in.readLine())= =null) {
       //从文件中M行,如果d了文件尾
       in.close( ); //关闭输入?
       moreQuotes=false;
       //标志变量|falseQ以l束循环
       returnValue="No more quotes. Goodbye.";
       //|返回?
       } //否则q回字符串即Z文gd的字W串
    }catch(IOEception e) { //异常处理
       returnValue="IOException occurred in server";
       //|异常返回?
    }
    return returnValue; //q回字符?
  }
  }
可以看出使用UDP和用TCP在程序上q是有很大的区别的。一个比较明昄区别是,UDP的Socket~程是不提供监听功能的,也就是说通信双方更ؓq等Q面对的接口是完全一L(fng)。但是ؓ了用UDP实现C/Sl构Q在使用UDP时可以用DatagramSocket.receive()来实现类g监听的功能。因为receive()是阻塞的函数Q当它返回时Q缓冲区里已l填满了接受到的一个数据报Qƈ且可以从该数据报得到发送方的各U信息,q一点跟 accept()是很相象的,因而可以根据读入的数据报来军_下一步的动作Q这pC跟网l监听相似的效果?

  

  8.3.14 用数据报q行q播通讯

  DatagramSocket只允许数据报发送一个目的地址Qjava.net包中提供了一个类MulticastSocketQ允许数据报以广播方式发送到该端口的所有客戗MulticastSocket用在客户端,监听服务器广播来的数据?

  我们对上面的E序作一些修改,利用MulticastSocket实现q播通信。新E序完成的功能是使同时运行的多个客户E序能够接收到服务器发送来的相同的信息Q显C在各自的屏q上?

  1. 客户方程?MulticastClient.java

  import java.io.*;
  import java.net.*;
  import java.util.*;
  public class MulticastClient {
    public static void main(String args[]) throws IOException
    {
     MulticastSocket socket=new MulticastSocket(4446);
     //创徏4446端口的广播套接字
     InetAddress address=InetAddress.getByName("230.0.0.1");
     //得到230.0.0.1的地址信息
     socket.joinGroup(address);
     //使用joinGroup()广播套接字l定到地址?
     DatagramPacket packet;

     for(int i=0;i<5;i++) {
       byte[] buf=new byte[256];
       //创徏~冲?
       packet=new DatagramPacket(buf,buf.length);
       //创徏接收数据?
       socket.receive(packet); //接收
       String received=new String(packet.getData());
       //由接收到的数据报得到字节数组Q?
       //q由此构造一个String对象
       System.out.println("Quote of theMoment:"+received);
       //打印得到的字W串
     } //循环5?
     socket.leaveGroup(address);
     //把广播套接字从地址上解除绑?
     socket.close(); //关闭q播套接?
   }
  }

  2. 服务器方E序:MulticastServer.java

  public class MulticastServer{
    public static void main(String args[]) throws java.io.IOException
    {
      new MulticastServerThread().start();
      //启动一个服务器U程
    }
  }

  3. E序MulticastServerThread.java

  import java.io.*;
  import java.net.*;
  import java.util.*;
  public class MulticastServerThread extends QuoteServerThread
  //从QuoteServerThreadl承得到新的服务器线E类MulticastServerThread
  {
    Private long FIVE_SECOND=5000; //定义帔RQ?U钟
    public MulticastServerThread(String name) throws IOException
    {
      super("MulticastServerThread");
      //调用父类Q也是QuoteServerThread的构造函?
    }

    public void run() //重写父类的线E主?
    {
     while(moreQuotes) {
     //Ҏ(gu)标志变量判断是否l箋循环
      try{
        byte[] buf=new byte[256];
        //创徏~冲?
        String dString=null;
        if(in==null) dString=new Date().toString();
        //如果初始化的时候打开文gp|了,
        //则用日期作传送的字符?
        else dString=getNextQuote();
        //否则调用成员函数从文件中d字符?
        buf=dString.getByte();
        //把String转换成字节数l,以便传送send it
        InetAddress group=InetAddress.getByName("230.0.0.1");
        //得到230.0.0.1的地址信息
        DatagramPacket packet=new DatagramPacket(buf,buf.length,group,4446);
        //Ҏ(gu)~冲区,q播地址Q和端口号创建DatagramPacket对象
        socket.send(packet); //发送该Packet
        try{
          sleep((long)(Math.random()*FIVE_SECONDS));
          //随机{待一D|_0?U之?
        }catch(InterruptedException e) { } //异常处理
      }catch(IOException e){ //异常处理
        e.printStackTrace( ); //打印错误?

        moreQuotes=false; //|结束@环标?
      }
    }
    socket.close( ); //关闭q播套接?
   }
  }

  xQJava|络~程q一章已l讲解完毕。读者通过学习(fn)Q应该对|络~程有了一个清晰的认识Q可能对某些概念q不是十分的清楚Q还是需要更多的实践来进一步掌握。编E语a的学?fn)不同于一般的学习(fn)Q及其强调实늚重要性。读者应该对URL|络~程QSocket中的TCPQUDP~程q行大量的练?fn)才能更好的掌握本章中所提到的一些概念,才能真正学到Java|络~程的精髓!

  最后几个小节所丄例子Q读者务必要亲自试验一下,如果遇到问题Q想办法解决之。最好能Ҏ(gu)自己的意囑֊以改q。这h能更好的理解q几个程序,理解其中所包含的编E思想?

  ?/span>本讲结?

  本讲主要讲解了Java环境下的|络~程。因为TCP/IP协议是Java|络~程的基知识Q本讲开重点介l了TCP/IP协议中的一些概念, TCP/IP协议本n是一个十分庞大的pȝQ用几个节是不可能讲清楚的。所以我们只是联pd际,讲解了一些最基本的概念,帮助学生理解后面的相兛_宏V重Ҏ(gu)一下几个概念:L名,IPQ端口,服务cdQTCPQUDP?

  后箋的内容分Z大块Q一块是以URLZU,讲解如何通过URLcdURLConnectionc访问WWW|络资源Q由于用URL十分方便直观Q尽功能不是很强,q是值得推荐的一U网l编E方法,其是对于初学者特别容易接受。本质上ԌURL|络~程在传输层使用的还是TCP协议?

  另一块是以Socket接口和C/S|络~程模型ZU,依次讲解了如何用Java实现ZTCP的C/Sl构Q主要用到的cLSocketQServerSocket。以及如何用Java实现Z UDP的C/Sl构Q还讨论了一U特D的传输方式Q广播方式,q种方式是UDP所Ҏ(gu)的,主要用到的类有DatagramSocket , DatagramPacket, MulticastSocket。这一块在Java|络~程中相对而言是最隄Q尽Java在网l编E这斚w已经做的??c)?了,但是|络~程在其他环境下的却是一件极为头痛的事情Q再"?c)?q是有一定的隑ֺQ,也是功能最为强大的一部分,读者应该好好研IӞ领?zhn)其中的思想?

  最后要的是要学好Java|络~程QJava语言Q最重要的还是在于多多练?fn)?


周游世界 2006-11-05 12:36 发表评论
]]>
JAVA教程 W八?Java|络~程(?http://www.tkk7.com/yanzhou/archive/2006/11/05/79180.html周游世界周游世界Sun, 05 Nov 2006 03:42:00 GMThttp://www.tkk7.com/yanzhou/archive/2006/11/05/79180.htmlhttp://www.tkk7.com/yanzhou/comments/79180.htmlhttp://www.tkk7.com/yanzhou/archive/2006/11/05/79180.html#Feedback0http://www.tkk7.com/yanzhou/comments/commentRss/79180.htmlhttp://www.tkk7.com/yanzhou/services/trackbacks/79180.html8.3 ZSocketQ套接字Q的低层ơJava|络~程

  8.3.1 Socket通讯

  |络上的两个E序通过一个双向的通讯q接实现数据的交换,q个双向链\的一端称Z个Socket。Socket通常用来实现客户方和服务方的q接。Socket是TCP/IP协议的一个十分流行的~程界面Q一个Socket׃个IP地址和一个端口号唯一定?

  在传l的UNIX环境下可以操作TCP/IP协议的接口不止Socket一个,Socket所支持的协议种cM不光TCP/IP一U,因此两者之间是没有必然联系的。在Java环境下,Socket~程主要是指ZTCP/IP协议的网l编E?

  说Socket~程是低层次|络~程q不{于它功能不强大Q恰恰相反,正因为层ơ低QSocket~程比基于URL的网l编E提供了更强大的功能和更灉|的控Ӟ但是却要更复杂一些。由于Java本n的特D性,Socket~程在Java中可能已l是层次最低的|络~程接口Q在Java中要直接操作协议中更低的层次Q需要用Java的本地方法调用(JNIQ,在这里就不予讨论了?

  8.3.2 Socket通讯的一般过

  前面已经提到Socket通常用来实现C/Sl构?

  使用Socketq行Client/ServerE序设计的一般连接过E是q样的:Server端Listen(监听)某个端口是否有连接请求, Client端向Server端发出Connect(q接)hQServer端向Client端发回AcceptQ接受)消息。一个连接就建立h了?Server端和Client端都可以通过SendQW(xu)rite{方法与Ҏ(gu)通信?

  对于一个功能齐全的SocketQ都要包含以下基本结构,其工作过E包含以下四个基本的步骤Q?
  Q?Q?创徏SocketQ?
  Q?Q?打开q接到Socket的输?出流Q?
  Q?Q?按照一定的协议对Socketq行?写操作;
  Q?Q?关闭Socket.

  W三步是E序员用来调用Socket和实现程序功能的关键步骤Q其他三步在各种E序中基本相同?

  以上4个步骤是针对TCP传输而言的,使用UDPq行传输时略有不同,在后面会有具体讲解?

  8.3.3 创徏Socket

  java在包java.net中提供了两个cSocket和ServerSocketQ分别用来表C双向连接的客户端和服务端。这是两个封装得非常好的c,使用很方ѝ其构造方法如下:
  Socket(InetAddress address, int port);
  Socket(InetAddress address, int port, boolean stream);
  Socket(String host, int prot);
  Socket(String host, int prot, boolean stream);
  Socket(SocketImpl impl)
  Socket(String host, int port, InetAddress localAddr, int localPort)
  Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
  ServerSocket(int port);
  ServerSocket(int port, int backlog);
  ServerSocket(int port, int backlog, InetAddress bindAddr)

  其中address、host和port分别是双向连接中另一方的IP地址、主机名和端口号Qstream指明socket是流socketq是数据?socketQlocalPort表示本地L的端口号QlocalAddr和bindAddr是本地机器的地址QServerSocket的主机地址Q,impl是socket的父c,既可以用来创建serverSocket又可以用来创建Socket。count则表C服务端所能支持的最大连接数。例如:
  Socket client = new Socket("127.0.01.", 80);
  ServerSocket server = new ServerSocket(80);

  注意Q在选择端口Ӟ必须心。每一个端口提供一U特定的服务Q只有给出正的端口Q才能获得相应的服务?~1023的端口号为系l所保留Q例?http服务的端口号?0,telnet服务的端口号?1,ftp服务的端口号?3, 所以我们在选择端口hQ最好选择一个大?023的数以防止发生冲H?

  在创建socket时如果发生错误,生IOExceptionQ在E序中必d之作出处理。所以在创徏Socket或ServerSocket是必Lh抛出例外?

  8.3.4 客户端的Socket

  下面是一个典型的创徏客户端Socket的过E?
   try{
     Socket socket=new Socket("127.0.0.1",4700);
     //127.0.0.1是TCP/IP协议中默认的本机地址
   }catch(IOException e){
     System.out.println("Error:"+e);
   }

  q是最单的在客L(fng)创徏一个Socket的一个小E序D,也是使用Socketq行|络通讯的第一步,E序相当单,在这里不作过多解释了。在后面的程序中会用到该程序段?


  8.3.5 服务?/font>端的ServerSocket

  下面是一个典型的创徏Server端ServerSocket的过E?
  ServerSocket server=null;
  try {
     server=new ServerSocket(4700);
     //创徏一个ServerSocket在端?700监听客户h
  }catch(IOException e){
     System.out.println("can not listen to :"+e);
  }
  Socket socket=null;
  try {
    socket=server.accept();
    //accept()是一个阻塞的Ҏ(gu)Q一旦有客户hQ它?yu)׃q回一个Socket对象用于同客戯行交?
  }catch(IOException e){
    System.out.println("Error:"+e);
  }

  以上的程序是Server的典型工作模式,只不q在q里Server只能接收一个请求,接受完后Server退Z。实际的应用中L让它不停的@环接Ӟ一旦有客户hQServerL会创Z个服务线E来服务新来的客P而自ql监听。程序中accept()是一个阻塞函敎ͼ所谓阻塞性方法就是说该方法被调用后,等待客L(fng)hQ直到有一个客户启动ƈhq接到相同的端口Q然后accept()q回一个对应于客户的socket。这Ӟ客户方和服务斚w建立了用于通信的socketQ接下来是由各个socket分别打开各自的输?输出?

  8.3.6 打开输入/出流

  cSocket提供了方法getInputStream ()和getOutStream()来得到对应的输入/输出以q行?写操作,q两个方法分别返回InputStream和OutputSteamcd象。ؓ了便于读/写数据,我们可以在返回的输入/输出对象上建立qo,如DataInputStream、DataOutputStream?PrintStreamcd象,对于文本方式对象,可以采用InputStreamReader和OutputStreamWriter?PrintWirter{处理?

  例如Q?
  PrintStream os=new PrintStream(new BufferedOutputStreem(socket.getOutputStream()));
  DataInputStream is=new DataInputStream(socket.getInputStream());
  PrintWriter out=new PrintWriter(socket.getOutStream(),true);
  BufferedReader in=new ButfferedReader(new InputSteramReader(Socket.getInputStream()));

  输入输出是|络~程的实质性部分,具体如何构造所需要的qo,要根据需要而定Q能否运用自如主要看读者对Java中输入输出部分掌握如何?

  8.3.7 关闭Socket

  每一个Socket存在Ӟ都将占用一定的资源Q在Socket对象使用完毕Ӟ要其关闭。关闭Socket可以调用Socket的CloseQ)Ҏ(gu)。在关闭Socket之前Q应与Socket相关的所有的输入/输出全部关闭,以释放所有的资源。而且要注意关闭的序Q与Socket相关的所有的输入/输出该首先关闭,然后再关闭Socket?
  os.close();
  is.close();
  socket.close();

  管Java有自动回收机Ӟ|络资源最l是会被释放的。但是ؓ了有效的利用资源Q徏议读者按照合理的序d释放资源?

  8.3.8 单的Client/ServerE序设计

  下面我们l出一个用Socket实现的客户和服务器交互的典型的C/Sl构的演C程序,读者通过仔细阅读该程序,会对前面所讨论的各个概忉|更深ȝ认识。程序的意义请参考注释?

  1. 客户端程?

  import java.io.*;
  import java.net.*;
  public class TalkClient {
    public static void main(String args[]) {
      try{
        Socket socket=new Socket("127.0.0.1",4700);
        //向本机的4700端口发出客户h
        BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
        //ql标准输入设备构造BufferedReader对象
        PrintWriter os=new PrintWriter(socket.getOutputStream());
        //由Socket对象得到输出,q构造PrintWriter对象
        BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //由Socket对象得到输入,q构造相应的BufferedReader对象
        String readline;
        readline=sin.readLine(); //从系l标准输入读入一字符?
        while(!readline.equals("bye")){
        //若从标准输入d的字W串?"bye"则停止@?
          os.println(readline);
          //从pȝ标准输入d的字W串输出到Server
          os.flush();
          //h输出,使Server马上收到该字W串
          System.out.println("Client:"+readline);
          //在系l标准输Z打印d的字W串
          System.out.println("Server:"+is.readLine());
          //从Serverd一字符Ԍq打印到标准输出?
          readline=sin.readLine(); //从系l标准输入读入一字符?
        } //l箋循环
        os.close(); //关闭Socket输出?
        is.close(); //关闭Socket输入?
        socket.close(); //关闭Socket
      }catch(Exception e) {
        System.out.println("Error"+e); //出错Q则打印出错信息
      }
  }
  } 2. 服务器端E序

  import java.io.*;
  import java.net.*;
  import java.applet.Applet;
  public class TalkServer{
    public static void main(String args[]) {
      try{
        ServerSocket server=null;
        try{
          server=new ServerSocket(4700);
        //创徏一个ServerSocket在端?700监听客户h
        }catch(Exception e) {
          System.out.println("can not listen to:"+e);
        //出错Q打印出错信?
        }

        Socket socket=null;
        try{
          socket=server.accept();
          //使用accept()d{待客户hQ有客户
          //h到来则生一个Socket对象Qƈl箋执行
        }catch(Exception e) {
          System.out.println("Error."+e);
          //出错Q打印出错信?
        }
        String line;
        BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
         //由Socket对象得到输入,q构造相应的BufferedReader对象
        PrintWriter os=newPrintWriter(socket.getOutputStream());
         //由Socket对象得到输出,q构造PrintWriter对象
        BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
         //ql标准输入设备构造BufferedReader对象

        System.out.println("Client:"+is.readLine());
        //在标准输Z打印从客L(fng)d的字W串
        line=sin.readLine();
        //从标准输入读入一字符?
        while(!line.equals("bye")){
        //如果该字W串?"bye"Q则停止循环
          os.println(line);
          //向客L(fng)输出该字W串
          os.flush();
          //h输出,使Client马上收到该字W串
          System.out.println("Server:"+line);
          //在系l标准输Z打印d的字W串
          System.out.println("Client:"+is.readLine());
          //从Clientd一字符Ԍq打印到标准输出?
          line=sin.readLine();
          //从系l标准输入读入一字符?
        }  //l箋循环
        os.close(); //关闭Socket输出?
        is.close(); //关闭Socket输入?
        socket.close(); //关闭Socket
        server.close(); //关闭ServerSocket
      }catch(Exception e){
        System.out.println("Error:"+e);
        //出错Q打印出错信?
      }
    }
  }

  从上面的两个E序中我们可以看刎ͼsocket四个步骤的用过E。读者可以分别将Socket使用的四个步骤的对应E序D选择出来Q这样便于读者对socket的用有q一步的了解?

  读者可以在单机上试验该E序Q最好是能在真正的网l环境下试验该程序,q样更容易分辨输出的内容和客hQ服务器的对应关pR同时也可以修改该程序,提供更ؓ强大的功能,或更加满者的意图?

  

  8.3.9 支持多客L(fng)client/serverE序设计

  前面提供的Client/ServerE序只能实现Server和一个客L(fng)对话。在实际应用中,往往是在服务器上q行一个永久的E序Q它可以接收来自其他多个客户端的hQ提供相应的服务。ؓ了实现在服务器方l多个客h供服务的功能Q需要对上面的程序进行改造,利用多线E实现多客户机制。服务器L在指定的端口上监听是否有客户hQ一旦监听到客户hQ服务器׃启动一个专门的服务U程来响应该客户的请求,而服务器本n在启动完U程之后马上又进入监听状态,{待下一个客L(fng)到来?

  客户端的E序和上面程序是完全一L(fng)Q读者如果仔l阅读过上面的程序,可以跌不读Q把主要_֊集中在Server端的E序上?

  2. 服务器端E序: MultiTalkServer.java

  import java.io.*;
  import java.net.*;
  import ServerThread;
  public class MultiTalkServer{
   static int clientnum=0; //静态成员变量,记录当前客户的个?
   public static void main(String args[]) throws IOException {
    ServerSocket serverSocket=null;
    boolean listening=true;
    try{
      serverSocket=new ServerSocket(4700);
      //创徏一个ServerSocket在端?700监听客户h
    }catch(IOException e) {
      System.out.println("Could not listen on port:4700.");
      //出错Q打印出错信?
      System.exit(-1); //退?
    }
    while(listening){ //永远循环监听
      new ServerThread(serverSocket.accept(),clientnum).start();
      //监听到客戯求,Ҏ(gu)得到的Socket对象?
       客户计数创徏服务U程Qƈ启动?
      clientnum++; //增加客户计数
    }
    serverSocket.close(); //关闭ServerSocket
  }
  }

  3. E序ServerThread.java

  import java.io.*;
  import java.net.*;
  public class ServerThread extends Thread{
   Socket socket=null; //保存与本U程相关的Socket对象
   int clientnum; //保存本进E的客户计数
   public ServerThread(Socket socket,int num) { //构造函?
    this.socket=socket; //初始化socket变量
    clientnum=num+1; //初始化clientnum变量
   }
   public void run() { //U程M
    try{
      String line;
      BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
  //由Socket对象得到输入,q构造相应的BufferedReader对象
      PrintWriter os=newPrintWriter(socket.getOutputStream());
      //由Socket对象得到输出,q构造PrintWriter对象
      BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
      //ql标准输入设备构造BufferedReader对象
      System.out.println("Client:"+ clientnum +is.readLine());
      //在标准输Z打印从客L(fng)d的字W串
      line=sin.readLine();
      //从标准输入读入一字符?
      while(!line.equals("bye")){
      //如果该字W串?"bye"Q则停止循环
        os.println(line);
        //向客L(fng)输出该字W串
        os.flush();
        //h输出,使Client马上收到该字W串
        System.out.println("Server:"+line);
        //在系l标准输Z打印该字W串
        System.out.println("Client:"+ clientnum +is.readLine());
        //从Clientd一字符Ԍq打印到标准输出?
        line=sin.readLine();
        //从系l标准输入读入一字符?
      } //l箋循环
      os.close(); //关闭Socket输出?
      is.close(); //关闭Socket输入?
      socket.close(); //关闭Socket
      server.close(); //关闭ServerSocket
     }catch(Exception e){
      System.out.println("Error:"+e);
      //出错Q打印出错信?
     }
   }
  }

  通过以上的学?fn),读者应该对Java的面向流的网l编E有了一个比较全面的认识Q这些都是基于TCP的应用,后面我们介l基于UDP的Socket~程

周游世界 2006-11-05 11:42 发表评论
]]>
PPP介绍http://www.tkk7.com/yanzhou/archive/2006/10/12/PPP?????.html周游世界周游世界Thu, 12 Oct 2006 06:16:00 GMThttp://www.tkk7.com/yanzhou/archive/2006/10/12/PPP?????.htmlhttp://www.tkk7.com/yanzhou/comments/74780.htmlhttp://www.tkk7.com/yanzhou/archive/2006/10/12/PPP?????.html#Feedback0http://www.tkk7.com/yanzhou/comments/commentRss/74780.htmlhttp://www.tkk7.com/yanzhou/services/trackbacks/74780.html一、介l?/b>

PPPQPoint-to-Point Protocol点到点协议)是ؓ在同{单元之间传输数据包q样的简单链路设计的链\层协议。这U链路提供全双工操作Qƈ按照序传递数据包。设计目的主 要是用来通过拨号或专U方式徏立点对点q接发送数据,使其成ؓ各种L、网桥和路由器之间简单连接的一U共通的解决Ҏ(gu)?

二、PPP链\建立q程

PPP协议中提供了一整套Ҏ(gu)来解决链路徏立、维护、拆除、上层协议协商、认证等问题。PPP协议包含q样几个部分Q?br />
    链\控制协议LCPQLink Control ProtocolQ?br />     |络控制协议NCPQNetwork Control ProtocolQ?br />     认证协议
   
LCP负责创徏Q维护或l止一ơ物理连接。NCP是一族协议,负责解决物理q接上运行什么网l协议,以及解决上层|络协议发生的问题? 最常用的认证协议包括口令验证协议PAPQPassword Authentication ProtocolQ和挑战握手验证协议CHAPQChallenge-Handshake Authentication ProtocolQ?br />
下面介绍PPP链\建立的过E:

PPP链\状态机如图1所C?

一个典型的链\建立q程分ؓ三个阶段Q创建阶Dc认证阶D和|络协商阶段?br />

阶段1Q创建PPP链\

LCP负责创徏链\。在q个阶段Q将对基本的通讯方式q行选择。链路两端设备通过LCP向对方发送配|信息报文(Configure PacketsQ。一旦一个配|成功信息包QConfigure-Ack packetQ被发送且被接Ӟ完成了交换Q进入了LCP开启状态?

应当注意Q在链\创徏阶段Q只是对验证协议q行选择Q用户验证将在第2阶段实现?

阶段2Q用户验?

在这个阶D,客户端会自qw䆾发送给q端的接入服务器。该阶段使用一U安全验证方式避免第三方H取数据或冒充远E客h与客户端的q接。在认证完成之前Q禁止从认证阶段前进到网l层协议阶段。如果认证失败,认证者应该跃q到链\l止阶段?

在这一阶段里,只有链\控制协议、认证协议,和链路质量监视协议的packets是被允许的。在该阶D里接收到的其他的packets必须被静静的丢弃?

最常用的认证协议有口o验证协议QPAPQ和挑战握手验证协议QCHAPQ?认证方式介绍在第三部分中介绍?

阶段3
Q调用网l层协议

认证阶段完成之后QPPP调用在链\创徏阶段Q阶D?Q选定的各U网l控制协议(NCPQ。选定的NCP解决PPP链\之上的高层协议问题,例如Q在该阶DIP控制协议QIPCPQ可以向拨入用户分配动态地址?

q样Q经q三个阶D以后,一条完整的PPP链\徏立v来了?

三?认证方式

1Q口令验证协议(PAPQ?

PAP是一U简单的明文验证方式。NASQ网l接入服务器QNetwork Access ServerQ要求用h供用户名和口令,PAP以明文方式返回用户信息。很明显Q这U验证方式的安全性较差,W三方可以很Ҏ(gu)的获取被传送的用户名和? 令,q利用这些信息与NAS建立q接获取NAS提供的所有资源。所以,一旦用户密码被W三方窃取,PAP无法提供避免受到W三Ҏ(gu)ȝ保障措施?

2Q挑?握手验证协议QCHAPQ?

CHAP是一U加密的验证方式Q能够避免徏立连接时传送用L(fng)真实密码。NAS向远E用户发送一个挑战口令(challengeQ,其中包括会话ID和一 个Q意生成的挑战字串Qarbitrary challengestringQ。远E客户必M用MD5单向哈希法Qone-way hashing algorithmQ返回用户名和加密的挑战口oQ会话ID以及用户口oQ其中用户名以非哈希方式发送?

CHAP对PAPq行了改q,不再直接通过链\发送明文口令,而是使用挑战口o以哈希算法对口oq行加密。因为服务器端存有客L(fng)明文口oQ所以服务器? 以重复客L(fng)q行的操作,q将l果与用戯回的口oq行对照。CHAP为每一ơ验证Q意生成一个挑战字串来防止受到再现dQreplay attackQ。在整个q接q程中,CHAP不定时的向客户端重复发送挑战口令,从而避免第3方冒充远E客Premote client impersonationQ进行攻凅R?

四、PPP协议的应?

PPP协议是目前广域网上应用最q泛的协议之一Q它的优点在于简单、具备用户验证能力、可以解决IP分配{?

家庭拨号上网是通过PPP在用L(fng)和运营商的接入服务器之间建立通信链\? 目前Q宽带接入正在成为取代拨号上|的势Q在宽带接入技术日新月异的今天QPPP也衍生出新的应用。典型的应用是在ADSLQ非对称数据用户环线Q? Asymmetrical Digital Subscriber LoopQ接入方式当中,PPP与其他的协议共同zZW合宽带接入要求的新的协议,如PPPoEQPPP over EthernetQ,PPPoAQPPP over ATMQ?

利用以太|(EthernetQ资源,在以太网上运行PPP来进行用戯证接入的方式UCؓPPPoE。PPPoE即保护了用户方的以太|资源,又完成了ADSL的接入要求,是目前ADSL接入方式中应用最q泛的技术标准?

同样Q在ATMQ异步传输模式,Asynchronous Transfer ModeQ网l上q行PPP协议来管理用戯证的方式UCؓPPPoA。它与PPPoE的原理相同,作用相同Q不同的是它是在ATM|络上,而PPPoE? 在以太网|络上运行,所以要分别适应ATM标准和以太网标准?

PPP协议的简单完整它得Cq泛的应用,怿在未来的|络技术发展中Q它q可以发挥更大的作用?img src ="http://www.tkk7.com/yanzhou/aggbug/74780.html" width = "1" height = "1" />

周游世界 2006-10-12 14:16 发表评论
]]>
[ZZ] JavaEE5的新特征http://www.tkk7.com/yanzhou/archive/2006/10/08/73716.html周游世界周游世界Sun, 08 Oct 2006 02:18:00 GMThttp://www.tkk7.com/yanzhou/archive/2006/10/08/73716.htmlhttp://www.tkk7.com/yanzhou/comments/73716.htmlhttp://www.tkk7.com/yanzhou/archive/2006/10/08/73716.html#Feedback0http://www.tkk7.com/yanzhou/comments/commentRss/73716.htmlhttp://www.tkk7.com/yanzhou/services/trackbacks/73716.html  JavaEE5规范

  2006q??8?JavaEE? 范专家组全票通过JavaEE5规范?月,最新的JavaEE的规范可以从q里下蝲到。在J2EE1.4发布1q半之后,Java企业开发技术的业界? 准终于又向前跨了一大步。我说的q一大步不仅仅是名字从J2EE到JavaEE的变化,? 不是单把版本?.4升?。应该说QJavaEE5的发布把Java技术在企业开发的业界标准又推向一个新的高度,对一些重要的规范都本质的改动?/p>

   JavaEE5规范最主要的目的就是简化开?提高开发的效率.同时,随着JavaEE规范变得逐渐庞大QJavaEE5对已有的子规范进行了pȝ的分 c?分别包括:企业应用、Web应用、Web服务和管理四个方面,如此分类让开发h员更加清晎ͼ更容易选择相关规范q行学习(fn).

  JavaEE5主要的新特征包括:

  ?EJB规范

   EJB规范在保证向后兼Ҏ(gu)的同时,做了较大的改?EJB规范的版本从2.1升?.0,在版本升U的背后包含了如下的显著特征:EJB成ؓ轻量U? ?POJO,可以q容器q行和测?EJB3.0中引入的持久化规范可以脱JavaEEq行环境,单独q行在标准的Java应用E序? q也是对Java持久化规范的一个重大A(ch)?我的同事Wynne Wang写了一关于EJB3.0的BlogQ里面详l介l了其新Ҏ(gu)?/p>

  ?Web层规?/p>

   引入了Java Server Faces(JSF) 1.2和Java Server Pages Standard Tag Library 1.2.在传l的JSP和Servlet的基之上Q这两个规范的引入也大大简化Web层或者说是展现层的开发,其中包括通用的组件、流E控制等?/p>

  ?标注(Annotation)的?/p>

   标注(Annotation)是JavaSE5在Java语言上的一个重大变化,JavaEE5大量使用了标注。标注的使用可以化JavaEE应用E? ?的发布过E,使得开发h员可以从代码和发布文件的同步中解脱出?同时Q标注也可以大大化应用程序中资源(例如:JDBC ConnectionQEJBq程接口)的查找过E,使得开发h员不用过多考虑pȝ环境的问题,专注于业务的开发?/p>

  值得一提的是,不可 否认QJava企业开发技术的业界标准也吸收了很多大家耳熟能详的框架的设计思想(包括Hibernate, Spring, Toplink和JDO{等)Q例如,Hibernate的创始hGavin King是EJB3.0规范的专家成员之一。我想从q一点也可以看出JavaEE的业界标准是一个开攄标准?/p>

  Glassfish---Sun开源JavaEE应用服务?/strong>

  Sun公司不仅仅是开发规范制定的领导者,同时也在规范的实现和推广上也做了很大的努力和贡献。从JavaEE参考实现到产品U别的应用服务器(Sun Java System Application Server)QSun都一套完整的产品Uѝ?/p>

  2005q??JavaOne大会上Sun开始了GlassFish目。GlassFish目使用CDDL规范.开发者可以查看、用、修改和发布Glassfish的代码?/p>

   Sun公司把其商用应用服务器的代码贡献到GlassFish目?Oracle也A(ch)献了Toplink的代码实现EJB的持久化功能。在正在开发中 Glassfish V2版本中,q将包括集群{特性? 虽然知道Glassfish的开发h员不是很多,但是我想Q就象Sun的另一个开源品NetBeansJavaIDE工具一P在不久的来一定会有越 来越多的Z用Glassfish!

  如果(zhn)还在犹豫,可以看看q篇Blog:Why to use Glassfish? 怿你看后一定会跃跃Ʋ试?/p>

  让我们跟上时代的步伐Q不要成为JavaEE5的淘汰?



周游世界 2006-10-08 10:18 发表评论
]]>
[ZZ] JSF详解(从jsf的运行原理开始介l了jsf)http://www.tkk7.com/yanzhou/archive/2006/09/30/73012.html周游世界周游世界Sat, 30 Sep 2006 05:23:00 GMThttp://www.tkk7.com/yanzhou/archive/2006/09/30/73012.htmlhttp://www.tkk7.com/yanzhou/comments/73012.htmlhttp://www.tkk7.com/yanzhou/archive/2006/09/30/73012.html#Feedback4http://www.tkk7.com/yanzhou/comments/commentRss/73012.htmlhttp://www.tkk7.com/yanzhou/services/trackbacks/73012.html JSF详解(从jsf的运行原理开始介l了jsf)

1Q?  l构Q?
a)     l构图:

   
b)     说明QJSF以MVC模式为基Q与Struts不同QJSF的目标是希望以一个与Swing相类似的方式来开发网,因此Q从JSF的结构图当中Q他的核心概念不是页面,而是控g?wi),也就是说Q当用户提交一个请求时QJSF会先页面上的组件先转换ZSwing当中cM的,由容器和控gl成的控件树(wi)Q然后数据和事g被设|到对应的控件上Q然后以一U与SwingcM的方式,来处理后l的h。控件树(wi)是整个JSF的核心,所有其他的一切一切都是围l着q棵控g?wi)展开的?
2Q?  生命周期Q?
a)     周期图:

 
  b)     说明Q?
  b)     说明Q?
  b)     说明Q?
              i.         Restore ViewQJSF的处理核心是控g?wi),他会先将面上所声明的控件{换ؓ一|件树(wi)Q后l的操作在q颗控g?wi)上q行。ؓ了提高性能Q系l会Z前生成的控g?wi)提供缓存。Restore View的工作就是在~存当中查找是否存在之前已经生成好的控g?wi),如果没有Q则Ҏ(gu)面的内容,重新生成?
            ii.         Apply Request ValuesQ把h当中的数据设|到控g?wi)当中对应的控g当中厅R?
          iii.         Process ValidationsQ如果某一控g有配|ValidatorQ则q些Validator对刚设|的数据的正性和合法性进行验证?
            iv.         Update Model ValuesQ控件树(wi)上的控g更新其底层所对应的模型?
              v.         Invoke ApplicationQ对产生的事件进行分发?
            vi.         Render ResponseQ构Z为响应的控g?wi)?
3Q?  UIQ?
a)     l构图:



b)     控gQ?
              i.         说明QJSF通过标签库,提供了一些主要控件的实现。包括标{,文本框,单选框Q列表等。由于JSF使用一U类gUI的方式来l织lgQ所以,除了基本的组件以外,q提供了一些用于布局的容器,例如面板{。在q里有一个要注意的地方就是,一般情况下Q页面的内容应该攑ֈJSF提供的view标签里面?
            ii.         代码Q?
<%@page contentType="text/html;charset=gb2312"%>
<%@ taglib uri="
http://java.sun.com/jsf/core " prefix="f"%>
<%@ taglib uri="
http://java.sun.com/jsf/html " prefix="h"%>
<html>
<head><title>Test</title></head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="1">
<h:outputLabel>
<h:outputText value="User ID"/>
</h:outputLabel>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
c)     事g处理Q?
              i.         说明Q与Struts不同Q由于JSF使用以控件树(wi)Z心的方式来处理请求,所以,Ҏ(gu)供了一U额外的cMSwing的,事g处理的方式来处理用户的输入事件。JSF提供了两U事件类型,ActionEventQ用于处理命令和ValueChangeEventQ用于处理数据更攏V?
            ii.         代码Q?
模型代码Q?
package nick;
public class UserActionListener implements ActionListener {
  public void processAction(ActionEvent arg0)
throws AbortProcessingException {
    FacesContext context = FacesContext.getCurrentInstance();
    ValueBinding binding = Util.getValueBinding("#{user}");
    User user = (User) binding.getValue(context);
    String id = user.getId();
  }
}
面代码Q?
<%@page contentType="text/html;charset=gb2312" import="java.util.*"%>
<%@ taglib uri="
http://java.sun.com/jsf/core " prefix="f"%>
<%@ taglib uri="
http://java.sun.com/jsf/html " prefix="h"%>
<html>
<head><title>Test</title></head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="2">
<h:outputLabel for="id">
<h:outputText value="User ID"/>
</h:outputLabel>
<h:commandButton id="regist" value="注册">
<f:actionListener type="nick.UserActionListener"/>
</h:commandButton>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
注:通过嵌套actionListener标签Q我们可以ؓ一个控件注册监视器?

4Q?  数据l定Q?
a)     说明Q数据绑定要解决的问题就是如何把模型中的|l定到页面的控g上。在JSF当中q可以通过JSF所提供的配|文件来完成?
b)     代码Q?
配置文gQ?
<faces-config>
<managed-bean>
<managed-bean-name> user </managed-bean-name>
<managed-bean-class> nick.User </managed-bean-class>
<managed-bean-scope> session </managed-bean-scope>
</managed-bean>
</faces-config>
模型代码Q?
package nick;
public class User {
  private String id = "Nick";
public void setId(String id) {
    this.id = id;
  }
  public String getId() {
    return this.id;
  }
}
面代码Q?
<%@page contentType="text/html;charset=gb2312"%>
<%@ taglib uri="
http://java.sun.com/jsf/core " prefix="f"%>
<%@ taglib uri="
http://java.sun.com/jsf/html " prefix="h"%>
<html>
  <head><title>Test</title></head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="2">
<h:outputLabel for="id">
<h:outputText value="User ID"/>
</h:outputLabel>
<h:inputText id="id" value="#{user.id}"/>
          </h:panelGrid>
        </h:form>
    </f:view>
  </body>  
</html>
注:通过配置文gQ我们把nick.Usercȝ定到名称user上,然后面的代码就可以直接使用#{user.xxx}来引用Userq个cM的各个字Dc?
5Q?  面:
a)     面到控制器Q?
              i.         说明QJSF通过使用Ҏ(gu)l定的方式来定义从页面到控制器的跌{Q和数据l定相同Qؓ了能够正找到被l定Ҏ(gu)所在的c,我们需要首先在配置文g当中声明managed-beanQ然后通过讄控g的action属性,定义面到控制器的蟩转逻辑?
            ii.         代码Q?
配置文gQ?
<faces-config>
<managed-bean>
<managed-bean-name> user </managed-bean-name>
<managed-bean-class> nick.User </managed-bean-class>
<managed-bean-scope> session </managed-bean-scope>
</managed-bean>
</faces-config>



模型代码Q?
package nick;
public class User {
  public String regist() {
    return "regist";
  }
  public String login() {
    return "login";
  }
}
面代码Q?
<%@page contentType="text/html;charset=gb2312"%>
<%@ taglib uri="
http://java.sun.com/jsf/core " prefix="f"%>
<%@ taglib uri="
http://java.sun.com/jsf/html " prefix="h"%>
<html>
<head><title>Test</title></head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="2">
<h:commandButton id="regist"
action="#{user.regist}" value="注册"/>
<h:commandButton id="login"
action="#{user.login}" value="登陆"/>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
注:上述的页面代码,把注册按钮的动作l定到Usercȝregist()Ҏ(gu)Q把登陆按钮的动作绑定到Usercȝlogin()Ҏ(gu)。因此,当这两个按钮被点?yn)LQ对应的Ҏ(gu)被调用Q用于实现页面流的方法,必须声明为publicQ而且她不接受参数Q且q回值必MؓString?
b)     控制器到面Q?
              i.         说明QJSF通过名称l定的方式,来定义从控制器到面的蟩转。ؓ了实C控制器到面的蟩转,我们需要在配置文g当中定义一?lt;navigation-rule>Q这些rule主要定义了怎么Ҏ(gu)上述action标签所l定的方法的q回值来查找下一面?
            ii.         代码Q?
配置文gQ?
<faces-config>
<managed-bean>
<managed-bean-name> user </managed-bean-name>
<managed-bean-class> nick.User </managed-bean-class>
<managed-bean-scope> session </managed-bean-scope>
</managed-bean>



<navigation-rule>
<from-view-id>/index.jsp</from-view-id>
<navigation-case>
<from-outcome>regist</from-outcome>
<to-view-id>/regist.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/login.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
模型代码Q?
package nick;
public class User {
  public String regist() {
    return "regist";
  }
  public String login() {
    return "login";
  }
}
注:上述的配|文件定义了一?lt;navigation-rule>Q该rule指明了如果?index.jsp”页面通过她内部的某个控g的action属性发生了跌{Q那么当该蟩转方法的q回gؓ字符东yregist”时Q则面蟩转到对应的?regist.jsp”中Q同理,如果q回gؓ“login”,则页面将跌{到?login.jsp”?
6Q?  数据传输Q?
a)     面到控制器Q?
              i.         说明Q在JSF的页面代码当中,通过数据l定Q我们把控g的value|与某个后台的数据bean兌h。而在前述的生命周期部分,我们看到Q当一个JSFh到达Ӟ他需要经历Restore ViewQApply Request Value{步骤,而Apply Request Value部分的工作,是把请求当中的值绑定到q个后台的bean之中Q因此,我们不需要考虑面中的Form值如何传入到后台的bean当中?
q一步,如果录入控g的value属性,和命令控件的action属性都是绑定在同一个bean上的话,那么在页面蟩转时Q我们可以直接访问到bean的属性倹{但是ؓ了不污染模型Q和实现控制与模型的分离Q一般情况下Q我们需要把输入控g的value值绑定到数据beanQ而把命o控g的action值绑定到控制beanQ由于两个bean不是同一个,所以,控制bean需要一U方法来获取数据bean中的属性倹{?
            ii.         代码Q?
配置文gQ?
<faces-config>
<managed-bean>
<managed-bean-name> user </managed-bean-name>
<managed-bean-class> nick.User </managed-bean-class>
<managed-bean-scope> session </managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name> action </managed-bean-name>
<managed-bean-class> nick.Action </managed-bean-class>
<managed-bean-scope> session </managed-bean-scope>
</managed-bean>
</faces-config>
模型代码Q?
        package nick;
public class User {
private String id = "Nick";
public void setId(String id) {
this.id = id;
}
public String getId() {
return this.id;
}
}
package nick;
public class Action {
  public String regist() {
    ValueBinding binding = Util.getValueBinding("#{user}");
    User user = (User)
binding.getValue(FacesContext.getCurrentInstance());
            ?
    return "regist";
  }
}
面代码Q?
<%@page contentType="text/html;charset=gb2312"%>
<%@ taglib uri="
http://java.sun.com/jsf/core " prefix="f"%>
<%@ taglib uri="
http://java.sun.com/jsf/html " prefix="h"%>
<html>
<head><title>Test</title></head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="2">
<h:outputLabel for="id">
<h:outputText value="User ID"/>
</h:outputLabel>
<h:inputText id="id" value="#{user.id}"/>
<h:commandButton id="regist"
action="#{action.regist}" value="注册"/>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>



注:面代码当中把输入控件的valuel定Cuser的id上,把命令控件的action值绑
定到action的regist上。当用户点击登陆按钮Ӟaction的regist()Ҏ(gu)会被调用,
而在该方法内部,Z获取之前面中的信息Q我们可以用ValueBindingcR该cM?
的数据绑定表辑ּ与页面中的类伹{?
b)     控制器到面Q?
              i.         说明Q通过之前的叙qͼ我们可以发现Q当我们需要把数据从控制器传到面Ӟ我们同样可以使用数据l定的方式,因ؓQ当我们通过数据l定表达式,获取到某个页面当中所使用的模型实例时Q便可以在该实例上直接调用对应的set()Ҏ(gu)Q来讑֮所希望的倹{?
7Q?  插g功能Q?
a)     ConverterQ{换)Q?
              i.         说明Q当模型中的某个字段需要在面上显C时Q她需要先被{换ؓ字符串类型;而用户在面输入的字W串|在传到模型中时也需要根据模型对应字D늚cdQ进行一个{换。另外,׃国际化的要去Q模型中的值在不同的地Z有不同的表示方式。ؓ了解决以上这些问题,JSF提供了Converter的实玎ͼ她主要做的事情就是根据所在的地区Q对面数据和模型数据进行双向的转换?
            ii.         代码Q?
模型代码Q?
package nick;
public class User {
  private Date date = new Date();
  public Date getDate() {
    return date;
  }
  public void setDate(Date date) {
    this.date = date;
  }
}
面代码Q?
<%@page contentType="text/html;charset=gb2312"%>
<%@ taglib uri="
http://java.sun.com/jsf/core " prefix="f"%>
<%@ taglib uri="
http://java.sun.com/jsf/html " prefix="h"%>
<html>
<head><title>Test</title></head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="date">
<h:outputText value="date"/>
</h:outputLabel>
<h:inputText id="date" value="#{user.date}">
<f:convertDateTime pattern="M/d/yyyy"/>
</h:inputText>
<h:message for="date"/>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
注:通过嵌套的convertXXX标签Q我们可以ؓ控g配置用于转换的{换器。我们可以用两U方式来注册转换器,一是通过控g的convert属性,另外一U就是通过嵌套的convertXXX标签。如果在转换的时候发生错误,那么JSF蟩q{换以后的步骤Q而直接蟩到Render Response步骤Q生成响应,q在FacesContext里添加一个出错的MessageQ该Message的内容可以通过message标签q行昄?br />b)     ValidateQ验证)Q?
              i.         说明Q在数据被交付后台处理以前,我们可以通过验证器,来验证输入的数据是否合法Q这包括数值的大小Q或者是字符串的长度{。用验证器的好处就是我们可以把验证的代码从控制代码中单独出来,以便理和重用?
            ii.         代码Q?
面代码Q?
<%@page contentType="text/html;charset=gb2312"%>
<%@ taglib uri="
http://java.sun.com/jsf/core " prefix="f"%>
<%@ taglib uri="
http://java.sun.com/jsf/html " prefix="h"%>
<html>
<head><title>Test</title></head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="id">
<h:outputText value="User ID"/>
</h:outputLabel>
<h:inputText id="id" value="#{user.id}">
<f:validateLength minimum="3" maximum="6"/>
</h:inputText>
<h:message for="id"/>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
注:通过嵌套的validateXXX标签我们可以Z个控件注册一个验证器Q与转换器不同,我们可以Z个控件注册多个验证器Q以q行复杂的验证。注册验证器的方法也有两个,一是通过控g的validator属性,另外一U就是通过嵌套的validateXXX标签。与转换器类|当验证失败时Q失败的原因也会以Message的Ş式被攑ֈFacesContext内,在页面内通过message标签可以寚w误信息进行显C?
8Q?  国际化支?
a)     说明Qؓ了提供对国际化的支持QJSF使用了与StrutscM的通过资源文g的Ş式,从外部获取需要显C的内容?
b)     代码Q?
配置文gQ?
<faces-config>
<application>
<message-bundle>nick.Messages</message-bundle>
<locale-config>
<default-locale>cn</default-locale>
<supported-locale>en</supported-locale>
</locale-config>
  </application>
</faces-config>
面代码Q?
<%@page contentType="text/html;charset=gb2312"%>
<%@ taglib uri="
http://java.sun.com/jsf/core " prefix="f"%>
<%@ taglib uri="
http://java.sun.com/jsf/html " prefix="h"%>
<html>
<head><title>Test</title></head>
<f:loadBundle basename="nick.Messages" var="message"/>
<body>
<f:view>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="id">
<h:outputText value="#{message.id}"/>
</h:outputLabel>
<h:inputText id="id" value="#{user.id}"/>
                </h:panelGrid>
</h:form>
</f:view>
</body>
</html>
注:如果我们需要考虑国际化的问题Ӟ那么我们需要ؓ同一个资源提供多个地区的资源文g实现。通过在配|文件中声明message-bundleQ我们可以注册资源文件的多个版本Q以上面ZQ她注册了两个资源文件nick.Messages_cn.properties和nickcen.Messages_en.properties分别对应于中国和英国地区Q当面当中通过loadBundle标签d资源Ӟ她就会根据所在的区域Q去查找对应的文件。当Ӟ所有资源文仉应该使用java所提供的native2ascii工具Q进行一下预处理?
9Q?  JSF定制Q?
a)     说明Q该部分主要展示如何对JSF提供的{换器Q验证器和控件进行定Ӟ以扩展JSF的功能?
b)     配置文g定制Q?
              i.         说明QJSF提供了比Struts更多的定制特性,包括用于实例化前端控制FacesServelt的faces-context-factoryQ用于实例化控gl画RenderKit的render-kit-factoryQ进行声明周期管理的lifecyle-factory{?
            ii.         代码Q?
配置文gQ?
<faces-config>
  <factory>
    <application-factory>?lt;/application-factory>
    <faces-context-factory>?lt;/faces-context-factory>
    <lifecycle-factory>?lt;/lifecycle-factory>
    <render-kit-factory>?lt;/render-kit-factory>
  </factory>
</faces-config>
c)     转换器定Ӟ
              i.         说明Q通过扩展JSF提供的Converter接口Q我们可以定义自q转换器。而ؓ了能在页面上使用自定义的转换器,我们需要在配置文g中,对{换器q行注册?
            ii.         代码Q?
配置文gQ?
<faces-config>
<converter>
<converter-id>nameConverter</converter-id>
<converter-class>nick.NameConverter</converter-class>
</converter>
</faces-config>
模型文gQ?
package nick;
public class NameConverter implements Converter {
public Object getAsObject(FacesContext ar0, UIComponent ar1, String ar2) {
    return ar2.toLowerCase();
}
public String getAsString(FacesContext ar0, UIComponent ar1, Object ar2) {
    retrun ((String) arg2).toUpperCase();
}
}
面文gQ?
<%@page contentType="text/html;charset=gb2312"%>
<%@ taglib uri="
http://java.sun.com/jsf/core " prefix="f"%>
<%@ taglib uri="
http://java.sun.com/jsf/html " prefix="h"%>
<html>
<head><title>Test</title></head>
<f:loadBundle basename="nick.Messages" var="message"/>
<body>
<f:view>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="id">
<h:outputText value="#{message.id}"/>
</h:outputLabel>
<h:inputText id="id"
value="#{user.id}" immediate="true">
<f:converter converterId="nameConverter"/>
</h:inputText>
<h:message for="id"/>
<h:commandButton
action="#{action.regist}" value="Regist"/>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
注:当页面数据{换ؓ后台数据ӞConverter的getAsObject()Ҏ(gu)会被调用。而当需要把后台数据昄到页面中ӞgetAsString()Ҏ(gu)会被调用。这里,我们注意刎ͼ我们的Converter是不能带M配置属性的Qؓ了让我们的Converter能够在页面中增加属性,我们需要进一步的定义自己的标{。除了可以根据converter-id来注册{换器以外Q我们还可以使用converter-for-class标签来ؓ某一特定的Javacd注册转换器。如果在转换q程中发生错误的话,那么我们可以通过抛出ConverterException来停止后l的工作?
d)     验证器定Ӟ
              i.         说明Q通过扩展Validator接口Q我们可以定义自q验证器。而ؓ了能在页面上使用自定义的验证器,我们需要在配置文g中,寚w证器q行注册?
            ii.         代码Q?
配置文gQ?
<faces-config>
<validator>
<validator-id>nameValidator</validator-id>
<validator-class>nick.NameValidator</validator-class>
</validator>
</faces-config>
模型文gQ?
package nick;
public class NameValidator implements Validator {
  public void validate(FacesContext arg0, UIComponent arg1, Object arg2)
        throws ValidatorException {
    String name = (String) arg2;
    if (!name.startsWith("nick")) {
        throw new ValidatorException(new FacesMessage(
            "name must start with nick"));
    }
  }
}



面文gQ?
<%@page contentType="text/html;charset=gb2312"%>
<%@ taglib uri="
http://java.sun.com/jsf/core " prefix="f"%>
<%@ taglib uri="
http://java.sun.com/jsf/html " prefix="h"%>
<html>
<head><title>Test</title></head>
<f:loadBundle basename="nick.Messages" var="message"/>
<body>
<f:view>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="id">
<h:outputText value="#{message.id}"/>
</h:outputLabel>
<h:inputText id="id" value="#{user.id}">             <f:validator validatorId="nameValidator"/>
</h:inputText>
<h:message for="id"/>
<h:commandButton
action="#{action.regist}" value="Regist"/>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
注:定制验证器的操作与定制{换器的操作大致相同,如果我们希望通过面的方式ؓ验证器提供属性的话,那么我们也需要定义额外的标签?
e)     控g定制Q?
              i.         说明QJSF允许用户ZJSF的框Ӟq行控g的定Ӟ控g定制需要完成以下几部分的工作,1.需要一个控件实现类Qؓ了能让控件在面上用,我们的控件还需要在配置文g中,通过component标签q行注册Q?.用于控g渲染的Renderc;3.用于在页面上使用控g的标{?
f)     控g?wi)定Ӟ?
              i.         说明Q除了可以通过面标签来声明控件以外,我们可以通过E序的方式来定制控g?wi),通过调用FacesContext上的getViewRoot()Ҏ(gu)Q我们可以获得控件树(wi)的根引用Q通过该引用,我们可以动态的Ҏ(gu)件进行增删,或者动态的为某一控g增删事g监听器,和验证器{?
g)     Web帔RQ?
              i.         说明QJSF提供了一l操作applicationQcontextQsessionQcookiesQpage{常量的Ҏ(gu)。通过调用FacesContext上的getExternalContext()Ҏ(gu)Q我们可以获得一个对ExternalContext的引用,通过该引用我们可以获取所有我们希望用的sessionQcookies{常量的引用Q除此以外,我们q能获取request当中的头信息和请求信息等?/font>


周游世界 2006-09-30 13:23 发表评论
]]>[ZZ] 解决web开发中的中文问?/title><link>http://www.tkk7.com/yanzhou/archive/2006/09/19/70535.html</link><dc:creator>周游世界</dc:creator><author>周游世界</author><pubDate>Tue, 19 Sep 2006 07:09:00 GMT</pubDate><guid>http://www.tkk7.com/yanzhou/archive/2006/09/19/70535.html</guid><wfw:comment>http://www.tkk7.com/yanzhou/comments/70535.html</wfw:comment><comments>http://www.tkk7.com/yanzhou/archive/2006/09/19/70535.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yanzhou/comments/commentRss/70535.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yanzhou/services/trackbacks/70535.html</trackback:ping><description><![CDATA[  q段旉l常看到有h问到web开发中怎么中文L?受原因其实很单,因ؓ大家大多用的是tomcat服务器,而tomcat服务器的默认~码?iso-8859-1(西欧字符)。就是因为iso-8859-1(西欧字符)~码造成了我们经常看刎ͼ受关于iso-8859-1(西欧字符)更多知识L(fng)<a name="main">《字节,字符和编?/a><a >?/a>q篇文章?br /><br />Ҏ(gu)一Q最单也是用的最多的Ҏ(gu)?br /><%@ page language="java" pageEncoding="GBK" %><br />或?lt;%@ page contenttype="text/html;charset=gbk";>q里可以用gb2312或者gbkQ只是gbk比gb2312支持跟多的字W?br /><br />q个Ҏ(gu)用于jsp面中的中文昄?br /><br />Ҏ(gu)二:使用qo器?br />qo器用主要针对表单提交,插入数据库的数据都是Q号。这也是应ؓtomcat不按request所指定的编码进行编码,q是自作d的采用默认编码方式iso-8859-1~码?br />~写一个SetCharacterEncodingFiltercR?br />import java.io.IOException;<br /><br />import javax.servlet.Filter;<br />import javax.servlet.FilterChain;<br />import javax.servlet.FilterConfig;<br />import javax.servlet.ServletException;<br />import javax.servlet.ServletRequest;<br />import javax.servlet.ServletResponse;<br /><br />public class SetCharacterEncodingFilter implements Filter {<br />protected String encoding = null;<br />protected FilterConfig filterConfig = null;<br />protected boolean ignore = true;<br /><br />public void init(FilterConfig filterConfig) throws ServletException {<br />this.filterConfig=filterConfig;<br />this.encoding=filterConfig.getInitParameter("encoding");<br />String value=filterConfig.getInitParameter("ignore");<br />if(value==null)<br />this.ignore=true;<br />else if(value.equalsIgnoreCase("true"))<br />this.ignore=true;<br />else<br />this.ignore=false;<br />}<br /><br />public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {<br />// TODO 自动生成Ҏ(gu)存根<br />if (ignore || (request.getCharacterEncoding() == null)) {<br />String encoding = selectEncoding(request);<br />if (encoding != null)<br />request.setCharacterEncoding(encoding);<br />}<br />chain.doFilter(request, response);<br />}<br /><br />public void destroy() {<br />// TODO 自动生成Ҏ(gu)存根<br />this.encoding = null;<br />this.filterConfig = null;<br />}<br /><br />protected String selectEncoding(ServletRequest request) {<br />return (this.encoding);<br />}<br />}<br /><br />然后再web.xml加上<br /><!-- Set Character Encoding--><br /><filter><br /><filter-name>Set Character Encoding</filter-name><br /><filter-class>com.struts.common.SetCharacterEncodingFilter</filter-class><br /><init-param><br /><param-name>encoding</param-name><br /><param-value>UTF-8</param-value><br /></init-param><br /></filter><br /><br /><filter-mapping><br /><filter-name>Set Character Encoding</filter-name><br /><url-pattern>/*</url-pattern><br /></filter-mapping><br /><!-- Set Character Encoding--><br /><br />使用qo器的好处很多Q特别是目之中?br />而且在用国际化时就更有用了Q只要在面指定<%@ page language="java" pageEncoding="UTF-8" %>Q服务器׃Ҏ(gu)本地Locale来显C正的字符集?br /><br />所以我特别推荐使用qo器?br /><br />Ҏ(gu)三:修改tomcat的server.xml文g中URIEncoding?br /><Connector<br />debug="0"<br />acceptCount="100"<br />connectionTimeout="20000"<br />disableUploadTimeout="true"<br />port="80"<br />redirectPort="8443"<br />enableLookups="false"<br />minSpareThreads="25"<br />maxSpareThreads="75"<br />maxThreads="150"<br />maxPostSize="0"<br /><font color="#0000ff"><b>URIEncoding="GBK"</b></font><br />><br /></Connector><br />q个Ҏ(gu)主要针对从url中获取字W串的问题?br />在tomcat5.0及以上版本,post和getҎ(gu)在处理编码时有所不同。如果你在url中获取中文就会出玎ͼ受但在tomcat4.1版本没有问题Q因为tomcat4.1的post和getҎ(gu)在处理编码时是一L(fng)?<img src ="http://www.tkk7.com/yanzhou/aggbug/70535.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yanzhou/" target="_blank">周游世界</a> 2006-09-19 15:09 <a href="http://www.tkk7.com/yanzhou/archive/2006/09/19/70535.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://skcncar.com" target="_blank">йŮ69ٸ</a>| <a href="http://0888qb.com" target="_blank">˾þþùۿëƬ</a>| <a href="http://ww99w.com" target="_blank">¹AVר </a>| <a href="http://aplus178.com" target="_blank">߹ۿ</a>| <a href="http://www2626cf.com" target="_blank">67194츾ѹۿ</a>| <a href="http://8222se.com" target="_blank">Ѿþþþþ</a>| <a href="http://clzqb2b.com" target="_blank">A벥ëƬһ</a>| <a href="http://580jp.com" target="_blank">ɫͼƵ߹ۿ</a>| <a href="http://339258.com" target="_blank">ҹƷ</a>| <a href="http://qulu999.com" target="_blank">vѹۿ</a>| <a href="http://cshjjc.com" target="_blank">Ů˱Ƶվ</a>| <a href="http://skcncar.com" target="_blank">ĻƵֻѿ</a>| <a href="http://seosuanfa.com" target="_blank">ھƷһëƬѿ</a>| <a href="http://88109a.com" target="_blank">99Ʒһ</a>| <a href="http://shlamore.com" target="_blank">ޱAAAר</a>| <a href="http://8123pp.com" target="_blank">Ļ޾Ʒ</a>| <a href="http://bjlfggcm.com" target="_blank">޹Ʒۺһ</a>| <a href="http://ymiwang.com" target="_blank">þƷAV鶹Ƭ </a>| <a href="http://963315.com" target="_blank">߹ۿƵ</a>| <a href="http://686kp.com" target="_blank">ɫͼƬС˵</a>| <a href="http://qmoread.com" target="_blank">˳ӰԺҹվ</a>| <a href="http://8888kkk.com" target="_blank">޹ģ߲</a>| <a href="http://963315.com" target="_blank">»ɫַ</a>| <a href="http://868664.com" target="_blank">Ƶ߹ۿƵ</a>| <a href="http://58rjz.com" target="_blank">av</a>| <a href="http://bisilover.com" target="_blank">ŷ޵һa߹ۿ</a>| <a href="http://t66ycom.com" target="_blank">av</a>| <a href="http://njchxf.com" target="_blank">ۺϾƷһ</a>| <a href="http://taoh2517.com" target="_blank">ŷƷպһ</a>| <a href="http://by22877.com" target="_blank">޸߹ۿ</a>| <a href="http://dsdkg.com" target="_blank">ۺϾþó69</a>| <a href="http://bentuxinli.com" target="_blank">ϵйƷƷ˿</a>| <a href="http://777vip8.com" target="_blank">Ƶվ</a>| <a href="http://18736374.com" target="_blank">޾ƷŮ</a>| <a href="http://jsjumei.com" target="_blank">˳ѹۿ</a>| <a href="http://123470c.com" target="_blank">˳ھþۺվ</a>| <a href="http://aa7852.com" target="_blank">޳aƬ߿</a>| <a href="http://8hnbuk14.com" target="_blank">ɫƷVRһ</a>| <a href="http://anyliz.com" target="_blank">ĻۺϾþۺ </a>| <a href="http://61255555.com" target="_blank">ŮƵվ </a>| <a href="http://fenxiangceo.com" target="_blank">AVר߹ۿ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>