订阅本站

JavaScript之eval()函数

中國壹石頭 发表于 2010-4-24 分类 备份文档_txt | 发表评论

 Eval()函数 这是我在学习找到的一篇简述Eval的文章,我在此转贴并加入一点自己的心得!在此谢谢原创者 该函数可以把一个字符串当作一个JavaScript表达式一样去执行它,具体来说,就是eval接受一个字符串类型的参数,将这个字符串作为代码在上下文环境中执行,并返回执行的结果。举个小例子: 
var the_unevaled_answer = “2 + 3″;
var the_evaled_answer = eval(“2 + 3″);
alert(“the un-evaled answer is ” + the_unevaled_answer + ” and the evaled answer is ” + the_evaled_answer);
    
    如果你运行这段eval程序, 你将会看到在JavaScript里字符串”2 + 3″实际上被执行了。所以当你把 the_evaled_answer的值设成 eval(“2 + 3″)时, JavaScript将会明白并把2和3的和返回给the_evaled_answer。这个看起来似乎有点傻,其实可以做出很有趣的事。比如使用eval你可以根据用户的输入直接创建函数。这可以使程序根据时间或用户输入的不同而使程序本身发生变化,通过举一反三,你可以获得惊人的效果。
但是在使用eval函数是需要注意两点:
1)它是有返回值的,如果参数字符串是一个表达式,就会返回表达式的值。如果参数字符串不是表达式,没有值,那么返回“undefined”。
2)参数字符串作为代码执行时,是和调用eval函数的上下文相关的,即其中出现的变量或函数调用必须在调用eval的上下文环境中可用。
资料引用:http://www.knowsky.com/400329.html

无题诗

中國壹石頭 发表于 2010-4-24 分类 备份文档_txt | 发表评论

望处雨收云断
凭阑悄悄
目送秋光
晚景萧疏
堪动宋玉悲凉

水风轻
蘋花渐老
月露冷
梧叶飘黄
遣情伤
故人何在
烟水茫茫

难忘
文期酒会
几孤风月
屡变星霜
海阔山遥
未知何处是潇汀

念双燕
难凭远信
指暮天
空识归航
黯相望
断鸿声里
立尽斜阳

Mina DNS Server

中國壹石頭 发表于 2010-4-24 分类 备份文档_txt | 发表评论

I’m implementing a DNS server using MINA (yes, I’ve looked at the one in
the directory project but no insight from that one since it only binds
to UDP). DNS servers should listen on both TCP and UDP (and in this case
it is required since some of the answers will blow out the UDP size
limits). Anyway, I’m having two problems;

1) Just to get the skeleton working I wanted to re-create the
ReverseProtocol example so that it worked on both UDP and TCP on the
same port. I have it binding and the logger shows the connections and
the packet contents but the ReverseProtocolHandler never sees the
packet. I’ve included the main class below. I haven’t really modified
ReverseProtocolHandler from the example other than changing the package
name.

2) Conceptually I’m trying to wrap my head around how to connect the
session oriented TCP side and the non-session oriented datagram side
together in the CodecFilter so that the IoHandler just gets a DNS
question that it simply answers without regard to whether it was
received via TCP or UDP. Does anyone have any suggestions for how to
handle that within the CodecFilter? One of the things I’m really
confused by is the use of Session ‘language’ about the DatagramAcceptor
and what that means.

Thanks!

public class DnsServer {
     private static final int PORT = 5300;
     public static void main( String[] args ) throws Exception
     {
         IoAcceptor tcpacceptor = new SocketAcceptor();
         IoAcceptor udpacceptor = new DatagramAcceptor();

         // Prepare the configuration
         SocketAcceptorConfig tcpcfg = new SocketAcceptorConfig();
         DatagramAcceptorConfig udpcfg = new DatagramAcceptorConfig();
         LoggingFilter loggingfilter = new LoggingFilter();
         tcpcfg.setReuseAddress( true );
         tcpcfg.getFilterChain().addLast( “logger”, loggingfilter );
         ProtocolCodecFilter codecFilter = new ProtocolCodecFilter(
          new  TextLineCodecFactory(Charset.forName(“UTF-8″)));

         tcpcfg.getFilterChain().addLast(
                 “codec”,
                 codecFilter);

         udpcfg.getFilterChain().addLast( “logger”, loggingfilter);
         udpcfg.getFilterChain().addLast(“codec”, codecFilter);

         // Bind
         tcpacceptor.bind(
                 new InetSocketAddress( PORT ),
                 new ReverseProtocolHandler(),
                 tcpcfg );

         udpacceptor.bind(
          new InetSocketAddress( PORT ),
          new ReverseProtocolHandler(),
          udpcfg);

         System.out.println( “Listening on port ” + PORT );
     }
}

Mina状态机

中國壹石頭 发表于 2010-4-24 分类 备份文档_txt | 发表评论

