Node 系的 headless 是原生的。Strapi、Directus 出娘胎就没前台------内容只走 API,前端爱怎么渲染怎么渲染,"内容也是代码"那一整套玩法都建立在没有包袱的地基上。
Java 系的 headless 是倒着长的。先有门户一体机:页面、权限、工作流、多站点,全在一个 JVM 里跑了好多年;后来客户要移动端、要小程序、要把内容喂给别的系统,才在这套现成系统上开 API 的门。门是后装的,装在原来那面墙上,装好了也能走人,但你一眼看得出哪栋楼是先有墙后开门。
看清这个出身,四家产品的差别就不再是功能表上勾没勾"支持 headless",而是门装在哪、装成什么样。
四条路,四种装法
dotCMS(2025-02-14 后新版本为 BSL 1.1):2009 年起家的老牌 Java CMS,走的是把新门和老墙熔成一体的混合路线。官方给页面编辑器取名 Universal Visual Editor(UVE),明确说它是"统一传统与 headless 两种场景的体验"。
业务团队在可视化界面里排页面、走审批,开发者走 REST、Page API(Layout as a Service)或 /api/v1/graphql 单一端点取数据,两边从同一个内容库读写。
CrafterCMS(GPL v3):把 API-first 写进交付层的代表。官方现行文档写明,Crafter Engine 向开发者提供内容、搜索、GraphQL 等接口,而且 Engine 本身多租户,一个交付引擎可以同时服务多个项目(站点)(本系列番外三,讲一个后台管 N 个站那篇拆过这层)。
它的 GraphQL 省了一桩常见的麻烦:每个项目的 schema 根据 Crafter Studio 里配好的内容类型独立生成,内容类型一改,schema 自动更新,不用手写第二份定义。
Magnolia (社区版 GPL v3):门是后来加上的,且社区版和商业版分了档。官方 REST 模块随社区版(CE)预装,内置 Delivery API,拿 HTTP GET 就能把 JCR 树里的节点、子节点和查询结果当 JSON 取出来;官方 CLI 的 mgnl jumpstart 提供 headless 模板,选 ce 就能把 Tomcat、Light Module 和 React/Angular/Vue 前端示例一起拉下来,靠 magnolia.config.js 把页面模板映射到前端组件。
但要注意协议与版本的分界:官方 GraphQL 模块只随商业版 DX Core 分发,而且只读、只能查 Content Types 定义的内容(查不了 Pages 和 Stories 应用里的页面,那两样仍走 REST Delivery API)。
Liferay(社区版 LGPL-2.1 或 DXP EULA 双许可):官方专门立了一章文档叫《Using Liferay as a Headless Platform》,给三条连接路子------符合 OpenAPI 规范的 Headless REST API、GraphQL API,以及 Service Builder 生成的普通 Web/REST 服务。
7.4 及以上版本里,后台把自定义对象(Objects)创建并发布出来,对应的 /o/c/* headless REST 端点就自动生成,配好 CORS 就能让外部 React 应用直接做增删改查。门户那套界面依然在主位,这套 API 的起点就是替原有的 Web 界面提供一份机器可读的对等操作。
为什么 Java 长成了这样
根子还在买家手里有什么。Java CMS 的买家早就有一堆现成系统:ERP、OA、老门户、内部业务台。他们要的往往是从现有内容库里拉数据出来喂新端,API 在这里的角色是接线。
拿 Node 那边"原生无前台"的标准去量,这批产品个个带着老房子的柱子;按接线的标准看,后开的门反而懂墙里原来埋着哪些管线------权限、工作流、审计日志都是现成的,不用前端自己再搭一套。
先开口子,别急着拆
- 团队只有一两个前端、内容就网站一个出口,别拆。拆开后多出来的部署、鉴权、缓存三笔账,全是系统原来替你干的活,单出口场景纯亏。
- 内容要同时喂主站、小程序、App,才值得逐个试这四家:
- 想要开源且自带自动 GraphQL schema,先看 CrafterCMS;
- 只用 REST 取 JCR 节点、前端自己映射组件,Magnolia 社区版就能跑通;
- 已经在用 Liferay 管门户和权限,直接开它的
/o/c/*端点最顺手。 - 尽量别自建一层中转 API------你有多少精力搭接口,就会少多少精力发内容。
- 拿不准就走中间路:在现有系统上开只读 API 给新前端,老页面照跑。等新出口用 API 稳稳跑上三个月,再谈全拆。这四家里除了 CrafterCMS 本来就按读写分离拆开,其余三家的官方口子都支持你先这么用。
本篇数据来源:
- dotCMS 官网(可视化编辑与 headless 混合定位):https://www.dotcms.com/
- dotCMS 官方文档《Universal Visual Editor》(统一传统与 headless 两种编辑场景):https://dev.dotcms.com/docs/author/pages-and-visual-editing/universal-visual-editor/universal-visual-editor
- dotCMS 官方文档《Page API (Layout as a Service)》(以 JSON 或渲染后 HTML 取页面结构与内容块):https://dev.dotcms.com/docs/build/apis/rest-apis/page-rest-api-layout-as-a-service-laas
- dotCMS 官方文档《GraphQL》(单一端点
/api/v1/graphql):https://dev.dotcms.com/docs/build/apis/api-basics/graphql - CrafterCMS 官方文档《Crafter Engine》(提供内容、搜索、GraphQL 等接口,Engine 多租户):https://craftercms.com/docs/current/reference/modules/engine.html
- CrafterCMS 官方文档《GraphQL》(schema 按项目内容类型独立生成、随变更自动更新):https://craftercms.com/docs/current/reference/api/graphql.html
- Magnolia 官方文档《REST module》(Bundled: Community edition,含 REST Content Delivery):https://docs.magnolia-cms.com/rest/
- Magnolia 官方文档《Delivery API》(
/.rest/delivery/*以 JSON 读取 JCR 节点、子节点与查询):https://docs.magnolia-cms.com/rest/api/delivery-endpoint/ - Magnolia 官方文档《Jumpstarting a headless Magnolia project》(CLI
headless模板支持选ce、SPA 组件映射magnolia.config.js):https://docs.magnolia-cms.com/product-docs/magnolia-front-end-development/jumpstarting-a-headless-magnolia-project/ - Magnolia 官方文档《GraphQL module》与《GraphQL API》(Bundled: DX Core,只读、仅查 Content Types,Pages 与 Stories 需走 REST Delivery endpoint):https://docs.magnolia-cms.com/graphql/ 、https://docs.magnolia-cms.com/graphql/reference-graphql-api/
- Liferay 官方文档《Using Liferay as a Headless Platform》(Headless REST/GraphQL/Service Builder 三种方式):https://learn.liferay.com/w/dxp/integration/headless-apis/using-liferay-as-a-headless-platform
- Liferay 官方教程《Remote Applications with Headless APIs》(7.4+ 发布对象后自动生成
/o/c/*headless REST 端点):https://learn.liferay.com/w/dxp/development/traditional-java-based-development/developing-a-web-application/using-react/remote-applications-with-headless-apis