计算机程序虚拟的人生
虚拟世界中的游魂

第一次接触mina这个物件,在网上看了一些相关的资料,同时也参考了别人的一些分析mina的心得和方式!
mina是何物?
Mina是一个用于开发高性能和高可用性的网络应用程序基础架构,它封装了底层的I/O和线程并发等复杂工作。
Mina主要是基于java NIO类库开发;采用非阻塞方式的异步传输、事件驱动、批量数据传输;支持TCP、UDP网络协议

首先从服务器端启动NioSocketAcceptor对象进行分析。
1、实例化DefaultSocketSessionConfig会话配置器和异步传输NioProcessor处理器
2、实例化AbstractPollingIoAcceptor构造器同时实例化SimpleIoProcessorPool处理器池
      --〉在SimpleProcessorPool中初始化执行器<线程池>,然后初始化一个IoProcessor对象数组,长度为3,最后将处理器对象放入到IoProcessor数组中
      --〉处理化传输带元数据
      --〉初始化服务监视器
      --〉初始化异常监视器
3、初始化过滤链
4、初始化选择器

架构介绍

应用结构图

深入分析结构图

mina的基本应用可以分为3层:
1、I/O Serivce:实际执行I/O层
2、I/OFilter chain:数据过滤和转换层,主要是把字节转换为需要的数据格式或者反过来处理
3、I/OHandler:业务处理层
创建Mina应用分为3部分:
1、创建I/O 2、创建过滤链
3、创建I/O业务处理

posted @ 2009-09-04 12:25 小兄弟(Robbins) 阅读(1402) | 评论 (1)编辑 收藏
 
 Dojo介绍
       Dojo 是一个用javascript语言实现的开源DHTML工具包。它是在几个项目捐助基础上建立起来的(nWidgets, Burstlib, f(m)), 这也是为什么叫它a \"unified\" toolkit的原因。Dojo的目标是解决开发DHTML应用程序遇到的那些,长期存在 、历史问题。historical problems with DHTML 跨浏览器问题。Dojo让你更容易 使web页面具有动态能力,或在任何稳健的支持javascript语言的环境中发挥作用。

a、利用dojo提供的组件,你可以提升你的web应用程序可用性、交互能力以及功能上的提高;
b、你也可以 更容易的建立degradeable user interfaces ??,dojo提供小巧的 widgets ,animate transitions;
c、利用它的低级APIs和可兼容的代码,写出轻便的、单一风格(复杂)的javascript代码,Dojo的 event system, I/O APIs, and generic language enhancement form the basis of a powerful programming environment.
d、通过Dojo提供的工具,你可以为你的代码写命令行式的单元测试代码。
e、the Dojo package system使你自己的代码更容易维护,偶合性更低。

Dojo通过很少的代码完成了以上的功能。(以后可能我详细说说dojo的package system ,只需要三个js文件)。当你写脚本时,只需要包含很少的js文件(大小)。也可以选择的(包含)下载dojo提供的庞大的功能。Dojo provides MultiplePointsOfEntry, InterpreterIndependence, ForwardLookingAPIs, and focuses on ReducingBarriersToAdoption.
  dojo试图建立一种新的标签语言DojoML。目标是,在DojoML和javascript脚本语言不变的情况下,用不同的render方式展示数据, Renderings may be made available in several rendering contexts (such as SVG, or perhaps even the desktop or Flash)。(比较美好啊)更进一步,the DojoML 剖析器可以接受html和svg为输入,容易的建立DegradeableResponsiveApplications。

第一部分  安装
第一个小节  怎么安装Dojo Toolkit
 Dojo在磁盘上只是一堆文件,它不需要特殊的设置,它可以通过以下三种途径获得:
 1、可以从google的内容分布网络获得
   加载的方法可以参考http://code.google.com/intl/zh-CN/apis/ajaxlibs/documentation/index.html#dojo
 2、.在你自己的服务器上使用Dojo
  a、下载最新的dojo包,地址:http://dojotoolkit.org/downloads;目前最新的包为1.3.1
  b、解压下载的压缩文件
         --dojo-release-1.3.1-src
            ----dijit
            ----dojo
            ----dojox
            ----util
  c、可以通过D:\Apache-Source\dojo\1.3.1\dojo-release-1.3.1-src\dojo-release-1.3.1-src\dijit\themes\themeTester.html 这样的路径来查看相关的JS例子
