开发基于JSR 168的开发和部署

来源:百度文库 编辑:神马文学网 时间:2024/04/29 14:01:35
轻松进行Java Portlets
——开发基于JSR 168的开发和部署 浏览次数: 1495 时间:2004-10-22

作者:Prakash Malani

摘要
Portlet是生成片段(遵守特定规范的标记语言(如HTML、XML)的片段)的Web组件。片段再合成一个完整的文档。本文介绍了关于Java Portlet的Java Specification Request (JSR) 168规范。它说明了如何使用BEA WebLogic Workshop 8.1 SP2来创建Java Portlet,以及如何将这些portlet部署到BEA WebLogic Portal 8.1 Sp2上。我将介绍一些关键概念,如门户、桌面和portlet,并详细描述多种portlet模式和窗口状态。我还将介绍如何使用Workshop来设计、实现、配置和执行portlet。
JSR 168定义了有关Java Portlet的规范。门户是一个Web应用程序和一个portlet的聚合。Portlet容器运行portlet,并管理它们的生命周期。JSR 168定义了portlet与portlet容器之间的契约,它没有定义portlet容器与门户之间的契约。门户的实现留给了门户供应商。
BEA WebLogic门户
BEA WebLogic Portal (8.1 SP2)的当前版本支持不同类型的portlet:JSP/HTML portlet、Java PageFlow portlet、Struts portlet和Java portlet,将来还会支持其他portlet,如Web Services for Remote Portlets (WSRP)。我们将着重介绍Java portlet。
WebLogic Portal提供了JSR 168中未描述的门户功能,包括但不限于:书和页面中portlet的组织、多渠道支持和使用skin、skeleton和shell定制。
为了能够继续下去,在进行下一部分之前,请先完成以下内容:
·使用WebLogic Domain Configuration Wizard创建一个门户域(如JSR168PortalDomain)。
·使用WebLogic Workshop创建一个使用上面所建立域的门户应用程序(如JSR168PortalApp)。
·在门户应用程序内创建一个门户Web项目(如JSR168PortalWebProject)。
·在门户Web项目中创建一个WebLogic Portal .portal文件(如JSR168.portal)。
·启动服务器实例。
创建您的第一个Java Portlet
下面的步骤描述了如何创建您的第一个JSR 168 portlet。
·在门户Web项目(如JSR168PortalWebProject)中,使用WebLogic Workshop为portlet(入FirstPortlet)创建一个新文件夹。
·在新文件夹内使用Wizard通过创建相应的.portlet文件创建一个新portlet(如Firstportlet)。
·选择portlet类型为Java Portlet。
·指定标题(如First)。
·指定定义标签(如first)。
·指定类名称(如com.malani.examples.portlets.jsr168.FirstPortlet)。
·打开门户(如JSR168.portal)。
·将portlet(如Firstportlet)拖放到门户中的页面上(如JSR168.portal)。
·运行.portal文件进行测试。
您的第一个JSR 168 portlet已经成功运行了!但向导在背后作了些什么呢?
·它创建了一个特定于WebLogic Workshop和WebLogic Portal的.portlet文件。.portlet文件构成了与特定于Workshop和WebLogic Portal的.portal文件的契约。
·向导创建了一个.java文件(如com.malani.examples.portlets.jsr168.FirstPortlet.java),该文件放置在WEB-INF/src目录中。
·向导创建了一个WEB-INF/portlet.xml配置文件,并为portlet在文件中插入了一个条目。该portlet的条目看上去如下:

Description goes here
first
com.malani.examples.portlets.jsr168.FirstPortlet


First


Java Portlet类
在该示例中,向导生成的Portlet Java文件扩展了javax.portlet.GenericPortlet类。GenericPortlet类实现了javax.portlet.Portlet接口。图1是一个Unified Modeling Language (UML)类图,描述了这些关系。通过直接实现portlet接口,可以编写一个portlet。然而,GenericPortlet是一个创建portlet的更方便方法。首先,我们看一下portlet生命周期、portlet模式和window状态。

图 1
Portlet生命周期
为了成功地创建portlet,您必须遵照portlet生命周期。javax.portlet.Portlet接口中的方法定义了该生命周期,这些生命周期方法是init()、render()、processAction()和destroy()。当部署portlet的实例时调用init()方法。它用于获得所需的任何昂贵资源(如后台连接),并执行其他一次性活动。当portlet的实例被撤销部署时,使用destroy()方法来释放这些资源。
Portlet规范清晰区别render请求和动作请求。图2描述了portlet请求和响应的一个UML类图。门户页面上的render请求会导致对所页面上的每个portlet上调用render()方法,当用户在特定portlet上调用某个动作(通常是HTML表单提交)时,将会调用该portlet的processAction()方法。这样,用户的动作请求转换为processAction()方法的一次调用和render()方法的多次调用。