如果你使用Mina开发一个复杂的网络应用时,你可能在某些地方会遇到那个古老而又好用的状态模式,来
使用这个模式解决你的复杂应用。然而,在你做这个决定之前,你或许想检出Mina的状态机的代码,它会
根据当前对象的状态来返回对接收到的简短的数据的处理信息。

注意:现在正式发布Mina的状态机。因此你要自己在Mina的SVN服务器上检出该代码,并自己编译,请参考
开发指南,来获取更多的关于检出和编译Mina源码的信息。Mina的状态机可以和所有已经发布的版本Mina配
合使用(1.0.x, 1.1.x 和 当前发布的版本)。

一个简单的例子

让我们使用一个简单的例子来展示一下Mina的状态机是如何工作的。下面的图片展示了一个录音机的状态机。
其中的椭圆是状态,箭头表示事务。每个事务都有一个事件的名字来标记该事务。

  *******************************************************************************
  *                                                                                                                                *
  *                                     这里展示的是那个煞笔图片                                           *
  *                                                                                                                                *
  *                                                                                                                                *
  *******************************************************************************

  初始化时,录音机的状态是空的。当磁带放如录音机的时候,加载的事件被触发,录音机进入到加载
  状态。在加载的状态下,退出的事件会使录音机进入到空的状态,播放的事件会使加载的状态进入到
  播放状态。等等……我想你可以推断后后面的结果:)

  现在让我们写一些代码。外部(录音机中使用该代码的地方)只能看到录音机的接口:

———————-START———————-
  public interface TapeDeck {
    void load(String nameOfTape);
    void eject();
    void start();
    void pause();
    void stop();
}
———————–END————————

下面我们开始编写真正执行的代码,这些代码在一个事务被触发时,会在状态机中执行。首先我们定义一
个状态。这些状态都使用字符串常量来定义,并且使用@state标记来声明。

———————-START———————-
public class TapeDeckHandler {
    @State public static final String EMPTY   = “Empty”;
    @State public static final String LOADED  = “Loaded”;
    @State public static final String PLAYING = “Playing”;
    @State public static final String PAUSED  = “Paused”;
}
———————–END————————

现在我们已经定义了录音机中的所有状态,我们可以根据每个事务来创建相应的代码。每个事务都和一个
TapeDeckHandler的方法对应。每个事务的方法都使用@Transtration标签来声明,这个标签定义了事件
的ID,该ID会触发事务的执行。事务开始时的状态使用start,事务结束使用next,事务正在运行使用on。

———————-START———————-
public class TapeDeckHandler {
    @State public static final String EMPTY = “Empty”;
    @State public static final String LOADED = “Loaded”;
    @State public static final String PLAYING = “Playing”;
    @State public static final String PAUSED = “Paused”;
   
    @Transition(on = “load”, in = EMPTY, next = LOADED)
    public void loadTape(String nameOfTape) {
        System.out.println(“Tape ‘” + nameOfTape + “‘ loaded”);
    }

    @Transitions({
        @Transition(on = “play”, in = LOADED, next = PLAYING),
        @Transition(on = “play”, in = PAUSED, next = PLAYING)
    })
    public void playTape() {
        System.out.println(“Playing tape”);
    }
   
    @Transition(on = “pause”, in = PLAYING, next = PAUSED)
    public void pauseTape() {
        System.out.println(“Tape paused”);
    }
   
    @Transition(on = “stop”, in = PLAYING, next = LOADED)
    public void stopTape() {
        System.out.println(“Tape stopped”);
    }
   
    @Transition(on = “eject”, in = LOADED, next = EMPTY)
    public void ejectTape() {
        System.out.println(“Tape ejected”);
    }
}
———————–END————————

请注意,TapeDeckHandler 类没有实现TapeDeck ,呵呵,这是故意的。

现在让我们亲密接触一下这个代码。在loadTape方法上的@Transition标签:

———————-START———————-
@Transition(on = “load”, in = EMPTY, next = LOADED)
public void loadTape(String nameOfTape) {}
———————–END———————–

指定了这个状态后,当录音机处于空状态时,磁带装载事件启动后会触发loadTape方法,并且
录音机状态将会变换到Loaded状态。@Transition标签中关于pauseTape,stopTape,ejectTape
的方法就不需要在多介绍了。关于playTape的标签和其他的标签看起来不太一样。从上面的图中
我们可以知道,当录音机的状态在Loaded或者Paused时,play事件都会播放磁带。当多个事务
同时条用同一个方法时,@Transition标签需要按下面的方法使用:

———————-START———————-
@Transitions({
    @Transition(on = “play”, in = LOADED, next = PLAYING),
    @Transition(on = “play”, in = PAUSED, next = PLAYING)
})
public void playTape(){}
———————–END———————–

@Transition标签清晰的列出了声明的方法被多个事务调用的情况。

 ###############################################################