3、每日构建代码
   你可以通过SVN地址获得
For instance, Dojo Core repository is:
http://svn.dojotoolkit.org/src/dojo/trunk

There are two versions of this view: anonymous and committer.

For users (readonly):
http://svn.dojotoolkit.org/src/view/anon/all/trunk

For committers (read/write):
https://svn.dojotoolkit.org/src/view/committer/all/trunk

第二部分 Ajax
第一个小节 ajax
a、ajax and Dojo
1)XHR选项
例子:

// post some data, ignore the response:
dojo.xhrPost({
form: "someFormId", // read the url: from the action="" of the <form>
timeout: 3000, // give up after 3 seconds
content: { part:"one", another:"part" } // creates ?part=one&another=part with GET, Sent as POST data when using xhrPost
});
// get some data, convert to JSON
dojo.xhrGet({
url:"data.json",
handleAs:"json",
load: function(data){
for(var i in data){
console.log("key", i, "value", data[i]);
}
}
});

2)XHR回调
有三种方法可以附加到XHR选择对象,以确定当数据回调时该怎么做。


posted @ 2009-06-29 14:20 小兄弟(Robbins) 阅读(368) | 评论 (0)编辑 收藏
 
   如果不输入绝对的URL访问地址,例如:URL=http://localhost:8080/petstore;则Glassfish能够自动的搜索项目中是否存在index.html或者index.jsp页面作为入口页面。 
   CatalogFacade对象在服务器启动时被实例化,然后将实例化的CatalogFacade对象放置到ServletContext环境中,这样可以直接从ServletContext环境中取得CatalogFacade对象进行相关数据方法的调用。
   index.jsp中涉足到一个js框架DOJO,这个需要进一步的学习。
   对数据的增、删、改、查主要用到了JPA来处理。
posted @ 2009-06-29 12:34 小兄弟(Robbins) 阅读(341) | 评论 (0)编辑 收藏
 
    由于PetStore涉及到了jsf,那就没有办法了,还是先看看JSF
--------------------------------------------------------------------------
    JSF是有JCP(JAVA Community Process)团队研发出来的一套标准,并在2004年3月发表JavaServer Faces1.0成果。

    看到一篇内容对初学者目前jsf的了解很重要:注意这篇文章是2006年的内容
       JSF1.1 JSF1.2 myfaces,oracle ADF,ajax4jsf facelets, 它们究竟是什么,有什么关系呢?

JSF1.1 1.2 都是 JSF 的标准,定义例如接口、规范( JSF 是面向接口编程的),必须通过实现才能被我们所使用,而实现包括有 JSF RI(Reference Implementation) ,还有 myfaces core1.1.4 的实现等。 JSF RI SUN JSF 的实现,相对来说兼容性比较好,也比较稳定(因为 1.1 已经很久没更新过了,已经转向 1.2 去了),而 myfaces 更新比较快,功能也比较多一点,初学的推荐 JSF RI1.1 就可以了, 1.2 需要新的 servlet2.5/jsp2.1 以及服务器支持,现在还不稳定。

myfaces ,它是一个大的项目,下面有几个子项目,分别是 myfaces core, sandbox ,tabago,tomahawk ,(奇怪的名字,好难说,我简称它为 TOM ),还有一个新的 ADF Faces (跟 oracle adf 有关,应该是兼容整合 adf 的功能吧)。 Tabago,tom 都是组件库, tabago 比较好玩的是支持换肤,还有一些支持 ajax 的组件, TOM 则是一个丰富的增强组件库,大概有三十个之多,例如 TREE TAB 等等。 Sandbox 是测试用的。