图 2
图3是一个序列图,说明了调用processAction()方法的效果,以及为同一页面上的portlet进行后续render()方法的调用。关于更多信息,请参阅关于处理动作的一节。

图 3
有两种重载的init()方法,一个没有参数,另一个有一个javax.portlet.PortletConfig类的实例。注意:关于init(PortletConfig)有一个特殊的caveat。调用super.init(aPortletConfig)失败将导致一个NullPointerException。所包含的源代码示例中的Init portlet说明了这种行为(源代码可以在www.sys-con.com/weblogic/source.cfm中找到)。
Portlet模式
JSR 168定义了三种Portlet模式:VIEW、EDIT和HELP。一个portlet实例在任何时候都可以恰巧在一种 portlet模式下。其他自定义portlet模式(如配置和源)都是可能的。VIEW模式是默认的模式。Portlet规范建议EDIT模式允许portlet用户定制portlet实例,以及HELP模式显示关于portlet的用法信息。Portlet必须支持VIEW模式,但在portlet中对EDIT模式和HELP模式的支持是可选的。例如,portlet First portlet示例不支持EDIT模式和HELP模式。
window状态
JSR 168定义了三种Window状态:NORMAL、MINIMIZED和MAXIMIZED。Portlet实例任何时候都可以恰好是一种window状态。其他自定义window状态(如半页)也是可能的。在NORMAL状态下,portlet占了屏幕区的一小部分。屏幕状态与其他portlet共享。在MINIMIZED状态下,portlet的内容被隐藏。在MAXIMIZED状态下,portlet的内容占屏幕区的大部分。其他共享同一页面的portlet在MAXIMIZED状态下被隐藏。例如,portlet First示例支持所有三种window状态。
GenericPortlet类
您创建的大多数portlet将会扩展javax.portlet.GenericPortlet类,而不是直接实现javax.portlet.Portlet接口。GenericPortlet类实现了render()方法。如果portlet的window状态被最小化,那么render()方法不能做任何事情。如果portlet的window状态不是最小化,那么render()方法设置在portlet.xml文件中指定的标题,并调用doDispatch()方法。根据Portlet模式, doDispatch()方法适当地调用doView()、doEdit()和doHelp()方法。这样,由于GenericPortlet类帮助实现render()方法,并且提供doView()、doEdit()和doHelp()方法来覆盖,因此GenericPortlet类比Portlet接口更便于扩展。
考虑一下First portlet示例。FirstPortlet类扩展了GenericPortlet,FirstPortlet改写了doView()方法。
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");
response.getWriter().write("

Hello World

");
}
注意:调用setContentType()方法前调用getWriter()方法会导致java.lang.IllegalStateException。
实现Portlet模式
VIEW模式是强制的,但EDIT和HELP模式是可选的。为了实现EDIT和HELP portlet模式,需要在portlet类中实现适当的doEdit()和doHelp()方法。请参考包含在源代码示例(本文的源代码可以在www.sys-con.com/wldj/sourcec.cfm找到)中的portlet Mode。此外,必须在portlet.xml中如下配置各模式:

text/html
edit
help

注意:修改portlet.xml配置文件,但不实现portlet类中的相应方法,会导致javax.portlet.PortletException。
实现window状态
JSR 168没有描述禁用window状态支持的方法。然而,WebLogic Portal实现了对它们的禁用。为了禁用portlet对window状态的支持,需要在weblogic-portlet.xml文件中排除window状态:

state

text/html
minimized
maximized


