云自无心水自闲

天平山上白云泉,云自无心水自闲。何必奔冲山下去,更添波浪向人间!
posts - 288, comments - 524, trackbacks - 0, articles - 6
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

index.jsp重定向到mainMenu.html,但其实mainMenu.html并不是一个真正的存在的Html页面。
在appfuse中,Struts的Action的后缀使用的是不是常见的.do,而使用的是.html。
见Web.xml:

    <servlet-mapping>
        <servlet-name>action</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>


因此,查看struts-config.xml,发现/menuMenu只是简单地Forward到/WEB-INF/pages/mainMenu.jsp。
所以,在此处显示的内容是mainMenu.jsp的内容。

mainMenu.jsp页面中的内容不多,只有一个简单的列表,包含两个链接:编辑信息、上传文件。

现在需要仔细研究一下菜单的显示了。可以看到在menuMenu.jsp和login.jsp中都没有菜单的定义和显示。其实菜单的定义和显示还是在前面说到的default.jsp中。
default.jsp中如下一段代码:

            <c:set var="currentMenu" scope="request"><decorator:getProperty property="meta.menu"/></c:set>
            <c:if test="${currentMenu == 'AdminMenu'}">
            <div id="sub">
                <menu:useMenuDisplayer name="Velocity" config="WEB-INF/classes/cssVerticalMenu.vm" permissions="rolesAdapter">
                    <menu:displayMenu name="AdminMenu"/>
                </menu:useMenuDisplayer>
            </div>
            </c:if>

            <div id="nav">
                <div class="wrapper">
                    <h2 class="accessibility">Navigation</h2>
                    <jsp:include page="/common/menu.jsp"/>
                </div>
                <hr />
            </div><!-- end nav -->

首先从页面中取出meta.menu的值,这个值在login.jsp中是: <meta name="menu" content="Login"/>
在mainMenu.jsp中是:<meta name="menu" content="MainMenu"/>
所以,login.jsp中 test="${currentMenu == 'AdminMenu'}" 都不通过。每一部分的内容在这两个页面中都不显示。

下面的一部分是common/menu.jsp,主要是一个menu:useMenuDisplayer
显示的菜单第一个进行了判断,<c:if test="${empty pageContext.request.remoteUser}">
查看Jsp容器中维护的认证中当前用户是否为空,如果成功登录,则这个值即为登录用户名,否则为空。
也就是说,如果没有成功登录,则会显示登录菜单<li><a href="<c:url value="/login.jsp"/>" class="current"><fmt:message key="login.title"/></a></li>。

除了刚才的第一个登录项以外,还有5条菜单菜单项,这5个菜单项使用的是struts-menu的标准用法,而不是象刚才那样直接HTML的输出。
    <menu:displayMenu name="MainMenu"/>
    <menu:displayMenu name="UserMenu"/>
    <menu:displayMenu name="FileUpload"/>
    <menu:displayMenu name="AdminMenu"/>
    <menu:displayMenu name="Logout"/>
查看menu-config.xml,可以发现,只有第一的菜单项MainMenu没有定义角色

< MenuConfig >
    
< Displayers >
        
< Displayer  name ="Velocity"  type ="net.sf.navigator.displayer.VelocityMenuDisplayer" />
    
</ Displayers >
    
< Menus >
        
< Menu  name ="MainMenu"  title ="mainMenu.title"  page ="/mainMenu.html" />
        
< Menu  name ="UserMenu"  title ="menu.user"  description ="User Menu"  forward ="editProfile"  roles ="admin,user" />
        
< Menu  name ="FileUpload"  title ="menu.selectFile"  description ="File Upload"  width ="100"  forward ="selectFile"  roles ="admin,user" />
        
< Menu  name ="AdminMenu"  title ="menu.admin"  description ="Admin Menu"  roles ="admin"  width ="120"  forward ="viewUsers" >
            
< Item  name ="ViewUsers"  title ="menu.admin.users"  forward ="viewUsers" />
            
< Item  name ="ActiveUsers"  title ="mainMenu.activeUsers"  action ="activeUsers" />
            
< Item  name ="ReloadContext"  title ="menu.admin.reload"  action ="reload" />
            
< Item  name ="FlushCache"  title ="menu.flushCache"  action ="flush" />
            