要点:更多关于@Transition 标签的参数
      (1)如果你省略了on参数,系统会将该值默认为“*”,这样任何事件都可以触发该方法。
      (2)如果你省略了next参数,系统会将默认值改为“_self_”,这个是和当前的状态相关的,
                如果你要实现一个循环的事务,你所需要做的就是省略状态机中的next参数。
       (3)weight参数用于定义事务的查询顺序,一般的状态的事务是根据weight的值
                按升序排列的,weight默认的是0.

 ###############################################################
  
现在最后一步就是使用声明类创建一个状态机的对象,并且使用这个状态机的实例创建一个代理对象,
该代理对象实现了TapeDeck接口:

———————-START———————-
public static void main(String[] args) {
    //  创建录音机事件的句柄
    TapeDeckHandler handler = new TapeDeckHandler();
    // 创建录音机的状态机
    StateMachine sm = StateMachineFactory.getInstance(Transition.class).create(TapeDeckHandler.EMPTY, handler);
    // 使用上面的状态机,通过一个代理创建一个TapeDeck的实例
    TapeDeck deck = new StateMachineProxyBuilder().create(TapeDeck.class, sm);
   
    // 加载磁带
    deck.load(“The Knife – Silent Shout”);
    // 播放
    deck.play();
    // 暂停
    deck.pause();
    // 播放
    deck.play();
    // 停止
    deck.stop();
    // 退出
    deck.eject();
}
———————–END———————–

这一行
———————-START———————-
TapeDeckHandler handler = new TapeDeckHandler();
StateMachine sm = StateMachineFactory.getInstance(Transition.class).create(TapeDeckHandler.EMPTY, handler);
———————–END———————–

使用TapeDeckHandler创建一个状态机的实例。StateMachineFactory.getInstance(…) 调用的方法中使用的Transition.class
是通知工厂我们使用@Transition 标签创建一个状态机。我们指定了状态机开始时状态是空的。一个状态机是一个基本的指示
图。状态对象和图中的节点对应,事务对象和箭头指向的方向对应。我们在TapeDeckHandler中使用的 每一个@Transition
标签都和一个事务的实例对应。

 ###############################################################

要点: 那么, @Transition 和 Transition 有什么不同吗?
 @Transition 是你用来标记当事务在状态之间变化时应该使用那个方法。在后台处理中,
 Mina的状态机会为MethodTransition 中每一个事务标签创建一个事务的实例。MethodTransition
 实现了Transition 接口。作为一个Mina状态机的使用者,你不用直接使用Transition 或者
MethodTransition 类型的对象。

 ###############################################################

录音机TapeDeck 的实例是通过调用StateMachineProxyBuilder来创建的:

———————-START———————-
TapeDeck deck = new StateMachineProxyBuilder().create(TapeDeck.class, sm);
———————–END———————–

StateMachineProxyBuilder.create()使用的接口需要由代理的对象来实现,状态机的实例将接收
由代理产生的事件所触发的方法。

当代码执行时,输出的结果如下:

———————-START———————-
Tape ‘The Knife – Silent Shout’ loaded
Playing tape
Tape paused
Playing tape
Tape stopped
Tape ejected
———————–END———————–

 ###############################################################

要点: 这和Mina有什么关系?
            或许你已经注意到,在这个例子中没有对Mina进行任何配置。但是不要着急。
     稍后我们将会看到如何为Mina的IoHandler接口创建一个状态机。

 ###############################################################
它是怎样工作的?

让我们走马观花的看看当代理调用一个方法的时候发生了什么。

 查看一个StateContext(状态的上下文)对象
 状态上下文之所以重要是因为它保存了当前的状态。代理调用一个方法时,状态上下文
 会通知StateContextLookup 实例去方法的参数中获取一个状态的上下文。一般情况下,
StateContextLookup 的实现将会循环方法中的参数,并查找一个指定类型的对象,并且
使用这个对象反转出一个上下文对象。如果没有声明一个状态上下文,StateContextLookup
将会创一个,并将其存放到对象中。

当代理Mina的IoHandler接口时,我们将使用IoSessoinStateContextLookup 实例,该实例用
来查询一个IoSession中的方法参数。它将会使用 IoSession的属性值为每一个Mina的session
来存放一个独立的状态上下文的实例。这中方式下,同样的状态机可以让所有的Mina的会话使用,
而不会使每个会话彼此产生影响。

###############################################################

要点: 在上面的例子中,当我们使用StateMachineProxyBuilder创建一个代理时,我们
一直没有我们一直没有配置StateContextLookup 使用哪种实现。如果没有配置,系统会
使用SingletonStateContextLookup 。SingletonStateContextLookup 总是不理会方法中
传递给它的参数,它一直返回一个相同的状态上下文。很明显,这中方式在多个客户端
并发的情况下使用同一个同一个状态机是没有意义的。这种情况下的配置会在后面的关于
IoHandler 的代理配置时进行说明。

 ###############################################################
将方法请求反转成一个事件对象