Oracle ADF oracle jsf 做的一个大型的组件库,以前是收费的,现在开源了,我没用过,不好说。

Ajax4jsf 是为 jsf 提供 AJAX 支持的一个标签库,使用它提供的标签,就能在原有的 JSF 程序上轻易的加上 AJAX 的功能,而且不用写任何 Javascript

Facelets 这个是很激动人心的一个框架,有了这个框架才把 JSF 的组件化发挥出来,通过模板的方式来组合成我们所需要的组件,而且可以不使用 <h:input> 这样的标签库,而用 <input type=”text” jsfc=”h:input”> 这样的方式来使用组件,这样就可以方便的使用 UI 可视化工具去开发我们的 WEB 程序。这个框架我会在以后的文章中详细的说,以及和 jsp2.0 的模板功能作对比。
--------------------------------------------------------------------------------
   JSF的session超时问题会在页面上抛出如下异常:
javax.faces.application.ViewExpiredException: viewId:/pages/index.faces - View /pages/index.faces could not be restored.
 at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:185)
 at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)
 at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
 at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
 at java.lang.Thread.run(Unknown Source)
    解决方案:
          在web.xml中添加如下代码:
  <error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/pages/SessionRefire.jsp</location>
  </error-page>

----------------------------------------------------
注意:所有的JSF标签一定要包含在<f:view></f:view>这个节点中,不然会报一下问题:

javax.servlet.ServletException: Component javax.faces.component.UIViewRoot@f1fad1 not expected type.  Expected: javax.faces.component.UIOutput.  Perhaps you're missing a tag?
javax.faces.webapp.FacesServlet.service(FacesServlet.java:256)


 

posted @ 2009-06-26 09:19 小兄弟(Robbins) 阅读(440) | 评论 (0)编辑 收藏
 
 Hibernate本身自带的连接池算法不成熟,并不适合用于产品系统或者性能测试。出于最佳性能和稳定性考虑你应该使用第三方连接池。
比如使用:C3PO。
C3PO是一个随Hibernate一同分发的开源JDBC连接池。
posted @ 2009-06-25 15:17 小兄弟(Robbins) 阅读(141) | 评论 (0)编辑 收藏
 

使用HTML5构建下一代的Web Form

作者 蒋博 发布于 2009年6月22日 上午4时52分

社区
Architecture,
Java
主题
编程,
语言
标签
W3C,
标识语言

HTML5 是由 WHATWG (Web Hypertext Application Technology Working Group) 发起的,最开始的名称叫做Web Application 1.0,而后这个标准吸纳了Web Forms 2.0的标准,并一同被W3C组织所采用,合并成为下一代的HTML5标准。

前言

HTML语言作为如今编程最为广泛的语言,具有易用、快捷、多浏览平台兼容等特点,但是随着时代的进步,HTML的标准却停滞不前,这一次还在不断开发中的HTML5标准的更新可以说给这门标记语言带来了新的生命力。本文将着重讨论HTML5中的Web Forms 2.0, 即表单的部分。

表单是网页中常见的控件(集)。小到网站注册登录,大到一个企业的数据管理系统,都基本上有表单的身影。表单之所以如此重要,主要是因为它担负大量的用户和网页后台数据更新交互的任务。Web开发人员,对于网页表单可以说又爱又恨,爱的是它方便的收集、组织数据的功能,恨的是它的功能很大程度上也就仅此而已。一些在最终网站用户看起来稀松平常的功能,比如说输入类型检查、表单校验、错误提示等等,开发人员无不需要花费大量精力利用 JavaScript和DOM编程来满足这些天然所需的功能点,而随着Ajax的流行,出现的一些JavaScript的工具库,比如Dojo, YUI等都提供了方便的JavaScript Widget或者API来减轻开发人员的负担。

HTML5的表单新特性

