TMS (Teamwork Management System) — 基于频道模式的团队沟通协作 + 轻量级任务看板 + 团队博文 Wiki + i18n 国际化翻译管理的响应式 Web 开源平台。
本面向开发者与运维人员,深入解读 TMS 的代码结构、架构设计、核心模块实现、安全机制、实时通讯、数据模型、API 设计、部署运维等关键技术细节,便于二次开发、定制化与维护。
| 维度 | 说明 |
|---|---|
| 项目名称 | TMS (Teamwork Management System) |
| GroupId / ArtifactId | com.lhjz / tms |
| 版本 | 1.0.0-SNAPSHOT |
| 主类 | Application.java |
| 打包方式 | war(可独立运行也可部署到外部 Tomcat) |
| 代码仓库 | GitHub / Gitee |
| 许可证 | MIT |
| 技术 | 版本 | 用途 |
|---|---|---|
| Java | 1.8 | 主开发语言 |
| Spring Boot | 2.4.13 | 应用框架(parent POM) |
| Spring Security | 跟随 Boot | 认证授权 |
| Spring Security OAuth2 | 2.4.1 | OAuth2 客户端 / 资源服务 |
| Spring Data JPA | 跟随 Boot | 数据访问层 |
| Spring WebSocket (STOMP) | 跟随 Boot | 实时通讯 |
| Thymeleaf | 跟随 Boot | 服务端模板引擎 |
| Spring Boot Actuator | 跟随 Boot | 运行时监控 |
| Lombok | 跟随 Boot | 实体样板代码精简 |
| Fastjson | 1.2.83 | JSON 序列化 |
| Gson | 跟随 Boot | JSON 处理 |
| markedj | 1.0.9 | Markdown 解析(服务端渲染) |
| Apache POI (poi-ooxml) | 3.17 | Excel 导入导出 |
| OpenCSV | 4.1 | CSV 解析 |
| Jsoup | 1.15.3 | HTML 解析与清洗 |
| Mammoth | 1.4.0 | Word (.docx) 文档解析 |
| Commons IO / BeanUtils / Lang | 2.14.0 / 1.9.4 / 2.6 | 通用工具 |
| Janino | 3.1.7 | 运行时表达式编译 |
| joda-time | 2.10.14 | 日期处理 |
| OGNL | 3.1.29 | 表达式求值(修复 NoClassDefFoundError) |
HTML5 / CSS3 / JavaScript、Bootstrap、Vue.js、Markdown 编辑器、思维导图 / 白板 / 画图 / 在线表格(LuckySheet 等)、FontAwesome 图标。前端工程独立维护后压缩打包进主仓库 src/main/resources/static。
prod-pg profile 切换)Dockerfile 基于 tomcat:8.5.73-jdk8)、Docker Compose、Kubernetes源码根包:com.lhjz.portal,详见 src/main/java/com/lhjz/portal。
com.lhjz.portal
├── Application.java # Spring Boot 启动类
├── ServletInitializer.java # WAR 部署到外部容器时的初始化器
├── base/ # 基础设施层
│ ├── BaseController.java # 控制器基类(日志、用户、异常处理)
│ ├── BaseDao.java # DAO 基类
│ └── BaseService.java # 服务基类
├── component/ # 组件层(Spring 组件 / 拦截器 / 处理器)
│ ├── core/ # 核心组件抽象(IChatMsg / MailQueue 等)
│ ├── Ajax*Handler.java # Ajax 感知的登录/登出/成功/失败处理器
│ ├── LoginSuccessHandler.java
│ ├── SpringSecurityAuditorAware.java # JPA 审计人填充
│ ├── TmsUserApprovalHandler.java # OAuth2 用户授权审批
│ ├── WsChannelInterceptor.java # WebSocket 入站通道拦截器
│ ├── WsHandshakeInterceptor.java # WebSocket 握手拦截器
│ ├── AsyncTask.java # 异步任务执行器
│ ├── CustomApplicationRunner.java # 启动后初始化任务
│ ├── MailSender / CustomMailSender.java # 邮件发送
│ └── ...
├── config/ # 配置层
│ ├── SecurityConfig.java # Spring Security 安全配置
│ ├── WsConfig.java # WebSocket (STOMP) 配置
│ ├── BeanConfig.java # 通用 Bean 配置
│ ├── DataInitConfig.java # 数据初始化
│ └── OAuth2ClientConfig.java # OAuth2 客户端配置
├── constant/
│ └── SysConstant.java # 系统常量
├── controller/ # 表现层(REST 控制器)
├── entity/ # JPA 实体(领域模型)
│ └── security/ # 安全相关实体(User / Authority / Group / OAuth2)
├── exception/
│ └── BizException.java # 业务异常
├── model/ # 传输模型 / DTO / Payload
├── pojo/ # 表单 / 枚举 / 排序对象
├── repository/ # Spring Data JPA 仓储
├── service/ # 业务服务层
│ └── impl/ # 服务实现(含分布式锁实现等)
└── util/ # 工具类(30+ 工具类)
src/main/resources/
├── application*.properties # 多环境配置
├── logback.xml # 日志配置
├── messages*.properties # i18n 消息资源
├── static/ # 前端静态资源(前端工程打包产物)
│ ├── image / img / fonts /
│ └── page/ # 前端源码与构建产物
└── md2pdf/ # Markdown 转 PDF 的 Node.js 子工程
├── index.js
└── package.json
TMS 是典型的 Spring Boot 分层 Web 应用,结合 STOMP over WebSocket 实现实时能力。
┌─────────────────────────────────────────────────────┐
│ 浏览器 / 移动端(Bootstrap + Vue.js 响应式 SPA) │
└───────────────┬──────────────────────┬──────────────┘
HTTP / HTTPS WebSocket (STOMP/SockJS)
│ │
┌───────────────▼──────────────────────▼──────────────┐
│ 表现层 Controller(@RestController) │
│ AdminController / ChatController / BlogController │
│ TranslateController / TodoController / ... │
└───────────────┬──────────────────────────────────────┘
│
┌───────────────▼──────────────────────────────────────┐
│ 业务层 Service(含分布式锁 BlogLock) │
│ ChatChannelService / ChannelService / FileService │
└───────────────┬──────────────────────────────────────┘
│
┌───────────────▼──────────────────────────────────────┐
│ 数据访问层 Spring Data JPA Repository(30+ 个) │
└───────────────┬──────────────────────────────────────┘
│
┌───────────────▼──────────────────────────────────────┐
│ MySQL / PostgreSQL (HikariCP 连接池) │
└──────────────────────────────────────────────────────┘
Application.java 使用 @SpringBootApplication 进行组件扫描与自动装配,并注册 OpenEntityManagerInViewFilter 以在视图渲染阶段保持 JPA EntityManager 开放(解决懒加载异常)。生产以 WAR 部署时由 ServletInitializer 完成 Spring Boot servlet 初始化。
启动后由 CustomApplicationRunner 执行数据初始化等任务(与 DataInitConfig 配合)。
SecurityConfig.java 是安全核心,采用两套 WebSecurityConfigurerAdapter 链(通过 @Order 区分优先级,仅在 dev / prod / prod-pg profile 下激活):
/admin/**、/api/**、/ws/**,要求认证;其余静态资源(/admin/css/**、/admin/img/**、/landing/**、/page/** 等)放行。/admin/login,登录处理 URL /admin/signin,登出 /admin/logout。AjaxSimpleUrlAuthenticationFailureHandler、LoginSuccessHandler),便于前后端分离式交互。JdbcTokenRepositoryImpl 持久化令牌,有效期 14 天(1209600 秒)。/ 与 /free/** 放行,供公开访问。密码编码器 PasswordEncoder 在 BeanConfig 中定义,认证用户来源为 JDBC(auth.jdbcAuthentication().dataSource(...)),用户表为 User、Authority、PersistentLogin。
SpringSecurityAuditorAware 实现 AuditorAware,从 SecurityContext 取当前用户名注入到实体的 @CreatedBy / @LastModifiedBy;配合 @CreatedDate / @LastModifiedDate 与 @EntityListeners(AuditingEntityListener.class) 实现自动审计字段填充(见 Blog.java 等实体)。
OAuth2ClientConfig + TmsUserApprovalHandler 提供 OAuth2 客户端与资源服务能力,相关实体位于 entity/security/oauth2/(OauthClientDetails、OauthAccessToken、OauthRefreshToken、OauthCode 等)。
GroupMember 关联用户,通过 GroupAuthority 关联权限,实现基于组的批量授权。@EnableGlobalMethodSecurity(securedEnabled = true) 启用,可使用 @Secured 注解。WsConfig.java:
/channel(频道消息)、/direct(私聊)、/blog(博文动态)。/chat(客户端发送消息前缀)。/ws、/ws-lock,setAllowedOriginPatterns("*") 跨域,withSockJS() 提供 SockJS 回退。WsChannelInterceptor,在消息进入业务前做认证 / 鉴权 / 上下文处理。component/core/ 定义消息处理抽象:
IChatMsg / ChatMsgImpl — 频道消息处理实现,将 STOMP 消息持久化并广播。MailQueue / MailQueueImpl / MailItem — 异步邮件队列,将通知邮件排队发送。ChatMsgItem — 单条聊天消息的内部表示。广播通过 SimpMessagingTemplate.convertAndSend("/channel/xxx", payload) 推送,前端订阅对应目的地即可实时接收。
实体位于 entity 包,使用 JPA 注解 + Lombok,统一审计字段。共 30+ 实体,按业务域分组:
| 实体 | 说明 |
|---|---|
| User | 用户,含用户名、密码(加密)、邮箱、头像、在线状态等 |
| Authority / AuthorityId | 用户直接权限(复合主键) |
| Group | 用户组 |
| GroupAuthority / GroupMember | 组权限 / 组成员 |
| PersistentLogin | Remember-Me 持久化令牌 |
| oauth2/* | OAuth2 客户端、令牌、授权码、审批 |
| 实体 | 说明 |
|---|---|
| Channel | 频道 |
| ChannelGroup | 频道分组 |
| Chat | 聊天消息基类(内容、类型、时间) |
| ChatChannel | 频道消息(关联频道) |
| ChatDirect | 一对一私聊 |
| ChatAt | @ 提及 |
| ChatReply | 消息回复(话题二级) |
| ChatLabel / Label | 消息标签 |
| ChatPin | 固定消息 |
| ChatStow | 收藏消息 |
| ChatChannelFollower | 频道关注 |
| 实体 | 说明 |
|---|---|
| Blog | 博文,唯一约束 uuid,索引 title / uuid / shareId,支持 BlogType(Markdown / 富文本 / 表格 / 思维导图 / 画图 / 白板)、Editor、Status、父子嵌套、版本号 @Version 乐观锁 |
| BlogAuthority | 博文权限 |
| BlogFollower | 博文关注 |
| BlogHistory | 历史版本(支持比较与回退) |
| BlogNews | 博文动态流 |
| BlogStow | 博文收藏 |
| Space / SpaceAuthority | 博文空间与空间权限 |
| Dir | 博文目录(拖拽排序、五级嵌套) |
| Tag | 博文标签 |
| Comment | 评论(含评论投票) |
| File | 上传文件实体 |
| 实体 | 说明 |
|---|---|
| Todo | 待办事项 |
| Schedule | 日程安排与提醒 |
| Gantt | 甘特图(项目规划) |
| Project | 翻译项目 / 业务项目 |
| Link | 频道外链 |
| 实体 | 说明 |
|---|---|
| Translate | 翻译项目 |
| TranslateItem | 翻译条目 |
| TranslateItemHistory | 翻译历史 |
| Language | 语言定义 |
| 实体 | 说明 |
|---|---|
| Log | 操作审计日志(Action + Target + targetId) |
| Setting | 系统设置 |
| Feedback | 用户反馈 |
BaseController 提供 log(Action, Target, targetId, ...) 方法,将关键操作统一写入 Log 实体,形成完整操作变更历史。Action / Target 为枚举(见 pojo/Enum.java),覆盖创建、更新、删除、登录、分享等动作与博文、频道、用户、翻译等目标对象。
控制器位于 controller 包,统一继承 BaseController,返回 RespBody(统一响应体)。主要控制器与路由前缀:
| 控制器 | 路由前缀 | 职责 |
|---|---|---|
| AdminController | admin/ |
后台管理、登录页、健康检查、用户/项目/语言/反馈/动态/翻译/导入/设置管理 |
| ApiController | api/ |
第三方集成入口(Jenkins 消息、外部应用消息投递到频道) |
| BlogController | admin/blog |
博文 CRUD、评论、权限、收藏、关注、历史、导出、投票、分享 |
| ChatController | admin/chat |
聊天消息收发与处理 |
| ChatChannelController | admin/chat/channel |
频道管理 |
| ChatDirectController | — | 私聊 |
| ChatLabelController | — | 消息标签 |
| ChannelController | — | 频道配置 |
| ChannelGroupController | — | 频道分组 |
| ChannelTaskController | — | 频道任务看板 |
| TranslateController | admin/translate |
翻译项目与条目管理、导入导出、Base64 |
| LanguageController | — | 语言管理 |
| TodoController | admin/todo |
待办事项 |
| ScheduleController | — | 日程 |
| GanttController | — | 甘特图 |
| SpaceController | — | 博文空间 |
| SpaceHomeController | free/space/home |
空间公开页 |
| FileController | — | 文件上传下载 |
| ImportController | admin/import |
CSV / Excel 导入为 Markdown 表格、导出 |
| HomeController | free/home |
公开博文列表 |
| RootController | / |
根路由、登录注册、公开 wiki |
| SettingController | — | 系统设置 |
| UserController | — | 用户管理 |
| UserTaskController | admin/user/task |
用户任务 |
| Oauth2ResourceController | — | OAuth2 资源接口 |
| FeedbackController | — | 用户反馈 |
admin/** — 需登录(受 Security 保护)。api/** — 受保护,对外集成接口(Jenkins 等)。ws/** — WebSocket 端点,需认证。free/** — 公开访问(着陆页、公开博文 / 空间)。所有接口统一返回 RespBody(见 model 包),BaseController 内通过 @ExceptionHandler 统一异常处理,把 BizException 等转换为标准 JSON 响应,前端据此做 Toastr 提示。
| 服务 | 接口 | 实现 | 职责 |
|---|---|---|---|
| ChatChannelService | 接口 | impl | 频道消息持久化与广播调度 |
| ChannelService | 接口 | impl | 频道生命周期管理 |
| FileService | 接口 | impl | 文件上传 / 下载 / 图片处理 |
| BlogLockService | 接口 | impl | 多人协作编辑时的分布式锁(基于 WebSocket 锁端点 /ws-lock) |
BlogLockServiceImpl 通过 WsLockPayload(model 包)在 /ws-lock 端点上协调多个客户端对同一篇博文的编辑权,避免并发覆盖;锁通过 WebSocket 心跳维持,断开自动释放。
util 包提供 30+ 工具类:
| 类 | 用途 |
|---|---|
| AuthUtil | 认证 / 当前用户获取 |
| DateUtil | 日期与时间(joda-time 封装) |
| FileUtil | 文件 IO(基于 commons-io) |
| ImageUtil | 图片缩放 / 头像处理 |
| ExcelUtil | POI Excel 读写(导入导出) |
| HtmlUtil | Jsoup HTML 清洗 / 转换 |
| JsonUtil | Fastjson / Gson 封装 |
| MapUtil / CollectionUtil | 集合操作 |
| SqlUtil | SQL 拼接与防注入 |
| SHA1 / EncoderUtil | 编码与摘要 |
| StringUtil | 字符串处理 |
| TemplateUtil | FreeMarker 模板渲染(邮件等) |
| WebUtil | Web 请求工具(IP、UA、Referer) |
| LuckySheetUtil | LuckySheet 在线表格数据解析 |
| ChineseUtil | 中文处理 |
| ValidateUtil | 校验工具 |
| ThreadUtil | 线程 / 异步工具 |
| 文件 | 说明 |
|---|---|
| application.properties | 主配置,默认 spring.profiles.active=dev,并 include=tms |
| application-dev.properties | 开发环境 |
| application-prod.properties | 生产(MySQL) |
| application-prod-pg.properties | 生产(PostgreSQL) |
| application-tms.properties | TMS 业务参数(共用) |
jdbc:mysql://localhost:3306/tms,HikariCP(最大池 30、最小空闲 10、连接超时 30s)。ddl-auto=update(自动维护表结构)、show-sql=false。server.port=80,context-path=/。cache=false(开发)、mode=HTML。base-path=/manage,默认关闭所有端点(enabled-by-default=false),按需开放。spring.mail.*(默认 163 邮箱)。client-id=tms / client-secret=tms,auto-approve-scopes=.*。default-property-inclusion=non-null。messages.properties / messages_en_US.properties — 系统级 i18n。spring.messages.basename=messages,views,编码 ISO-8859-1(Spring 默认)。mvn clean package 产出 target/tms-1.0.0-SNAPSHOT.war。spring-boot-maven-plugin 支持 repackage,war 可独立 java -jar 运行,也可部署到外部 Tomcat(spring-boot-starter-tomcat 为 provided,由容器提供)。
mvn clean package
# 将 war 部署到 Tomcat 8.5 webapps/ROOT.war
Dockerfile 即基于 tomcat:8.5.73-jdk8,将 war 复制到 webapps/ROOT.war。
docker-compose.yml 启动两个服务:web(TMS 应用,8090→8080)与 db(MySQL,3307→3306),通过 backend 网络互通。PostgreSQL 版本使用 docker-compose-pg.yml。
docker-compose up -d
k8s/deploy.yaml 定义 Deployment(单副本,含 tms-mysql 与 tms-tomcat 两个容器),k8s/svc.yaml 定义 Service。镜像来自 registry.cn-hangzhou.aliyuncs.com/xiweicheng/tms-*:v1。
| 脚本 | 说明 |
|---|---|
| deploy.sh | MySQL 部署脚本 |
| deploy-pg.sh | PostgreSQL 部署脚本 |
| deploy2local.sh | 本地部署脚本 |
| src/main/resources/deploy.sh | 容器内部署辅助 |
ddl-auto=update 维护表结构。http://localhost/tms(context-path 已改为 /,直接 http://localhost/)。http://localhost:8090/。log/tms/tms.log;代码中统一使用 SLF4J。/manage,默认关闭,需显式开启(可在生产 profile 中按需 management.endpoints.web.exposure.include=...)。Log 实体记录所有关键操作(创建 / 更新 / 删除 / 登录 / 分享等),可追溯。src/main/resources/md2pdf 是一个独立 Node.js 工程(package.json + index.js),用于将博文 Markdown 渲染为 PDF 导出,与后端 Java 进程协作完成导出能力(博文支持导出 PDF / Markdown / HTML / Excel / PNG)。
application-dev.properties 数据库连接。http://localhost/。entity/ 新增 JPA 实体(继承审计字段)。repository/ 新增 JpaRepository 接口。service/(+ impl/)新增业务服务。controller/ 新增 @RestController,继承 BaseController,返回 RespBody。log(Action, Target, targetId) 记录操作审计。SimpMessagingTemplate 推送实时消息到对应 Broker 目的地。@Data / @ToString,避免手写 getter/setter。RespBody,异常走 BaseController 统一处理。spring.servlet.multipart.* 限制,通过 FileService 统一处理。spring-boot-starter-test(排除 JUnit 4)、testng 6.8.13、spring-security-test、junit(test scope)。src/test/,可使用 TestNG 或 JUnit 编写单元 / 集成测试。json-path 用于对 JSON 响应做断言。validate 并使用迁移工具(如 Flyway / Liquibase)管理 schema。ognl:3.1.29 修复 NoClassDefFoundError。TMS 是一款功能完整、架构清晰的 Spring Boot 团队协作平台,覆盖沟通、博文 Wiki、i18n 翻译三大场景,具备实时通讯、细粒度权限、多人协同编辑、多格式导出、多数据库与多云部署能力。本技术文档可作为二次开发与运维的参考基线,建议配合 CODE_WIKI.md 与 FEATURES.md 一起阅读。