所有在代理对象上的方法请求都会有代理对象转换成事件对象。一个事件有一个ID或者0个或多个
参数。事件的ID和方法的名字相当,事件的参数和方法的参数相当。调用方法deck.load(“The Knife – Silent Shout”)
相当于事件{id = “load”, arguments = ["The Knife - Silent Shout"]}.事件对象中包含一个状态上下文的引用,
该状态上下文是当前查找到的。
触发状态机

一旦事件对象被创建,代理会调用StateMachine.handle(Event).方法。StateMachine.handle(Event)
遍历事务对象中当前的状态,来查找能够接收当前事件的事务的实例。这个过程会在事务的实例找到
后停止。这个查询的顺序是由事务的重量值来决定的(重量值一般在@Transition 标签中指定)。

执行事务

最后一部就是在Transition 中调用匹配事件对象的Transition.execute(Event)方法。当事件已经执行,这
个状态机将更新当前的状态,更新后的值是你在事务中定义的后面的状态。
###############################################################

要点: 事务是一个接口。每次你使用@Transition 标签时,MethodTransition对象将会被创建。

 ###############################################################
MethodTransition(方法事务)

MethodTransition非常重要,它还需要一些补充说明。如果事件ID和@Transition标签中的on参数匹配,
事件的参数和@Transition中的参数匹配,那么MethodTransition和这个事件匹配。

所以如果事件看起来像{id = “foo”, arguments = [a, b, c]},那么下面的方法:

———————-START———————-
@Transition(on = “foo”)
public void someMethod(One one, Two two, Three three) { … }
———————–END———————–
只和这个事件匹配((a instanceof One && b instanceof Two && c instanceof Three) == true).。当匹配时,
这个方法将会被与其匹配的事件使用绑定的参数调用。

###############################################################

要点: Integer, Double, Float, 等也和他们的基本类型int, double, float, 等匹配。

 ###############################################################

libevent源码分析

中國壹石頭 发表于 2010-4-24 分类 备份文档_txt | 发表评论

libevent实现了网络IO,timer,signal的事件触发机制. 可以很方便的应用于event-driven服务器中,作为其底层事件处理模块. 比较成功的案例有 memcache(分布式缓存), PLB(负载均衡器)等.
最近研究了一下libevent的源码, 版本是1.4.4,可以大概分成几个模块:

? 事件处理框架

? 事件引擎模块

? Buffer管理模块

? 信号处理模块

1. 事件处理框架
1.1 event_init() 初始化

首先要隆重介绍event_base对象:

struct event_base {
    const struct eventop *evsel;
    void *evbase;
    int event_count;        /* counts number of total events */
    int event_count_active; /* counts number of active events */
   
    int event_gotterm;      /* Set to terminate loop */
       
    /* active event management */
    struct event_list **activequeues;
    int nactivequeues;

    struct event_list eventqueue;
    struct timeval event_tv;

    RB_HEAD(event_tree, event) timetree;
};

   event_base对象整合了事件处理的一些全局变量, 角色是event对象的”总管家”, 他包括了事件引擎函数对象(evsel, evbase), 当前入列事件列表(event_count, event_count_active, eventqueue), 全局终止信号(event_gotterm), 活跃事件列表(avtivequeues), 事件队列树(timetree)…

   初始化时创建event_base对象, 选择 当前OS支持的事件引擎(epoll, poll, select…)并初始化, 创建全局信号队列(signalqueue), 活跃队列的内存分配( 根据设置的priority个数,默认为1).

1.2 event_set() 事件定义

    event_set来设置event对象,包括所有者event_base对象, fd, 事件(EV_READ| EV_WRITE), 回掉函数和参数,事件优先级是当前event_base的中间级别(current_base->nactivequeues/2). event对象的定义见下:

struct event {
    TAILQ_ENTRY (event) ev_next;
    TAILQ_ENTRY (event) ev_active_next;
    TAILQ_ENTRY (event) ev_signal_next;
    RB_ENTRY (event) ev_timeout_node;

    struct event_base *ev_base;
    int ev_fd;
    short ev_events;
    short ev_ncalls;
    short *ev_pncalls; /* Allows deletes in callback */

    struct timeval ev_timeout;

    int ev_pri;     /* smaller numbers are higher priority */

    void (*ev_callback)(int, short, void *arg);
    void *ev_arg;

    int ev_res;     /* result passed to event callback */
    int ev_flags;
};

1.3 event_add() 事件添加:

   int event_add(struct event *ev, struct timeval *tv)

   这个接口有两个参数, 第一个是要添加的事件, 第二个参数作为事件的超时值(timer). 如果该值非NULL, 在添加本事件的同时添加超时事件(EV_TIMEOUT)到时间队列树(timetree), 根据事件类型处理如下: 

   EV_READ   => EVLIST_INSERTED => eventqueue

   EV_WRITE   => EVLIST_INSERTED => eventqueue

   EV_TIMEOUT => EVLIST_TIMEOUT => timetree

EV_SIGNAL => EVLIST_SIGNAL => signalqueue

