跳转至

Message 模块 API

Message 模块是 MyApps 平台的**消息推送与通知服务**(obpm-message),提供站内消息、公告、消息评论、事项提醒通知、消息中心通知(含 SSE 实时推送)等能力。该模块的 context-path 占位符为 ${myapps.context-path.message:}(部署时替换为具体上下文路径,缺省为空;lite 统一打包下为 /,此时模块路径前缀多一层 /message)。

注:本仓库根 docs/restful-api/index.md「服务与基址」表暂未单独列出 message 行;模块无独立 application*.yml 公开源码(端口由部署侧 server.port 决定)。本模块路径前缀与 URL 模式均以源码为准。

覆盖进度:5 / 5 控制器(已覆盖 CommentController、MessageController(消息域)、NoticeController、NotificationController、MessageController(runtime 消息中心))

Message 模块共有 5 个有端点的控制器,合计 31 个端点(评论 6 + 消息 9 + 通知 5 + 消息通知 7 + runtime 消息 4)。源码树中另有 BaseController<E>(抽象基类)、AbstractRuntimeController(抽象基类)、HtmlEditUploadController(无端点,仅注册 MessageUploadServlet,不在本文档范围)不单独成文。

注:message 模块存在**两个同名 MessageController**,分属不同包、职能不同,本文档按下列命名区分: - message.mdcn.myapps.message.message.controller.MessageController(消息/公告 CRUD,基址 /api/message/messages) - message-runtime.mdcn.myapps.message.runtime.message.controller.MessageController(runtime 消息中心「通知事项」轻量 API,基址 /runtime/messages

已文档化控制器

文件 中文名 基址 端点数
comment.md CommentController(消息评论) ${myapps.context-path.message:}/api/message/comment 6
message.md MessageController(消息/公告 CRUD) ${myapps.context-path.message:}/api/message/messages 9
notice.md NoticeController(事项提醒通知) ${myapps.context-path.message:}/api/message/notice 5
notification.md NotificationController(消息中心通知 / SSE 推送) ${myapps.context-path.message:}/api/message/notification 7
message-runtime.md MessageController(runtime 消息中心) ${myapps.context-path.message:}/runtime/messages 4

鉴权说明

(据源码)message 模块**不使用 Spring Security**,也**不使用 HandlerInterceptor 做鉴权**(PersistenceHandlerInterceptor 仅在 postHandle 关闭数据库连接,preHandle 恒返回 true,不参与鉴权)。访问控制由以下两个 Servlet Filter 协同完成:

  • CommonSecurityFilter(obpm-common,CommWebMvcConfig.filterRegistrationBeanCommonSecurityFilter1 注册,URL 模式 /*,order=-1):所有模块共享的前置过滤器。携带合法 systemToken 请求头(系统间 Feign 调用,JWT 内 username 固定为 systemToken)的请求被标记 pass=true 跳过后续鉴权;/v3/api-docs/swagger-ui/druid 需 designer/admin token;/actuator(除 /actuator/health 放开)返回 401;仅允许 GET/POST/HEAD/OPTIONS 方法,其他方法返回 HTTP 405(HTML 错误页)。
  • MessageSecurityFilter(obpm-message,MessageMvcConfig.filterRegistrationBeanMessageSecurityFilter 注册,order=2):message 模块核心鉴权。URL 模式与 context-path 相关——独立部署(context-path 非 /)下为 /*,lite 统一部署(context-path 为 /)下为 /message/*(避免误拦截其他模块)。流程:
  • 若前置过滤器已标记 pass=true(合法系统 systemToken),直接放行;
  • 否则调用 Security.getUserIdFromToken(request) 解析 accessToken;解析异常或得到 null 时由 MessageSecurityFilter.responseUnauthorized 直接设置 HTTP 401无响应体);
  • 成功解析后 chain.doFilter 进入控制器。

accessToken 传递方式(据 cn.myapps.common.util.Security.getUserIdFromToken

按以下顺序查找:

  1. query 参数 accessToken
  2. query 参数 access_token(移动端兼容)
  3. 请求头 accessToken
  4. Cookie accessToken
  5. 请求头 Authorization: Bearer <token>

缺失或解析失败时由 MessageSecurityFilter 直接设置 HTTP 401无响应体)。

鉴权豁免(白名单)

CommWebMvcConfig.filterRegistrationBeanPassFilter1(order=HIGHEST_PRECEDENCE)显式列举的 URL 命中即标记 pass=true,跳过 MessageSecurityFilter,主要包括:

  • 模块首页://signon/manager/designer
  • 健康检查:/health/actuator/health/kms/health/ai/health
  • 登录/注销:/api/runtime/login/*/api/authtime/login/*/api/designtime/login/*/api/*/logout/api/debuglogin/*
  • runtime 取 token:/api/rest/accessToken/rest/accessToken/api/runtime/secrets/*
  • 静态资源后缀:.jpg .js .css .ico .png .gif .html .json .map .woff2 .woff .ttf .eot .svg .mpg .mp4 .mp3 .wav .avi .flv .m3u8 .m3 .ts
  • magic-api:/magic-api/*/obpm/magic-api/*

message 模块所有控制器路径(/api/message/**/runtime/messages/**均不在白名单内,故全部端点需 accessToken(或合法 systemToken 内部调用)。

执行用户

  • BaseController.getUser()(CommentController / MessageController / NoticeController / NotificationController 继承):先 Security.getUserIdFromToken(request),失败再 Security.getDebugUserIdFromToken(request)(取 debugToken),然后经 Feign(UserAPI.getUserById)装载 MessageUser
  • AbstractRuntimeController.getUser()(runtime MessageController 继承):仅 Security.getUserIdFromToken(request) 装入 MessageUser(仅设置 id),不回退 debugToken,不调 Feign。

完整鉴权机制与错误码说明见:顶层 index.md

响应结构与错误码

message 模块控制器分属**两套响应风格**(按基类区分):

风格一:Map 结构(继承 BaseController

BaseController.addActionResult(isSuccess, data) 产生,序列化为 JSON:

{
  "status": 1,
  "message": "ok",
  "data": <任意>
}
字段 类型 说明
status int 1=成功,0=失败
message string "ok" 或 "error"
data object/null 业务数据(data==null 时不写入该字段,因类级 @JsonSerialize(Inclusion.NON_NULL)

与顶层 index.md「统一响应结构 Resource」不同——BaseController 系列控制器返回 Mapstatus/message/data),不是 Resourceerrcode/errmsg/data/errors)。本风格涵盖 CommentController、MessageController(消息域)、NoticeController、NotificationController。

这些控制器内 try/catch 捕获 Exception 后返回 status=0, message="error", data=null,HTTP 状态码仍为 200;个别方法(MessageController.doCreateMessageNoticeController.doCreateNotificationController.doCreate)返回 void,无响应体。

风格二:Resource 结构(继承 AbstractRuntimeController

AbstractRuntimeController.success("ok", data) 产生,与顶层 index.md「统一响应结构 Resource」一致:

{
  "errcode": 0,
  "errmsg": "ok",
  "data": <任意>,
  "errors": null
}

本风格仅 runtime MessageController 使用,并经 AbstractRuntimeController@ExceptionHandler 统一映射异常。

错误码补充

message 模块**未引入模块专属业务错误码**。鉴权层引入以下与统一 Resource 不同的纯 HTTP 状态码:

errcode / status HTTP 含义
401 401 accessToken 缺失或失效(由 MessageSecurityFilter 直接设置状态码,无响应体
405 405 HTTP 方法不被允许(由 CommonSecurityFilter 拦截,仅允许 GET/POST/HEAD/OPTIONS,返回 HTML 错误页)
200 BaseController 系列控制器业务异常:status=0, message="error", data=null(HTTP 状态仍 200)
0 200 runtime MessageController 成功
404 404 runtime MessageController 抛 ResourceNotFoundException
500 500 runtime MessageController 抛 RuntimeException / OBPMValidateException
40035 406 runtime MessageController 参数类型不匹配(MethodArgumentTypeMismatchException
406 406 runtime MessageController 请求包体解析错误(PathNotFoundException

覆盖说明

本阶段覆盖 obpm-message 工作树下的 CommentController(消息评论,6 个端点)、MessageController(消息域)(消息/公告 CRUD,9 个端点,含创建站内消息、消息列表、公告列表、附件预览)、NoticeController(事项提醒通知,5 个端点,含已读/全部已读、/read 端点 @Deprecated)、NotificationController(消息中心通知,7 个端点,含 2 个 SseEmitter SSE 实时推送端点 /count/watch/count/listen,根 GET 端点 @Deprecated)、MessageController(runtime 消息中心)(轻量通知事项 API,4 个端点,返回统一 Resource)。除抽象基类 BaseController<E>AbstractRuntimeController(不单独成文)与无端点的 HtmlEditUploadController 外,message 模块有端点控制器已**全部覆盖**。