请参考源代码示例中的portlet State。
包含JavaServer Pages (JSPs)
考虑portlet First的doView()方法,该方法获得了Writer的实例,并直接输出HTML片段。由于多种原因(如为了达到Java逻辑与HTML视图表现的分离),往往不推荐输出直接的HTML片段。推荐的方法是使用JSP来显示视图。portlet类中的方法执行业务逻辑、设置render参数以及包含JSP。为了包含一个特定的JSP,应首先获得PortletContext。从PortletContext实例中,通过调用getRequestDispatcher()方法获得一个PortletRequestDispatcher的实例。通过调用include()方法来包含JSP。例如:
// execute the necessary logic here...
PortletRequestDispatcher aDispatcher =
getPortletContext().getRequestDispatcher(
"/IncludePortlet/includeView.jsp"
);
aDispatcher.include(aRequest, aResponse);
注意:在执行render()方法时,portlet可能只使用一个PortletRequestDispatcher对象。
请参考包含在源代码中的portlet Include。JSP页面(如includeView.jsp)不包含根HTML标签(如、和<body>),因为这些标签由门户框架提供。JSP页面只包含显示portlet所必需的HTML片段。<br>处理动作<br>在一个标准的Web应用程序中,一个HTML表单提交将导致执行一些业务逻辑。业务处理的结果,要么作为属性而被设置在请求或会话中并转发,要么包含到下一个JSP。<br>在一个JSR 168 portlet中,一个HTML表单的动作URL应该是什么样呢?JSR 168定义了一个JSP标签库,称为portlet taglib。HTML表单的动作URL可以使用actionURL portlet标签生成。例如(请参考favoriteColorEdit.jsp文件):<br><form action="<portlet:actionURL/>" method="post"><br>...<br></form><br>提交该HTML表单将会导致调用portlet的processAction(ActionRequest aRequest, ActionResponse aResponse)方法。像通常一样,可以通过调用request对象的getParameter()方法来获得表单参数。注意:通过提交表单调用动作,但portlet中却没有processAction()方法,将会导致javax.portlet.PortletException。<br>processAction()方法设置response对象中的值。不要使用ActionRequest或ActionResponse对象的setAttribute()方法。值不会从processAction()传递到render()方法,而且在JSP中是不可用的。相反要使用ActionResponse对象的setRenderParameter()方法。这些render参数将对所有后续render请求可用,这一点与典型的Web应用程序请求属性很不相同。典型的Web application请求属性只对于一个请求可用。另一方面,render请求参数对于许多后续render请求可用。render参数保持可用直到值被动作的重新执行显式地修改或删除。<br>考虑portlet FavoriteColor。它在VIEW模式显示了一个用户偏好的颜色,但是可以在EDIT模式下更改。在EDIT模式下提交偏好的颜色选择将调用processAction()方法。该方法获得偏好的颜色请求参数,并将其设置为render参数。这样,偏好的的颜色render参数将在所有后续render请求中都可用。<br>所呈现的参数是怎样显示在JSP上的呢?应使用来自portlet标签库的defineObjects标签来定义portlet对象。该标签使renderRequest、renderResponse和portletConfig portlet对象在页面中可用。参数通过调用renderRequest对象的getParameter()方法来显示。请参考与所包含的源代码示例中的favoriteColorView.jsp。<br>portlet FavoriteColor也展示了其他概念。第一个是如何在processAction()方法中用编程的方法改变portlet模式。调用ActionResponse对象的setPortletMode()方法来修改portlet模式。第二个概念是如何使用一个HTML链接来修改portlet模式。该链接使用来自portlet标签库的renderURL标签生成。根据希望的portlet模式指定portletMode属性的值。请参考源代码示例中的FavoriteColorPortlet类和favoriteColorView.jsp页面。<br>Portlet Preferences<br>Portlet Preferences(Portlet首选项)是portlet的基本配置数据。一个preference是一个“名称和值”对。名称的类型是一个字符串,而值的类型是字符串或字符串数组。Portlet Preference不适于存储任意数据。portlet容器为portlet preferences提供持久性。在WebLogic Portal中,preference的持久性只在下面两个条件都为真时才起作用:<br>·门户运行在桌面中,而不是DOT门户模式。<br>·用户已经登录。<br>桌面与DOT门户模式<br>在WebLogic Workshop中创建.portal文件时,像书、页面和portlet等项都可以被拖放到.portal文件中,.portal文件能够直接从Workshop内运行。然而,某些功能,如preferences的存储,在这种DOT门户模式下运行时是不可用的(DOT门户模式也称为单文件模式(Single File Mode))。<br>其他模式称为桌面模式。创建一个门户时使用Portal Administrator。在门户内,一个桌面被创建。像图书、页面和portlet等项被创建,并放置在桌面中。在这种模式下,某些功能,像preferences的存储,是可用的(桌面模式也被称为流模式(Streamed Mode))。<br>在继续讨论前,先创建一个桌面:<br>启动Portal Administration(譬如,http://localhost:7001/JSR168PortalAppAdmin/)。一种启动Portal Administration的方法是直接从Workshop中启动。选择Portal菜单,选中Portal Administration菜单项。<br>·登录进Portal Administration。<br>·创建一个新门户(譬如,JSR168)。<br>·在门户中,创建一个新桌面(如d1)。<br>·将LoginPortlet添加到桌面的一个页面中。<br>·将ContactPortlet添加到桌面的一个文件中。<br>Portlet Preferences示例<br>Contact portlet演示了Portlet Preferences。Portlet Preferences可以是静态的或动态的。静态 preferences与portlet一起在portal.xml文件中指定。例如,ContactPortlet具有一个成为contact-preference的 preferences。contact-preference的默认值也被指定:<br><portlet-preferences><br><preference><br><name>contact-preference</name><br><value>Email</value><br></preference><br></portlet-preferences><br>动态 preferences不在portlet.xml配置文件中预定义。当portlet运行时,这些preferences被存储和读取。在运行期间,一个javax.portlet.PortletPreferences接口的实例包含这些preferences。该实例通过调用PortletRequest对象的getPreferences()方法获得。特定preferences的值通过调用preferences实例上的getValue()方法来获得。<br>调用preferences实例的setValue()方法会更新一个preferences值。然而,需要一个额外的步骤来提交这些修改。preferences实例的store()方法被调用来使preferences持久化。preferences只能在processAction()方法中进行修改。如果在processAction()方法中没有调用store()方法,任何对preferences实例的修改都会被丢弃。注意:就如前面提到的,如果用户没有登录或门户处于DOT门户模式,那么调用store()方法将会导致一个运行时异常。<br>在portlet和servlet之间有很多相似点。然而,它们也存在着重要区别。portlet规范建立在servlet规范之上。portlet容器存在于servlet容器中。就像servlet部署在一个Web应用程序中,portlet也是如此。Servlet和Web应用程序使用portlet.xml文件进行配置。一个servlet具有显式的生命周期:init()、doGet()、doPost()等。类似地,一个portlet也具有显式的生命周期:doView()、doEdit()、processAction()等。servlet和portlet类的方法必须以安全线程的方式编码。<br>然而,也存在着重要的区别。Servlet被允许进行include、forward和redirect操作;然而portlet只被允许进行include操作。Servlet能够呈现一个完整的页面,但portlet只提交页面片段。portlet具有严格定义的portlet模式和Window状态,这方面不像servlet。Portlet具有更正式的请求,对render请求和动作请求进行处理,它们也具有preferences。portlet并不是servlet!<br>结束语<br>本文通过使用一个简单的向导描述portlet的创建而开始,并说明了portlet的生命周期以及portlet类实现的内部工作方式,描述了portlet.xml配置文件和相应的weblogic-portlet.xml配置文件的结构和语义。对各种概念,如portlet模式和window状态,本文也进行了解释。本文演示了portlet标签库的用法和portlet中的表单处理。最后,我介绍了如何使用portletpreferences。理解了本文所介绍的这些知识和概念,您就可以在创建和部署自己的强大portlet的道路上前进了。<br>致谢<br>感谢Subbu Allamaraju、Max Cooper、Steve Ditlinger、David Lu、Roshni Malani和Alex Toussaint,他们仔细阅读了这篇文章,并提供了有价值的反馈意见。<br>参考资料<br>· 要讨论这篇文章、并提问问题,从这里开始:www.bartssandbox.com。需要免费成员资格。<br>· 下载、阅读JSR 168:www.jcp.org/en/jsr/detail?id=168<br>· WebLogic Portal文档的起始点:e-docs.bea.com/wlp/docs81/index.html<br>· 建立Workshop Help的Java Portlet部分:e-docs.bea.com/workshop/docs81/doc/en/core/index.html<br>· 用WebLogic Portal 8.1开发JSR 168 Portlet:dev2dev.bea.com/products/wlportal81/articles/JSR168.jsp <br>· Web Services for Remote Portlets (WSRP)规范:www.oasis-open.org/committees/tc_home.php?wg_abbrev=wsrp<br>· 尝试一下WSRP:dev2dev.bea.com/codelibrary/code/wsrp_supportkit.jsp<br>· Single File Mode和Streamed Rendering Mode:单击这里!<br>· 有关Portlet规范上的文章:<br>- 介绍Portlet规范,第1部分:<br>www.javaworld.com/javaworld/jw-08-2003/jw-0801-portlet_p.html<br>-介绍Portlet规范,第2部分:<br>www.javaworld.com/javaworld/jw-09-2003/jw-0905-portlet2_p.html<br>· 对JSR 168白皮书的介绍:单击这里!<br>· Java Passion Portlet演讲笔记:www.javapassion.com/j2eeadvanced/Portlet4.pdf<br>关于作者<br>Prakash Malani在架构、设计和开发面向对象的软件方面具有广泛的经验,曾经在很多应用领域从事过软件开发,如娱乐、零售、机械、通信和互动电视等。他实践和指导着很多领先的技术,如J2EE、UML和XML。   Prakash已经在多个行业领先的出版物上发表了多篇文章。(更多内容)<br>源代码<br>源代码-Zip文件<br>英文原文:http://www.sys-con.com/story/?storyid=45565&DE=1<br>_xyz</div> <div class="list-group"> <a href="/article/2980" class="list-group-item">开发基于JSR 168的开发和部署</a> <a href="/article/327700" class="list-group-item">在MOSS中开发和部署Infopath</a> <a href="/article/39561" class="list-group-item">基于Java的移动游戏开发入门</a> <a href="/article/57629" class="list-group-item">开发基于JBoss的J2EE应用</a> <a href="/article/58435" class="list-group-item">基于intel架构的网络课件开发</a> <a href="/article/79125" class="list-group-item">基于JSON的高级AJAX开发技术</a> <a href="/article/99421" class="list-group-item">基于Java的Web应用开发规范</a> <a href="/article/183306" class="list-group-item">基于CGM勘探应用软件的开发</a> <a href="/article/207055" class="list-group-item">基于.net的快速开发思想</a> <a href="/article/226027" class="list-group-item">教程:基于MapServer的WebGIS开发</a> <a href="/article/241511" class="list-group-item">基于Spring框架的WebSphere应用开发</a> <a href="/article/569290" class="list-group-item">基于Spring框架的WebSphere应用开发</a> <a href="/article/934540" class="list-group-item">ArcIMS--基于WEB的GIS开发</a> <a href="/article/2124354" class="list-group-item">基于JSON的高级AJAX开发技术</a> <a href="/article/1274011" class="list-group-item">的开发和</a> <a href="/article/98030" class="list-group-item">创建新的门户: 第 5 部分:开发、构建和部署门户</a> <a href="/article/92799" class="list-group-item">使用 Portlet Builder 开发和部署门户组件</a> <a href="/article/140067" class="list-group-item">Symbian和C++ SDK开发入门之部署</a> <a href="/article/189057" class="list-group-item">中国首次全面规划部署保护和开发蓝色国土</a> <a href="/article/29037" class="list-group-item">基于 Windows Mobile 的 Pocket PC 和 Smartphone 的开发工具简介</a> <a href="/article/396552" class="list-group-item">第四组基于网络资源的对网络教育资源的建立和开发</a> <a href="/article/1164218" class="list-group-item">基于 Windows Mobile 的 Pocket PC 和 Smartphone 的开发工具简介</a> <a href="/article/136819" class="list-group-item">基于uClinux的开发应用程序-Helloworld和跑马灯程序||操作系统|</a> <a href="/article/253939" class="list-group-item">时勘:基于胜任特征模型的人力资源开发和绩效管理</a> </div> </div> </div> </div> </div> </div> <footer id="footer" class="footer hidden-print"> <div class="container"> <div class="panel panel-default"> <div class="panel-heading">相关问题</div> <div class="panel-body"> <a class="btn btn-default" href="/article/762786" title="现代文字狱 - 归途博客">现代文字狱 - 归途博客</a> <a class="btn btn-default" href="/article/762787" title="电缆修理工作业操作规程---煤矿安全生产网">电缆修理工作业操作规程---煤矿安全生产网</a> <a class="btn btn-default" href="/article/762788" title="谁说高血压要吃一辈子">谁说高血压要吃一辈子</a> <a class="btn btn-default" href="/article/762789" title="假如 生活 欺骗了你">假如 生活 欺骗了你</a> <a class="btn btn-default" href="/article/762790" title="提升过程与方法(转自SSOA) - 光与爱 |灵性成长网|心灵成长|为你寻找生命的平衡点|...">提升过程与方法(转自SSOA) - 光与爱 |灵性成长网|心灵成长|为你寻找生命的平衡点|...</a> <a class="btn btn-default" href="/article/762791" title="10秒钟改变自己">10秒钟改变自己</a> <a class="btn btn-default" href="/article/762792" title="一汤一粥解决顽固性口腔溃疡">一汤一粥解决顽固性口腔溃疡</a> <a class="btn btn-default" href="/article/762793" title="毛泽东诗词收录">毛泽东诗词收录</a> <a class="btn btn-default" href="/article/762794" title="《心灵鸡汤》卷六 克服障碍(之一)">《心灵鸡汤》卷六 克服障碍(之一)</a> <a class="btn btn-default" href="/article/762795" title="你一辈子都在找的一篇文章1!(不知谁整理的,太好了...借来用用,呵呵...)">你一辈子都在找的一篇文章1!(不知谁整理的,太好了...借来用用,呵呵...)</a> <a class="btn btn-default" href="/article/762796" title="不奢求,爱情所以长久">不奢求,爱情所以长久</a> <a class="btn btn-default" href="/article/762797" title="试情人的绝招">试情人的绝招</a> <a class="btn btn-default" href="/article/762798" title="笑话中感悟人生">笑话中感悟人生</a> <a class="btn btn-default" href="/article/762799" title="[分享]奇迹课程资料在线阅读">[分享]奇迹课程资料在线阅读</a> <a class="btn btn-default" href="/article/762800" title="谁是小偷,谷歌还是百度(转载)-大老粗的博客-搜狐博客">谁是小偷,谷歌还是百度(转载)-大老粗的博客-搜狐博客</a> <a class="btn btn-default" href="/article/762801" title="如何研究均线-周期,方向,大小,拐点1">如何研究均线-周期,方向,大小,拐点1</a> <a class="btn btn-default" href="/article/762802" title="赌场大揭秘之三(共十二篇、有赌的人必看) -">赌场大揭秘之三(共十二篇、有赌的人必看) -</a> <a class="btn btn-default" href="/article/762803" title="强大的多内核高清播放器,“史”上最强大的“山寨播放器” - 电脑疯子╃软件更新 - 电脑疯子论坛 电脑疯子论坛,电脑疯子官方网站 - Powered by Discuz!">强大的多内核高清播放器,“史”上最强大的“山寨播放器” - 电脑疯子╃软件更新 - 电脑疯子论坛 电脑疯子论坛,电脑疯子官方网站 - Powered by Discuz!</a> <a class="btn btn-default" href="/article/762804" title="《个人觉醒的力量》又名《觉察的力量》">《个人觉醒的力量》又名《觉察的力量》</a> <a class="btn btn-default" href="/article/762805" title="宝贝,听我说……(写给失恋女生的)">宝贝,听我说……(写给失恋女生的)</a> <a class="btn btn-default" href="/article/762806" title="《发烧车舞 DSD》聆听劲爆与天籁">《发烧车舞 DSD》聆听劲爆与天籁</a> <a class="btn btn-default" href="/article/762807" title="[转帖]十件你生命中无能为力的事(看了你会放开很多) - 修炼成长 - 栖息谷·管理人论坛">[转帖]十件你生命中无能为力的事(看了你会放开很多) - 修炼成长 - 栖息谷·管理人论坛</a> <a class="btn btn-default" href="/article/762808" title="咳嗽与哮喘">咳嗽与哮喘</a> <a class="btn btn-default" href="/article/762809" title="怎样学好《伤寒论》?0">怎样学好《伤寒论》?0</a> <a class="btn btn-default" href="/article/762810" title="峥嵘岁月:才子?报人?老革命 ——记吴砚农同志">峥嵘岁月:才子?报人?老革命 ——记吴砚农同志</a> <a class="btn btn-default" href="/article/762811" title="故宫各殿镇物">故宫各殿镇物</a> <a class="btn btn-default" href="/article/762812" title="愤青辞典">愤青辞典</a> <a class="btn btn-default" href="/article/762813" title="周易与医学0">周易与医学0</a> <a class="btn btn-default" href="/article/762814" title="心理学入门书籍导读 - 光与爱 |灵性成长网|心灵成长|为你寻找生命的平衡点|活出灵魂的特...">心理学入门书籍导读 - 光与爱 |灵性成长网|心灵成长|为你寻找生命的平衡点|活出灵魂的特...</a> <a class="btn btn-default" href="/article/762815" title="是爷们吗?是就学学吧!">是爷们吗?是就学学吧!</a> <a class="btn btn-default" href="/article/762816" title="中国名菜典故">中国名菜典故</a> </div> </div></div> <div class="copy-right"> <p>神马文学网,客观、专业、权威的知识性互动百科全书。</p></div> </footer> </body> </html>