1.4 event_base_loop() 事件处理主循环

   这里是事件的主循环,只要flags不是设置为EVLOOP_NONBLOCK, 该函数就会一直循环监听事件/处理事件.

   每次循环过程中, 都会处理当前触发(活跃)事件:

   (a). 检测当前是否有信号处理(gotterm, gotsig), 这些都是全局参数,不适合多线程

   (b). 时间更新,找到离当前最近的时间事件, 得到相对超时事件tv

    (c). 调用事件引擎的dispatch wait事件触发, 超时值为tv, 触发事件添加到activequeues

   (d). 处理活跃事件, 调用caller的callbacks (event_process_acitve)

2. 事件引擎模块 :
   Linux下有多种I/O复用机制, .来处理多路事件监听, 常见的有epoll, poll, select, 按照优先级排下来为:

evport
kqueue
epoll
devpoll
rtsig
poll
select
   在event_init()选择事件引擎时,按照优先级从上向下检测, 如果检测成功,当前引擎被选中.每个引擎需要定义几个处理函数,以epoll为例:

struct eventop epollops = {
    “epoll”,
    epoll_init,
    epoll_add,
    epoll_del,
    epoll_recalc,
    epoll_dispatch,
    epoll_dealloc
};

3. Buffer管理模块:
   libevent定义了自己的buffer管理机制evbuffer, 支持多种类型数据的read/write功能, 包括不定长字符串,buffer中内存采用预分配/按需分配结合的方式, 可以比较方便的管理多个数据结构映射到内存buffer.

   需要拉出来介绍的是evbuffer_expand()函数, 当内部内存不够时,需要expand, 这里采用预分配的方式,如果需要长度<256字节,预分配256字节, 同时内存成倍增长,一直到大于需要的长度.

4. 信号处理模块
   信号处理单独提出来,主要是libevent的信号处理比较轻巧, 从而很好融合到event机制.

   singal模块初始化(evsignal_init)时, 创建了UNIX域socket ( pipe)作为内部消息传递桥梁:

    if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1)
        event_err(1, “%s: socketpair”, __func__);

    FD_CLOSEONEXEC(ev_signal_pair[0]);
    FD_CLOSEONEXEC(ev_signal_pair[1]);

    fcntl(ev_signal_pair[0], F_SETFL, O_NONBLOCK);

    event_set(&ev_signal, ev_signal_pair[1], EV_READ,
        evsignal_cb, &ev_signal);
    ev_signal.ev_flags |= EVLIST_INTERNAL;

   evsignal_add(), 添加信号事件, 关联信号处理方法(sigaction)

   实际运行过程中,如果某singal发生, 对应的信号处理方法被调用, write a character to pipe

   同时pipe的另一端被激活, 添加信号到singalqueue, 在事件循环中evsignal_process处理信号callbacks

5. 其他资料:
libevent官方网址:   http://www.monkey.org/~provos/libevent/

JavaScript提交表单

中國壹石頭 发表于 2010-4-24 分类 备份文档_txt | 发表评论

js提交表单及js表单验证2008/05/26 03:56 P.M.js提交表单及js表单验证功能强大,很多原本需要在服务器端实现的功能,现在通过简单的js代码就可以在客服端实现同样的效果。下面是一些常用的js表单验证代码,供大家参考学习。

1:js 字符串长度限制、判断字符长度 、js限制输入、限制不能输入、textarea 长度限制
<script>
function test()
{
if(document.a.b.value.length>50)
{
alert(“不能超过50个字符!”);
document.a.b.focus();
return false;
}
}
</script>
2:js验证邮箱格式
<SCRIPT LANGUAGE=javascript RUNAT=Server>
function isEmail(strEmail) {
if (strEmail.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) != -1)
return true;
else
alert(“oh”);
}
</SCRIPT>

3: js屏蔽关键字(这里屏蔽***和****)
<script language=”javascript1.2″>
function test() {
if((a.b.value.indexOf (“***”) == 0)||(a.b.value.indexOf (“****”) == 0)){
alert(“:)”);
a.b.focus();
return false;}
}
</script>

4: js两次输入密码是否相同
<script>
function check()
{
with(document.all){
if(input1.value!=input2.value)
{
alert(“false”)
input1.value = “”;
input2.value = “”;
}
else document.forms[0].submit();
}
}
</script>

5:js屏蔽右键
oncontextmenu=”return false” ondragstart=”return false” onselectstart=”return false”加在body中
6: js判断表单项不能为空
<script   language=”javascript”><!–
function   CheckForm()
{
if   (document.form.name.value.length   ==   0)   {
alert(“请输入您姓名!”);
document.form.name.focus();
return   false;
}
return   true;
}
–>
</script>

7:js比较两个表单项的值是否相同
<script   language=”javascript”>
<!–
function   CheckForm()
if   (document.form.PWD.value   !=   document.form.PWD_Again.value)   {
alert(“您两次输入的密码不一样!请重新输入.”);
document.ADDUser.PWD.focus();
return   false;
}
return   true;
}
–>
</script>