HTML5 Web Forms 2.0是对目前Web表单的全面提升,它在保持了简便易用的特性的同时,增加了许多内置的控件或者控件属性来满足用户的需求,并且同时减少了开发人员的编程。在我看来,HTML5 主要在以下几个方面对目前的Web表单做了改进:

  • 新的控件类型
    • 还在为类型检查犯愁吗,还在为那一长串看不太明白的检验输入的正则表达式而苦恼吗,HTML5提供的一系列新的控件将天然的具备类型检查的功能。比如说URL输入框,Email输入框等。
      <input type="url"></input>
      <input type="email"></input>
    • 当然还有非常重要的日期输入框,要知道使用JavaScript和CSS来“手工”制作一个日期输入框还是非常花功夫的,类似Dojo,YUI这样的类库也无不在这个widget上面大做文章。
      <input type="date"></input>
    • 作为我痛苦记忆的一部分,我经常记得我们开发人员要为一个select下拉别表动态的添加非常多的选项,这些选项大多数都是来自数据库,比如说国家、省市列表等等。这个事情非常繁琐。HTML5将支持data属性,为select控件外联数据源!
      <select data="http://domain/getmyoptions"></select>
  • 改进的文件上传控件,你可以使用一个控件上传多个文件,自行规定上传文件的类型(accept),你甚至可以设定每个文件最大的大小(maxlength)。你看出它和一般操作系统提供的文件上传控件的区别了吗,反正我觉得基本一致了。在HTML5应用中,文件上传控件将变得非常强大和易用。
  • 重复(repeat)的模型,HTML5提供一套重复机制来帮助我们构建一些重复输入列表,其中包括一些诸如 add、remove、move-up,move-down的按钮类型,通过这一套重复的机制,开发人员可以非常方便的实现我们经常看到的编辑列表,这是一个很常见的模式,我们可以增加一个条目、删除某个条目、或者移动某个条目等等。
  • 内建的表单校验系统,HTML5为不同类型的输入控件各自提供了新的属性,来控制这些控件的输入行为,比如我们常见的必填项required属性,以及为数字类型控件提供的max、min等。而在你提交表单的时候,一旦校验错误,浏览器将不执行提交操作,而会显示相应的检验错误信息。
    <input type="text" required></input>
    <input type="number" min=10  max=100></input>
  • XML Submission,我们一般常见的是form的编码格式是application/x-www-form-urlencoded。开发人员都很清楚这种格式,数据送到服务器端,可以方便的存取。HTML5将提供一种新的数据格式:XML Submission,即application/x-www-form+xml。简单的举例说,服务器端将直接接收到XML形式的表单数据。
    <submission>
        <field name="name" index="0">Peter</field>
        <field name="password" index="0">password</field>
    </submission>

实例分析

我将利用HTML5新的表单系统, 做一个简单的用户注册的界面,包括用户名,密码,出生日期,保密问题等内容,代码如下:

<! doctype html>
<html>
<head>
<style>
p label {
width: 180px;
float: left;
text-align: right;
padding-right: 10px
}
table {
margin-left: 80px
}
table td {
border-bottom: 1px solid #CCCCCC
}
input.submit {
margin-left: 80px
}
</style>
</head>
<body>
<form action='/register' enctype="application/x-www-form+xml" method="post">
<p>
<label for='name'>ID(请使用Email注册)</label>
<input name='name' required type='email'></input>
</p>
<p>
<label for='password'>密码</label>
<input name='password' required type='password'></input>
</p>
<p>
<label for='birthday'>出生日期</label>
<input type='date' name='birthday' />
</p>
<p>
<label for='gender'>国籍</label>
<select name='country' data='countries.xml'></select>
</p>
<p>
<label for='photo'>个性头像</label>
<input type='file' name='photo' accept='image/*' />
</p>
<table>
<thead>
<td><button type="add" template="questionId">+</button> 保密问题</td>
<td>答案</td>
<td></td>
</thead>
<tr id="questionId" repeat="template" repeat-start="1" repeat-min="1" repeat-max="3">
<td><input type="text" name="questions[questionId].q"></td>
<td><input type="text" name="questions[questionId].a"></td>
<td><button type="remove">删除</button></td>
</tr>
</table>
<p>
<input type='submit' value='send' class='submit' />
</p>
</form>
</body>
</html>