< Item  name ="Clickstream"  title ="menu.clickstream"  page ="/clickstreams.jsp" />
        
</ Menu >
        
< Menu  name ="Logout"  title ="user.logout"  page ="/logout.jsp"  roles ="admin,user" />
    
</ Menus >
</ MenuConfig >


因此,在login.jsp页面也能显示此菜单项。
而剩下需要角色的菜单,就需要登录后,根据角色的设置来显示相应的菜单了。

比如:mraible用户是admin角色,可以显示全部菜单。tomcat用户是user角色,就看不到AdminMenu了。

 

posted @ 2007-03-08 09:51 云自无心水自闲 阅读(1615) | 评论 (0)编辑 收藏

这次详细地说明一下Appfuse的认证过程:
1. 在Web.xml中定义了FilterChainProxy,
2. 在Security.xml中对FilterChain进行了详细定义。
3. 其中AuthenticationManager的Providers包含了DaoAuthenticationProvider,而此Provider的UserDetailsService引用了userDao。
4. 在applicationContext-hibernate.xml中定义了userDao,是org.appfuse.dao.hibernate.UserDaoHibernate。
5. 而UserDaoHibernate实现了UserDetailsService接口,主要是实现了loadUserByUsername(String)方法,其中参数是String类型的用户名,而返回一个UserDetails类型的对象。
6. 在LoadUserByUsername方法中,使用getHibernateTemplate().find来获得了一个org.appfuse.model.User类型的List,其中User类型实现了UserDetails。

posted @ 2007-03-07 23:46 云自无心水自闲 阅读(1325) | 评论 (2)编辑 收藏

    Acegi提供了一个优秀的基于J2EE企业级应用的安全认证机制。尤其是对于Spring框架的支持,在J2EE的企业软件开发解决方案中是领先的。
    来看一下Acegi的重要的共享组件。如果组件是框架的核心而且一旦缺少这些组件框架将无法运转,那么这些组件可以称为是“共享”的。这些Java类型是系统其他部分的基础,所以理解他们是十分重要的,虽然你可以并不会直接与之互动。

    其中最基础的对象是SecurityContextHolder,用于存储应用安全上下文的细节信息。缺省情况下,SecurityContextHolder使用ThreadLocal来存储信息,这意味着安全上下文对于同一个线程的所有方法都是有效的。有一些应用不适合使用ThreadLocal,比如:一个Swing的客户端可能希望所有JVM所有的线程都使用相同的安全上下文。对于这种情况,你可以用SecurityContextHolder.MODE_GLOBAL。你可以把SecurityContextHolder从缺省模式MODE_THREADLOCAL改变为MODE_GLOBAL。

    在SecurityContextHolder中存储了与应用互动的规则。Acegi使用Authentication对象来表示这些信息。这并不是需要你自己创建Authentication对象,更通常的做法是查询到一个Authentication对象。举例如下,在应用的任何一个地方都可以这样使用:

Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if( obj instanceof UserDetails){
 String username=((UserDetails)obj).getUsername();
}else{
 String username=obj.toString();
}

    上面这段代码介绍了不少有意思的对象和关系。首先,大家会发现在SecurityContextHolder和Authentication之间存在着一个即时对象:SecurityContext,SecurityContextHolder.GetContext()返回的类型就是SecurityContext。Acegi有数个SecurtiyContext的实现。

    另一个值得注意的是我们从Authentication中获得了一个规则。这个规则的类型是:Object。大多数情况下,我们可以把它强制性转换成UserDetails对象。UserDetails是Acegi的核心接口。它代表了一种规则,但是经过了应用相关的扩展。可以把UserDetails想象成为应用数据库与Acegi的SecurityContextHolder需要的两者之间的适配器(Adapter)。如果作为应用自己的数据库的代表,那么可以把UserDetails强制性转换为其原始类,这样,你就可以调用其中的业务方法(比如:getEmail()等等)。

    那么,为什么要提供一个UserDetails对象呢?是这样的:有一个特殊的接口:UserDetailsService,这个接口只有一个方法,这个方法接收一个String类型的表示用户名的参数,返回UserDetails对象。大多数认证提供provider装配一个代理到UserDetailsService上。UserDetailsService被用于创建SecurityContextHolder中存储的Authentication对象。Acegi中提供了若干个UserDetailsService的实现,一个使用内存Map,一个用JDBC。大多数用户倾向于写一个自己的实现,通常是使用DAO。不论UserDetailsService返回的是什么,都可以通过SecurityContextHolder获得。


    Authentication提供另一个重要的方法是getAuthorites()。这个方法返回一个GrantedAuthority对象的数组。GrantedAuthority是授权给的认证。这个认证通常指的是“角色”,比如:ROLE_ADMINISTRATOR或者ROLE_HR_SUPERVISOR。这些角色需配置用于web认证,方法认证和域对象认证。如果Acegi的其他部分希望看到这些认证,那么UserDetailsService返回GrantedAuthority对象即可。

    最后,有时你需要在HTTP requests之间传递SecurityContext,有时每次请求都需要重新认证。那么可以使用HttpSessionContextIntergrationFilter,这是用于在HTTP Request之间传递SecurityContext的东东。就象名称所表示的那样:HttpSession用于存储这些信息。但是你不需要直接操作HttpSession。