8:js判断表单项只能为数字和”_”,用于电话/银行帐号验证上,可扩展到域名注册等
<script   language=”javascript”>
<!–
function   isNumber(String)
{
var   Letters   =   “1234567890-”;   //可以自己增加可输入值
var   i;
var   c;
if(String.charAt(   0   )==’-')
return   false;
if(   String.charAt(   String.length   -   1   )   ==   ‘-’   )
return   false;
for(   i   =   0;   i   <   String.length;   i   ++   )
{
c   =   String.charAt(   i   );
if   (Letters.indexOf(   c   )   <   0)
return   false;
}
return   true;
}
function   CheckForm()
{
if(!   isNumber(document.form.TEL.value))   {
alert(“您的电话号码不合法!”);
document.form.TEL.focus();
return   false;
}
return   true;
}
–>
</script>
9:js判断表单项输入数值/长度限定
<script   language=”javascript”><!–
function   CheckForm()
{
if   (document.form.count.value   >   100   ||   document.form.count.value   <   1)
{
alert(“输入数值不能小于零大于100!”);
document.form.count.focus();
return   false;
}
if   (document.form.MESSAGE.value.length<10)
{
alert(“输入文字小于10!”);
document.form.MESSAGE.focus();
return   false;
}
return   true;
}
//–>
</script>

10:js判断中文/英文/数字/邮件地址合法性判断

<SCRIPT   LANGUAGE=”javascript”><!–
function   isEnglish(name)   //英文值检测
{
if(name.length   ==   0)
return   false;
for(i   =   0;   i   <   name.length;   i++)   {
if(name.charCodeAt(i)   >   128)
return   false;
}
return   true;
}

function   isChinese(name)   //中文值检测
{
if(name.length   ==   0)
return   false;
for(i   =   0;   i   <   name.length;   i++)   {
if(name.charCodeAt(i)   >   128)
return   true;
}
return   false;
}

function   isMail(name)   //   E-mail值检测
{
if(!   isEnglish(name))
return   false;
i   =   name.indexOf(“   at   “);
j   =   name   dot   lastIndexOf(“   at   “);
if(i   ==   -1)
return   false;
if(i   !=   j)
return   false;
if(i   ==   name   dot   length)
return   false;
return   true;
}

function   isNumber(name)   //数值检测
{
if(name.length   ==   0)
return   false;
for(i   =   0;   i   <   name.length;   i++)   {
if(name.charAt(i)   <   “0″   ||   name.charAt(i)   >   “9″)
return   false;
}
return   true;
}

function   CheckForm()
{
if(!   isMail(form.Email.value))   {
alert(“您的电子邮件不合法!”);
form.Email.focus();
return   false;
}
if(!   isEnglish(form.name.value))   {
alert(“英文名不合法!”);
form.name.focus();
return   false;
}
if(!   isChinese(form.cnname.value))   {
alert(“中文名不合法!”);
form.cnname.focus();
return   false;
}
if(!   isNumber(form.PublicZipCode.value))   {
alert(“邮政编码不合法!”);
form.PublicZipCode.focus();
return   false;
}
return   true;
}
//–>
</SCRIPT>
11:js限定表单项不能输入的字符
<script   language=”javascript”><!–

function   contain(str,charset)//   字符串包含测试函数
{
var   i;
for(i=0;i<charset.length;i++)
if(str.indexOf(charset.charAt(i))>=0)
return   true;
return   false;
}

function   CheckForm()
{
if   ((contain(document.form.NAME.value,   “%\(\)><”))   ||   (contain(document.form.MESSAGE.value,   “%\(\)><”)))
{
alert(“输入了非法字符”);
document.form.NAME.focus();
return   false;
}
return   true;
}
//–>
</script>

12:js检查一段字符串是否全由数字组成          
<script language=”Javascript”><!–          
function checkNum(str){return str.match(/\D/)==null}          
alert(checkNum(“1232142141″))          
alert(checkNum(“123214214a1″))          
// –></script>            
13:js怎么判断是否是字符
<script language=”Javascript”><!–          
function checkChr(str)   
if (/[^\x00-\xff]/g.test(s)) alert(“含有汉字”);         
else alert(“全是字符”);     
// –></script>         
   
14: 邮箱格式验证   
<script language=”Javascript”><!–  
//函数名:chkemail    
//功能介绍:检查是否为Email Address    
//参数说明:要检查的字符串    
//返回值:0:不是 1:是    
function chkemail(a)    
{ var i=a.length;    
var temp = a.indexOf(‘@’);    
var tempd = a.indexOf(‘.’);    
if (temp > 1) {    
if ((i-temp) > 3){    
if ((i-tempd)>0){    
return 1;    
}    
   
}    
}    
return 0;    
}    
// –></script>

JSP页面用一个Form提交两个action

中國壹石頭 发表于 2010-4-24 分类 备份文档_txt | 发表评论

在JSP页面中用一个form提交两个action的方法:
<form name=”formname” action=”\formaction.do” method=”post”>
<input type=”submit” value=”firstsub” onclick=”return formsub();”/>
<a href=”#” onclick=”return hrefsub();”>second sub</a>
</form>
上面的form中有两个提交,第一个是submit的提交,第二个是a href的提交
javascript函数如下:
function formsub()
{
   return true;//直接就提交到\formaction.do中了
}
function hrefsub()
{
 with(document.formname) {
    var oldact = action;//保存原来的action
      var oldtarget = target;//保存原来的    target
      target = “_blank”;//新的target
      action = “/herfaction.do”;//新的action
      submit();   //提交
      action=oldact;//恢复原来的target action
      target = oldtarget;
}
return false;
}

JAVA字符编码

中國壹石頭 发表于 2010-4-24 分类 备份文档_txt | 发表评论

  一、概要 
  在JAVA应用程序特别是基于WEB的程序中,经常遇到字符的编码问题。为了防止出现乱码,首先需要了解JAVA是如何处理字符的,这样就可以有目的地在输入/输出环节中增加必要的转码。其次,由于各种服务器有不同的处理方式,还需要多做试验,确保使用中不出现乱码。 
  二、基本概念 
  2.1   JAVA中字符的表达 
 JAVA   中有char、byte、String这几个概念。char   指的是一个UNICODE字符,为16位的整数。byte   是字节,字符串在网络传输或存储前需要转换为byte数组。在从网络接收或从存储设备读取后需要将byte数组转换成String。String是字符串,可以看成是由char组成的数组。String   和   char   为内存形式,byte是网络传输或存储的序列化形式。 
  举例: 
  英 
  String   ying   =   “英”; 
  char   ying   =   ying.charAt(0); 
  String   yingHex   =   Integer.toHexString(ying); 
  82   F1   
  byte   yingGBBytes   =   ying.getBytes(“GBK”); 
  GB编码的字节数值 
  D3   A2   
  2.2   编码方式的简介 
  String序列化成byte数组或反序列化时需要选择正确的编码方式。如果编码方式不正确,就会得到一些0x3F的值。常用的字符编码方式有ISO8859_1、GB2312、GBK、UTF-8/UTF-16/UTF-32。 
  ISO8859_1用来编码拉丁文,它由单字节(0-255)组成。 
  GB2312、GBK用来编码简体中文,它有单字节和双字节混合组成。最高位为1的字节和下一个字节构成一个汉字,最高位为0的字节是ASCII码。 
  UTF-8/UTF-16/UTF-32是国际标准UNICODE的编码方式。   用得最多的是UTF-8,主要是因为它在对拉丁文编码时节约空间。 
  UNICODE值   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   
  三、J2SE中相关的函数 
  String   str   =”英”; 
  //取得GB2312编码的字节 
  byte[]   bytesGB2312   =   str.getBytes(“GB2312”);   
  //取得平台缺省编码的字节(solaris为ISO8859_1,windows为GB2312) 
  byte[]   bytesDefault   =   str.getBytes(); 
  //用指定的编码将字节转换成字符串 
  String   newStrGB   =   new   String(bytesGB2312,   “GB2312”); 
  
  //用平台缺省的编码将字节转换成字符串(solaris为ISO8859_1,windows为GB2312) 
  String   newStrDefault   =   new   String(bytesDefault); 
  //用指定的编码从字节流里面读取字符 
  InputStream   in   =   xxx; 
  InputStreamReader   reader   =   InputStreamReader(   in,   “GB2312”); 
  char   aChar   =   reader.read(); 
  四、JSP、数据库的编码 
  4.1   JSP中的编码 
  (1)   静态声明: 
  CHARSET有两个作用: 
  JSP文件的编码方式:在读取JSP文件、生成JAVA类时,源JSP文件中汉字的编码 
  JSP输出流的编码方式:在执行JSP时,往response流里面写入数据的编码方式 
  (2)   动态改变:在往response流里面写数据前可以调用response.setContentType(),设定正确的编码类型。 
  (3)   在TOMCAT中,由Request.getParameter()   得到的参数,编码方式都是ISO8859_1。所以如果在浏览器输入框内输入一个汉字“英”,在服务器端就得到一个ISO8859_1编码的(0×00,0xD3,0×00,0xA2)。所以通常在接收参数时转码: 
  String   wrongStr   =   response.getParameter(“name”); 
  String   correctStr   =   new   String(wrongStr.getBytes(“ISO8859_1”),”GB2312”); 
  在最新的SERVLET规范里面,也可以在获取参数之前执行如下代码: 
  request.setCharacterEncoding(“GB2312”); 
  4.2   数据库的编码 
  (1)   数据库使用UTF-16 
  如果String中是UNICODE字符,写入读出时不需要转码 
  (2)   数据库使用ISO8859_1 
  如果String中是UNICODE字符,写入读出时需要转码 
  写入:String   newStr   =   new   String(oldStr.getByte(“GB2312”),   “ISO8859_1”); 
  读出:String   newStr   =   new   String(oldStr.getByte(“ISO8859_1”),”GB2312”); 
  五、源文件的编码 
  5.1   资源文件 
  资源文件的编码方式和编辑平台相关。在WINDOWS平台下编写的资源文件,以GB2312方式编码。在编译时需要转码,以确保在各个平台上的正确性: 
  native2ascii   –encoding   GB2312   source.properties 
  这样从资源文件中读出的就是正确的UNICODE字符串。 
  5.2   源文件 
  源文件的编码方式和编辑平台相关。在WINDOWS平台下开发的源文件,以GB2312方式编码。在编译的时候,需要指定源文件的编码方式: 
  javac   –encoding   GB2312 
  JAVA编译后生成的字节文件的编码为UTF-8。 
  
  ①最新版TOMCAT4.1.18支持request.setCharacterEncoding(String   enc) 
  ②资源文件转码成company.name=\u82f1\u65af\u514b 
  ③如果数据库使用utf-16则不需要这部分转码 
  ④页面上应有 
  转码ⅰ: 
  String   s   =   new   String 
  (request.getParameter(“name”).getBytes(“ISO8859_1”),”GB2312”); 
  转码ⅱ: 
  String   s   =   new   String(name.getBytes(“GB2312”),”ISO8859_1”); 
  转码ⅲ: 
  String   s   =   new   String(name.getBytes(“ISO8859_1”),”   GB2312”); 
  
    
  
    ========================================================= 
  
  JAVA内部究竟是用的什么字符编码呢?这个问题我也找了很久,后来在THINK   IN   JAVA   3rd的12章里看到一个例子出现了UTF-16BE,难道是它?   
            byte[]   utf_16be   =   name.getBytes(“utf-16be”); 
  
            printbyte(utf_16be); 
  
  结果出来了:58   02     length   =   2 
  哈哈,I   got   it!不多不少两个字节,内容也一样。果然是它。同时我在里面也看到,UNICODE的编码还有一个LE,这里的BE,LE我想应该是bigendian和littleendian吧。 
  
    ========================================================== 
  
  import   java.io.*; 
            public   class   TestCodeIO   { 
                        public   static   void   main(String[]   args)   throws   Exception{ 
                                    InputStreamReader   isr   =   new   InputStreamReader(System.in,”iso8859-1″); 
                                                //Create   an   InputStreamReader   that   uses   the   given   charset   decoder 
                                    BufferedReader   br   =   new   BufferedReader   (isr); 
                                    String   strLine   =   br.readLine(); 
                                    br.close(); 
                                    isr.close(); 
                                    System.out.println(strLine); 
                                    System.out.println(new   String   (strLine.getBytes(),”iso8859-1″));//错误改法 
                                                //Encodes   this   String   (strLine)   into   a   sequence   of   bytes   using   the   platform’s   
                                                //default   charset(gb2312)   then   constructs   a   new   String   by   decoding   the   
                                              //specified   array   of   bytes   using   the   specified   charset   (iso8859-1) 
                                              //because   this   String   (strLine)   uses   the   charset   decoder   “iso8859-1″,so   it   can 
                                              //only   be   encoded   by   “iso8859-1″,cann’t   be   encoded   by   the   platform’s   default 
                                              //charset   “gb2312″,so   this   line   is   wrong. 
                                  System.out.println(new   String   (strLine.getBytes(“iso8859-1″)));//正确改法 
                                            //Encodes   this   String   (strLine)   into   a   sequence   of   bytes   using   the   named   
                                            //charset   (iso8859-1),then   constructs   a   new   String   by   decoding   the   
                                            //specified   array   of   bytes   using   the   platform’s   default   charset   (gb2312). 
                                            //This   line   is   right. 
                }   
  } 
  
  上面的英文注释已经说得很清楚了,这里我还是解释一下吧: 
  
  首先是错误的改法     System.out.println(new   String   (strLine.getBytes(),”iso8859-1″)); 
  这句代码是将strLine中的字符串用系统默认的编码方式(这里是gb2312) 
  转换为字节序列,然后用指定的编码方式(这里是iso8859-1)构造一个新的 
  String对象,并打印到屏幕上。 
  错误在哪里呢? 
  
  请注意这一段代码     
  InputStreamReader   isr   =   new   InputStreamReader(System.in,”iso8859-1″); 
  BufferedReader   br   =   new   BufferedReader   (isr); 
  String   strLine   =   br.readLine(); 
  这里strLine存储的内容是用指定的编码方式(iso8859-1)存储的,而转换成字节码 
  的时候(这句代码strLine.getBytes())却使用了系统默认的gb2312编码,所以当然就 
  输出乱码了!然后用gb2312编码的字节序列构建新的String对象的时候又使用了 
  iso8859-1编码,所以输出的乱码和System.out.println(strLine)有所不同。 
  
  至于正确的改法就不用详细说明了吧,首先将strLine用iso8859-1编码方式转换成字节 
  序列,然后用系统默认的编码方式(gb2312)构建新的String对象,然后打印输出。