由于目前HTML5标准仍然在开发中,不同的浏览器对HTML5特性的支持都相当有限。其中Opera在表单方面支持得比较好,本实例在Opera9上运行一切正常,效果图如下:

这个实例运用了一些HTML5的新的表单元素,比如email类型的输入框(ID),日期类型的输入框(出生日期)。并且使用了重复模型来引导用户填写保密问题,而在个性头像的上传中,通过限制文件类型,方便用户选择图片进行合乎规范的内容上传。而用户选择国籍的下拉选择输入框中,采用的是外联数据源的形式,外联数据源使用coutries.xml,内容如下:

<select xmlns="http://www.w3.org/1999/xhtml">
<option>China</option>
<option>Japan</option>
<option>Korea</option>
</select>

并且form的enctype是application/x-www-form+xml,也就是HTML5的XML提交。所以一旦form校验通过,form的内容将会以XML的形式提交。你还会发现,在ID输入框如果没有值,或者输入了非email类型的字符串时,一旦试图提交表单,就会有提示错误的信息出现,而这都是浏览器内置的。

结语

HTML5对表单控件的更新,无疑是很振奋人心的。本文描述了一部分表单的新特性,还有一部分新特性同样很令人期待。相信随着标准的深入开发以及浏览器对HTML5支持程度的进一步提升,设计一个简单易用的表单的工作,将变得非常轻松。

参考资料

  1. W3C HTML5 规范: http://www.w3.org/TR/html5/
  2. HTML5 与 HTML4的差异:http://www.w3.org/TR/html5-diff/
  3. Opera dev: Improve your forms with HTML5: http://dev.opera.com/articles/view/improve-your-forms-using-html5/
  4. Comparison of layout engines(HTML5):
    http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(HTML_5)

关于作者

蒋博,主要从事Web前端技术的开发工作,在Web开发与性能分析以及敏捷实践等领域有较丰富的经验。对HTML5的发展以及各种 JavaScript类库有比较浓厚的兴趣,经常关注社交型的网站发展情况,平常喜欢听音乐,看一些历史类书籍。(本文仅代表个人观点,与公司立场无关。)


给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家加入到InfoQ中文站用户讨论组中与我们的编辑和其他读者朋友交流。

posted @ 2009-06-24 09:04 小兄弟(Robbins) 阅读(183) | 评论 (0)编辑 收藏
 
    看完这本书给我的感觉,比较实在,基本上对spring有个初步的认识。
    接下来我会接着看<Spring参考手册>,这样更好的理解Spring这个轻量级的框架。
    
    从纵向第三方框架集成方面讲
    1、 web层的集成
           spring对于web层集成外部框架有:Struts、webwork、Tapestry、JSF、Dinamica、VRaptor
    2、DAO层的集成
            spring对于DAO层集成外部框架有:Hibernate、Ibatis、JDO

    事务处理上,Spring可以利用不同的事务管理对象进行事务上的配置,根据不同的数据层环境而定。
posted @ 2009-06-23 21:44 小兄弟(Robbins) 阅读(174) | 评论 (0)编辑 收藏
 
  Spring的容器事务主要是基于动态AOP来处理。
 下面这段xml配置片断展示了Spring中的事务设定方式:
<beans>
     <bean id="dataSource"
                class="org.apache.commons.dbcp.BasicDataSource"
                destroy-method="close">
              <property name="driverClassName">
                       <value>org.gjt.mm.mysql.Driver</value>
              </property>
              <property name="url">
                        <value>jdbc:mysql://localhost/sample</value>
             </property>
             <property name="username">
                       <value>user</value>
             </property>
             <property name="password">
                        <value>mypass</value>
              </property>
       </bean>
      <bean id="transactionManager"
                 class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                 <property name="dataSource">
                      <ref local="dataSource" />
                 </property>
       </bean>
        <bean id="userDAO" class="net.xiaxin.dao.UserDAO">
                  <property name="dataSource">
                        <ref local="dataSource" />
                 </property>
         </bean>
        <bean id="userDAOProxy"
                   class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                 <property name="transactionManager">
                          <ref bean="transactionManager" />
                 </property>
                 <property name="target">
                         <ref local="userDAO" />
                 </property>
                  <property name="transactionAttributes">
                         <props>
                            <prop key="insert*">PROPAGATION_REQUIRED</prop>
                            <prop key="get*">
                               PROPAGATION_REQUIRED,readOnly
                             </prop>
                           </props>
                    </property>
             </bean>
</beans>

------------------------------------------------------------------------------------------------------------------------------------------------------------------
EJB事务处理与Spring事务处理的区别,关键两点:
1、Spring可以将任意Java Class 纳入事务管理这里的UserDAO只是我们编写的一个普通Java Class,其中包含了一些基本的数据应用逻辑。通过Spring,我们即可简单的实现事务的可配置化。也就是说,我们可以随意为某个类的某个方法指定事务管理机制。与之对比,如果使用EJB容器提供的事务管理功能,我们不得不按照EJB规范编将UserDAO 进行改造,将其转换为一个标准的EJB。
2、Spring事务管理并不依赖特定的事务资源。EJB 容器必须依赖于JTA 提供事务支持。而Spring 的事务管理则支持JDBC、JTA 等多种事务资源。这为我们提供了更多的选择,从而也使得我们的系统部署更加灵活。
posted @ 2009-06-23 20:08 小兄弟(Robbins) 阅读(156) | 评论 (0)编辑 收藏
 
  模板技术相对传统JSP技术有以下三个主要的优势:
   1、表现逻辑与业务逻辑的分离
   2、将UI和程序分离,即将美工人员和程序员分离
   3、如果需要,模板引擎可以脱离web容器单独运行,为系统可能的移植需求提供了更多的弹性空间

   目前spring支持以下模板技术: 
   1、XSLT
         XSLT的性能相对较低,因为在XSLT中,每个节点都是一个java对象,大量对象的存储对内存占用极大,同时大量对象的频繁创建和销毁也对JVM垃圾收集产生了较大的负面影响。
   2、Velocity
         目前最为成熟的模板技术,它是apache jakarta项目中的一个子项目。
   3、FreeMarker
         对于web开发而言,FreeMarker在生产效率和学习成本上更具优势,而velocity的相对优势在于更多第三方工具的支持和更广泛的开发和用户团体。
  
posted @ 2009-06-23 13:13 小兄弟(Robbins) 阅读(165) | 评论 (0)编辑 收藏
 
    对于web应用,spring提供了可配置的ApplicatonContext加载机制;加载器目前有两种加载选择:ContextLoaderListener和ContextLoaderServlet

    加载器目前有两种选择:ContextLoaderListener和ContextLoaderServlet。这两者在功能上完全等同,只是一个是基于Servlet2.3版本中新引入的Listener接口实现,而另一个基于Servlet接口实现。开发中可根据目标Web容器的实际情况进行选择。

在web.xml中增加:
<listener>
    <listener-class>
         org.springframework.web.context.ContextLoaderListener
     </listener-class>
</listener>
-----------------------------------------------------------------
<servlet>
      <servlet-name>context</servlet-name>
      <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
</servlet>
通过以上配置,Web容器会自动加载/WEB-INF/applicationContext.xml初始化

如果需要指定配置文件位置,可通过context-param加以指定
<context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>/WEB-INF/myApplicationContext.xml</param-value>
</context-param>

posted @ 2009-06-23 11:32 小兄弟(Robbins) 阅读(201) | 评论 (0)编辑 收藏
仅列出标题
共3页: 1 2 3 下一页