posted @ 2007-03-07 13:00 云自无心水自闲 阅读(1633) | 评论 (0)编辑 收藏

1、编译部署成功后,在地址栏中输入:http://localhost:8080/appfuse,即可看到首页-登录页

2、第一个页面是login.jsp,此页面使用include包含了taglibs.jsp和loginForm.jsp
其中taglibs.jsp是一个公共页面,定义了页面中使用到的taglibs
而loginForm.jsp则是用户登录Form定义的页面

3、现在会发现一点:此时浏览器中显示的内容比login.jsp的内容要多,包括最上方的语言切换行,下面的标题行,最下文的版本信息行等。
这是因为Appfuse使用了Sitemesh的Decorator。
在WEB-INF目录下,有两个Xml文件:sitemesh.xml和decorators.xml
在Web.xml中定义了sitemesh的Filter
在decorators目录下有default.jsp这个布局文件。
Sitemesh的作用就是对定义的文件进行装饰。
在Appfuse中,会对所有的文件作为Body安放到default.jsp这个布局文件中。

4、查看login.jsp,发现他的Form的Action是比较奇怪的:j_security_check
这并不是一个真实存在的URL
在security.xml中可以发现,这个是authenticationProcessingFilter的filterProcessesUrl属性
这就是Spring中使用Acegi安全认证服务,在Appfuse1.9.4中使用的是Acegi的基于表单的身份认证
filterProcessUrll告诉AuthenticationProcessingFilter应该拦截哪个URL
属性authenticationFailureUrl指定当身份验证失败时用户应该被送往哪里
defaultTargetUrl定义登陆成功时转向的页面

5、用户登录成功后,转到defaultTargeUrl所指定的路径:/ 根路径
而此路径的Welcome file是index.jsp, 而index.jsp又redirect到了mainMenum.html
因此会显示mainMenu.html页面。

posted @ 2007-03-04 23:08 云自无心水自闲 阅读(1583) | 评论 (0)编辑 收藏

http://www.graniteds.org/confluence/display/INTRO/Granite+Data+Services+Overview

