opencms的主工作区文件研究

简介:

引入:

在我们第一次打开openCMS主工作区的时候,我们的请求地址是:http://localhost:8080/opencms/opencms/system/workplace/views/workplace.jsp, 它会打开一个类似如下的工作区界面:

wKioL1R6iHCykAa0AAQP1JQwhwY057.jpg

细心的读者会发现,此工作区文件workplace.jsp在整个opencms.war中根本就没有,那么这个页面到底来自哪里呢?


解决:

我们做了调试,当请求到达opencms时候,它最早会进入OpenCmsServlet的doGet()方法,它进而会去调用OpenCmsCore的showResource()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected  void  showResource(HttpServletRequestreq,HttpServletResponse res) {
  
         CmsObject cms =  null ;
         try  {
             cms = initCmsObject(req, res);
  
….
  
             // user is initialized, now deliver the requested resource
             CmsResource resource = initResource(cms, cms.getRequestContext().getUri(),req,res);
             if  (resource !=  null ){
                 // a file was read, go on process it
                 m_resourceManager.loadResource(cms, resource, req, res);
                 m_sessionManager.updateSessionInfo(cms, req);
             }
  
         catch  (Throwable t) {
             errorHandling(cms, req, res, t);
         }
}

此方法从宏观上做了几件大事:

(1)初始化CMS对象和当前用户配置信息(这个我们没兴趣)

(2)根据请求URL获取Resource对象(这应该是一个对象ID)。

(3)让CmsResourceManager载入Resource对象(这应该是一个真实页面)

我们逐个分析。



亮点1: 如何根据请求URL获取Resource对象:

对于根据请求URL获取Resource对象,可以看到它首先调用了CmsResource的initResource()方法,而initResource()方法会调用CmsObject的readDefaultFile方法来从CMS的VFS(虚拟文件系统)中获取指定的Resource. 这个readDefaultFile会根据请求的资源URI来创建一个UUID,然后获取资源对象,如果获取不成功,则直接通过URI来获取资源对象。这里从调试过程可以看出,它是直接通过URI来获取资源对象:

wKiom1R6t_PAXyTxAAN29YBfRUo564.jpg

而获取方式则是通过CmsSecurityManager的readResource()方法,它进而会委托CmsDriverManager的readResource()方法来从数据库中获取Resource对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
public  CmsResource readResource(CmsDbContext dbc, String resourcePath,CmsResourceFilter filter)
    throwsCmsDataAccessException {
  
         CmsUUID projectId =getProjectIdForContext(dbc);
         // please note: the filter will be applied in the security manager later
         CmsResource resource =getVfsDriver(dbc).readResource(dbc, projectId, resourcePath,filter.includeDeleted());
  
         // context dates need to be updated
         updateContextDates(dbc, resource);
  
         // return the resource
         return  resource;
}

从调试结果可以看,它会构建以下的查询语句:

1
SELECT  CMS_OFFLINE_STRUCTURE.STRUCTURE_ID,CMS_OFFLINE_STRUCTURE.RESOURCE_ID,CMS_OFFLINE_STRUCTURE.RESOURCE_PATH,CMS_OFFLINE_STRUCTURE.STRUCTURE_STATE,CMS_OFFLINE_STRUCTURE.DATE_RELEASED,CMS_OFFLINE_STRUCTURE.DATE_EXPIRED,CMS_OFFLINE_STRUCTURE.STRUCTURE_VERSION,CMS_OFFLINE_RESOURCES.RESOURCE_ID,CMS_OFFLINE_RESOURCES.RESOURCE_TYPE,CMS_OFFLINE_RESOURCES.RESOURCE_FLAGS,CMS_OFFLINE_RESOURCES.RESOURCE_STATE,CMS_OFFLINE_RESOURCES.DATE_CREATED,CMS_OFFLINE_RESOURCES.DATE_LASTMODIFIED,CMS_OFFLINE_RESOURCES.USER_CREATED,CMS_OFFLINE_RESOURCES.USER_LASTMODIFIED,CMS_OFFLINE_RESOURCES.PROJECT_LASTMODIFIEDASLOCKED_IN_PROJECT,CMS_OFFLINE_RESOURCES.RESOURCE_SIZE,CMS_OFFLINE_RESOURCES.DATE_CONTENT,CMS_OFFLINE_RESOURCES.SIBLING_COUNT,CMS_OFFLINE_RESOURCES.RESOURCE_VERSION,CMS_OFFLINE_RESOURCES.PROJECT_LASTMODIFIEDFROM CMS_OFFLINE_STRUCTURE,CMS_OFFLINE_RESOURCES WHERECMS_OFFLINE_STRUCTURE.RESOURCE_PATH= '/system/workplace/views/workplace.jsp'  ANDCMS_OFFLINE_STRUCTURE.RESOURCE_ID=CMS_OFFLINE_RESOURCES.RESOURCE_ID  ORDER  BYCMS_OFFLINE_STRUCTURE.STRUCTURE_STATE  ASC

此查询的用意是根据请求的RESOURCE_PATH来查找CMS离线结构表CMS_OFFLINE_STRUCTURE(很好理解,因为这块是框架层面的,不是对外作为站点内容给用户看的,所以这些资源应该是offline的结构资源),获取对应的RESOURCE_ID和其他一些相关信息:

wKiom1R6uQ3zjILCAAIR1V0qPY8512.jpg

这样,我们就获得了资源ID为9c0a79be-f058-11d8-ba65-db38cc8f19d7 的资源,这就是请求workplace.jsp的资源ID。此资源对象的信息从调试器中获知为:

1
[org.opencms.file.CmsResource, path:/system/workplace/views/workplace.jsp, structure id840ccc67-11b7-11db-91cd-fdbae480bac9, resource id:9c0a79be-f058-11d8-ba65-db38cc8f19d7, type id: 4, folder: false, flags: 0, project:00000000-0000-0000-0000-000000000000, state: 0, date created: Mon Jun 2716:00:00 CST 2005, user created: c300ba5c-01e8-3727-b305-5dcc9ccae1ee, datelastmodified: Mon Jan 29 18:25:58 CST 2007, user lastmodified:c300ba5c-01e8-3727-b305-5dcc9ccae1ee, date released: Thu Jan 01 08:00:00 CST1970, date expired: Sun Aug 17 15:12:55 CST 292278994, date content: Sun Nov 3008:06:18 CST 2014, size: 1546, sibling count: 2, version: 1]


亮点2:如何根据Resource对象获得真实Resource并进行渲染:

这就是靠CmsResourceManager的loadResource()方法来做具体的文件读取,然后通过CmsSessionManager来更新会话了。具体略,其实质就是通过刚才的ResourceID查找CMS_CONTENT表获取对应的页面JSP文件,然后利用合适的加载器来加载。因为fileType是jsp,所以最终使用的加载器是CmsJspLoader. 

我们查找数据库CMS_CONTENTS表,果然找到了对应的记录:

wKioL1R6ux3CX4KxAAFYzrzsgrc328.jpg

将该BLOB打开,我们查看内容:

wKioL1R6iijzDAkVAAO75a1grhY292.jpg

发现它是用的frameset结构,之前会先外部引入一些js 文件,比如explorer.js,ajax.js,top_js.jsp,之后在frameset中,又会先包含top_head.jsp,主体和top_foot.jsp ,而这一切和我们从Firebug的网络视图中看到的是一样的:

wKiom1R6iljgUsX9AAIzEdjkGuo132.jpg


总结:

(1)这些最终请求的资源文件都以BLOB形式存放在数据库中而不是直接在opencms.war中。

(2)从请求URI到资源ID获取通过查找CMS_OFFLINE_STRUCTURE和CMS_OFFLINE_RESOURCES这两张表。CmsResource,CmsObject,CmsSecurityManager,CmsDriverManager都参与其中。

(3)从资源ID到真实页面的JSP文件通过查找CMS_CONTENTS表,CmsResourceManager参与其中。






本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1584645,如需转载请自行联系原作者
目录
相关文章
|
缓存 知识图谱
SVN培训笔记(下拉项目、同步修改、添加文件、修改文件、删除文件、改名文件等)
为了方便新加入团队的员工熟悉团队写作开发。为了将好东西分享给广大网友和初入职场的小白。将SVN内部员工培训文档公开,以方便更多的人,提高知识获取速度,尽快熟悉协同开发。本文档培训员工对于SVN的基本操作,这些操作是开发过程中最常用的操作。
SVN培训笔记(下拉项目、同步修改、添加文件、修改文件、删除文件、改名文件等)
|
Windows
将指定文件夹纳入OneDrive同步:mklink命令
本文介绍利用mklink语言,使得OneDrive自动同步电脑中任意指定文件夹的方法~
423 1
将指定文件夹纳入OneDrive同步:mklink命令
|
存储 JSON 安全
electron如何自定义目录,修改文件名保存下载的网络文件
很多同学觉得用localstorage可以代替vuex, 对于不变的数据确实可以,但是当两个组件共用一个数据源(对象或数组)时,如果其中一个组件改变了该数据源,希望另一个组件响应该变化时,localstorage无法做到,原因就是区别1。
electron如何自定义目录,修改文件名保存下载的网络文件
解决TortoiseGit文件夹和文件状态图标不显示问题
解决TortoiseGit文件夹和文件状态图标不显示问题
160 0
解决TortoiseGit文件夹和文件状态图标不显示问题
|
NoSQL 开发工具 数据库
git,程序配置文件管理,忽略本地更改
在不同的开发环境(同事与同事之间 开发与测试与生产环境)大概率是不同的。 如果每个人都按普通的流程,Pull然后修改成自己本地的,没有忽略监听更改。 那么当他提交代码时,经常会把配置文件也上传到git仓库中。 会影响其他人的开发。
169 0
|
XML Java Android开发
AndroidStudio不自动添加新创建的文件到VCS的解决办法
AndroidStudio不自动添加新创建的文件到VCS的解决办法
AndroidStudio不自动添加新创建的文件到VCS的解决办法
|
Web App开发 Apache 数据安全/隐私保护
|
JavaScript 前端开发 Java