支持AMF3

  • 支持AMF3
  • EJB3服务的透明externalization机制,参见Flex2的开发文档
  • http://www.adobe.com/livedocs/flex/201/html/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Book_Parts&file=ent_services_config_097_11.html
    在Flex的序列化和反序列化过程中,只能传递public的,非静态的属性,如果要序列化此部分内容在Flex与Java间传递,必须使用externalization机制

  • ActionScript3的Beans的Lazy Initialize
  • EJB3实体Bean到ActionScript3的类的代码生成(计划中)
  • POJO服务(远程调用简单Java类的公共方法)
  • 一系列Flex组件用于复杂的数据结构(计划中)、
  • posted @ 2007-03-01 22:22 云自无心水自闲 阅读(865) | 评论 (0)编辑 收藏

    (续昨日)
    页面乱码的问题,今天看了一下,是资源文件的问题。
    原来appfuse提供的资源文件没有用native2ascii处理过。

    学习心得:
    1、Appfuse的页面基本上都包含了commom\taglibs.jsp,在此文件中定义了taglib
    在Tomcat5以上的版本中,不再需要在Web.xml中定义Taglib了,只需要在WEB-INF\lib目录下放置standard.jar就可以了。

    posted @ 2007-03-01 00:49 云自无心水自闲 阅读(876) | 评论 (0)编辑 收藏

    目前网上有一些介绍如何在Eclipse中应用Appfuse的文章,但因为Appfuse本身附带了强大的Ant任务,Eclipse在其中如Raible据说更多充当的是文本编辑器的作用。编译/部署都使用Ant完成,也比较方便。但是,无法跟踪调试源码,有些不爽,因此,想把Appfuse进行提炼完全整合到Eclipse中。

    一、运行Ant New
    1. 不知道为什么,此项任务会到jre的lib目录下寻找tools.jar,没有仔细地查找原因,简单地把jdk\lib\tools.jar拷贝过来
    2. 需要定义CATALINA_HOME这个环境变量
    OK, 完成上述两个步骤后,Ant命令执行成功,命令过程中有数个选项可以选择,比如:应用名称,数据库名称,Package名称,这些关系都不大。
    有一个选项比较重要一些,是询问使用何种Web框架,有webwork, tapestry, spring, jsf等,我也是使用的默认选项:struts.

    二、启动MySql数据库,运行Ant setup-db
    在数据库中生成mydb数据库,以及数据表

    三、在Eclipse中建立Tomcat Project名字与Ant New中输入的应用一致。

    四、将common, decorators, images, MATA-INF, scripts, styles这几个目录从ant new生成的目录复制到Eclipse项目的目录中.
    将web-inf\pages目录下的jsp文件拷贝到Eclipse相同目录下。

    五、运行ant webdoclet, 生成Form目录下的3个Form的java源文件,以及model目录下的2个hibernate的xml映射文件

    六、将org.appfuse.webapp,org.appfuse.sercies, org.appfuse.dao以及model和util目录所包含的所有Java源文件复制到Eclipse项目所在的文件夹web-inf\src中。

    七、将lib复制到web-inf\lib目录下
    acegi-security-1.0.2.jar
    activation.jar
    antlr-2.7.6.jar
    antlr.jar
    asm.jar
    aspectjweaver-1.5.2.jar
    cglib-2.1.3.jar
    clickstream-1.0.2.jar
    commons-beanutils.jar
    commons-codec-1.3.jar
    commons-collections.jar
    commons-dbcp.jar
    commons-digester.jar
    commons-fileupload.jar
    commons-io.jar
    commons-lang.jar
    commons-logging-1.1.jar
    commons-pool.jar
    commons-validator.jar
    displaytag-1.1.jar
    dom4j-1.6.1.jar
    dwr.jar
    ehcache-1.2.3.jar
    hibernate3.jar
    itext-1.4.jar
    jakarta-oro.jar
    jstl.jar
    jta.jar
    log4j-1.2.11.jar
    mail.jar
    mysql-connector-java-5.0.3-bin.jar
    oscache-2.3.2.jar
    sitemesh-2.2.1.jar
    spring.jar
    standard.jar
    struts-el.jar
    struts-menu-2.4.2.jar
    struts.jar
    urlrewrite-3.0-beta.jar
    velocity-1.4.jar
    velocity-tools-view-1.1.jar

    八、启动Sysdeo Tomcat, 在浏览器中输入http://locallhost:8080/myapp, 出现页面,输入mraible/tomcat,登录成功。

    九、还有一个问题就是目前所有的页面都是乱码,明天再解决了,今天要睡觉了。

     

    posted @ 2007-02-28 00:52 云自无心水自闲 阅读(2953) | 评论 (2)编辑 收藏

    最近在Oracle网站上下载一个Oracle 10g安装了一下,只有一张盘,而且安装时还有一个便捷的选项,非常方便。
    可以安装完毕后,使用的时候却遇到了麻烦:如果只是本机的访问 sqlplus system/manager这样是没有问题的。
    但是如果使用 sqlplus system/manager@orcl的时候却会报ora-12514的错误。

    解决方法:
    1. 打开<OracleHome>/network/admin/listener.ora文件,找到:

       SID_LIST_LISTENER =
       (SID_LIST =
         (SID_DESC =
           (SID_NAME = PLSExtProc)
           (ORACLE_HOME = D:\oracle\product\10.2.0\db_1)
           (PROGRAM = extproc)
         )
       )
      2. 添加:
                (SID_DESC =
           (GLOBAL_DBNAME = ORACLE)
           (ORACLE_HOME = D:\oracle\product\10.2.0\db_1) 
           (SID_NAME = ORACLE)
          )
      3. 最后变成:
     SID_LIST_LISTENER =
       (SID_LIST =
         (SID_DESC =
           (SID_NAME = PLSExtProc)
           (ORACLE_HOME = D:\oracle\product\10.2.0\db_1)
           (PROGRAM = extproc)
         )
         (SID_DESC =
           (GLOBAL_DBNAME = ORACLE)
           (ORACLE_HOME = D:\oracle\product\10.2.0\db_1) 
           (SID_NAME = ORACLE)
          )
       )
      4. 保存文件,重启服务中的TNSListener,OK!

    PS: Oracle10g有一个好处:不再与Tomcat的端口冲突了。原来的Oracle9i安装完成后,8080端口就会被占用,一般都需要改tomcat的端口。现在终于轻松了。

    posted @ 2007-02-12 23:45 云自无心水自闲 阅读(273806) | 评论 (50)编辑 收藏

    Flex是一个事件驱动的编程模型, 任何事情的发生, 其背后必然存在一个事件. 而开发者第一次看到MXML时, 很难体会到一个Xml标记的应用的事件流和实例化的生命周期. 这个对于HTML和Flash的开发者尤其会感到困惑, 因为其熟悉的方式与Flex的一点也不相似. HTML的实例化是从上到下的, Flash的执行是从Frame0开始一帧帧运行的. 而Flex则又有不同.

    从我们开始学习Flex时, 我们就需要了解事件流和MXML的实例化. 我非常困惑因为我实在难以理解什么样的事件会被触发或者事件什么时候会被触发. 关键是要理解事件的基础并亲自观察事件流的初始化.


    我们来看一个简单的MXML的应用.

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application
        xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="absolute"
        backgroundGradientColors="[#67cbff, #fcffff]"
        color="#000000"
        fontSize="12"   
        preinitialize="report( event , 'preinitialize' )"
        initialize="report( event , 'initialize' )"
        creationComplete="report( event , 'creationComplete' )"
        applicationComplete="report( event , 'applicationComplete' )"
        >
       
        <mx:Script>
            <![CDATA[   
                       
                [Bindable]
               
                public var outTextData:String="";
               
                public function report( event:Event , value:String ):void
                {
                    outTextData += String( flash.utils.getTimer() ) + 'ms >> '
                    + event.currentTarget + '.' + value + '\n';   
                }
               
            ]]>
        </mx:Script>
       
        <mx:TextArea
            id="outTextArea"
            text="{ outTextData }"
            right="10" left="10" top="50" bottom="10" alpha="0.5"
            wordWrap="false"
            initialize="report( event , 'initialize' )"
            creationComplete="report( event , 'creationComplete' )"
            />
       
        <mx:Button
            y="10" height="30" left="168" width="150"
            id="HelloButton"
            label="Say Hello"
            initialize="report( event , 'initialize' )"
            creationComplete="report( event , 'creationComplete' )"
            rollOver="report( event , 'rollOver' )"
            rollOut="report( event , 'rollOut' )"
            click="report( event , 'click > Hello!' )"
            />
           
        <mx:Button
            id="GoodByeButton"
            label="Say Goodbye"
            y="10" left="10" height="30" width="150" color="#000000"
            initialize="report( event , 'initialize' )"
            creationComplete="report( event , 'creationComplete' )"
            click="report( event , 'click > Goodbye!' )"
            />
           
        <mx:Button
            id="ClearButton"
            label="Clear"
            y="10" left="326" height="30" color="#000000" right="10"       
            initialize="report( event , 'initialize' )"
            creationComplete="report( event , 'creationComplete' )"
            click="outTextData='';report( event , 'click' )"
             />
       
    </mx:Application>


    这个应用运行时, 输出了实例流程和事件流. 这校我们就能够看到所有事件的触发顺序. 可以发现应用启动后, 事件的顺序是一定的. 下面是输出的内容:

    167ms >> EventFlow0.preinitialize
    183ms >> EventFlow0.outTextArea.initialize
    187ms >> EventFlow0.HelloButton.initialize
    188ms >> EventFlow0.GoodByeButton.initialize
    189ms >> EventFlow0.ClearButton.initialize
    189ms >> EventFlow0.initialize
    243ms >> EventFlow0.outTextArea.creationComplete
    243ms >> EventFlow0.HelloButton.creationComplete
    243ms >> EventFlow0.GoodByeButton.creationComplete
    244ms >> EventFlow0.ClearButton.creationComplete
    244ms >> EventFlow0.creationComplete
    246ms >> EventFlow0.applicationComplete

    一旦applicationComplete事件触发后, 组件就会在鼠标事件派发后触发自己的事件.

    1807ms >> EventFlow0.HelloButton.rollOver
    2596ms >> EventFlow0.HelloButton.rollOut
    2954ms >> EventFlow0.HelloButton.rollOver
    3170ms >> EventFlow0.HelloButton.rollOut
    3543ms >> EventFlow0.HelloButton.rollOver
    4052ms >> EventFlow0.HelloButton.click > Hello!
    4267ms >> EventFlow0.HelloButton.click > Hello!
    4474ms >> EventFlow0.HelloButton.click > Hello!
    4569ms >> EventFlow0.HelloButton.rollOut
    4907ms >> EventFlow0.GoodByeButton.click > Goodbye!
    5130ms >> EventFlow0.GoodByeButton.click > Goodbye!

     

    posted @ 2007-02-11 23:50 云自无心水自闲 阅读(3914) | 评论 (1)编辑 收藏

     

    在ActionScript 3中,你会发现在flash.utils包中有一系列函数提供了反射的功能。主要包含以下功能:

        * 确定对象的类
        * 获取类的成员、方法、构造函数、父类的信息
        * 确定接口声明的常数和方法
        * 在运行时根据类名创建类的实例
        * 在运行时根据成员名称获取或者设置对象成员的值
        * 在运行时根据方法名称,调用对象的方法

    你可以使用类似于"describeType"之类的功能,它返回一个Xml对象。举一个例子:

    package {
        import flash.display.Sprite;
        import flash.utils.describeType;
      
        public class DescribeTypeExample extends Sprite {
            public function DescribeTypeExample() {
                var child:Sprite = new Sprite();
                var description:XML = describeType(child);
                trace(description..accessor.@name.toXMLString());
            }
        }
    }

    如果你想进一步,根据类名创建对象的实例,我们可以使用"getDefinitionByName()"

    package {
        import flash.display.DisplayObject;
        import flash.display.Sprite;
        import flash.utils.getDefinitionByName;

        public class GetDefinitionByNameExample extends Sprite {
            private var bgColor:uint = 0xFFCC00;
            private var size:uint = 80;

            public function GetDefinitionByNameExample() {
                var ClassReference:Class = getDefinitionByName(“flash.display.Sprite”) as Class;
                var instance:Object = new ClassReference();
                instance.graphics.beginFill(bgColor);
                instance.graphics.drawRect(0, 0, size, size);
                instance.graphics.endFill();
                addChild(DisplayObject(instance));
            }
        }
    }

    尽管这是一些非常方便的方法,但是在FlashPlayer中使用反射还是会有许多的限制,因为缺乏运行时的动态源码编译。上面的功能对于那些在内建的类,比如:Sprite类来说无疑是有用的,但是对于自定义类来说,我们会遇到很多麻烦。比如:

    package {
        import com.customtypes.string; // Custom String Implementation Class
        import flash.utils.getDefinitionByName;

        public class GetDefinitionByNameExample {
            public function GetDefinitionByNameExample() {
                var ClassReference:Class = getDefinitionByName(“com.customtypes.string”) as Class;
                var instance:Object = new ClassReference();
                instance.customParameter = “my parameter”;
            }
        }
    }

    尽管我们使用了import语句,但是"getDefinitionByName()"还是会失败。原因上面已经说过了,在运行时编译源代码是不允许的。也许以后可以。在目前情况下,要实现上述功能,至少要在代码中初始化一个类的实例。也就是声明一个类的实例:

    var customType : com.customtypes.string;

     

    posted @ 2007-02-10 14:32 云自无心水自闲 阅读(1238) | 评论 (4)编辑 收藏

    仅列出标题
    共29页: First 上一页 18 19 20 21 22 23 24 25 26 下一页 Last