本文是 NRI 闭源 Java 商业框架全景 与 Spring MVC 核心机制深度解析 的姐妹篇。前两篇分别讲了”是什么”,这一篇讲**“区别在哪、为什么有这些区别、对你有什么用”**。
为什么这个对比值得专门写一篇
如果你正在对日 Java 圈子、或者准备从对日项目跳出去,这两组框架大概率你都会遇到:
- NRI ow+ / o3w:你当前在做的事;200+ 人的大型项目主流;规则严、迁移性弱;
- Spring MVC:全球 Java Web 事实标准;招聘必问;灵活、迁移性强;
- OW X(NRI 转型版):正在发生的过渡——底层切到 Spring,但规约还是 NRI 那套。
搞清楚两者的差异,等于搞清楚三件事:你的经验里哪些值钱、哪些会归零、哪些要被”翻译”成简历语言。
一页总览
| 维度 | NRI ow+ | Spring MVC |
|---|---|---|
| 出身 | 野村综研自研,闭源商业框架 | Rod Johnson 开源(现 VMware / Broadcom) |
| 时代 | 2009 正式发布;2000 前内部已用 | 2003 第一版;当前 6.x |
| 设计目标 | 标准化、规则强制、防人为错误 | 灵活、可插拔、生态丰富 |
| 调度入口 | ActionServlet(Front Controller,XML 配置) | DispatcherServlet(唯一 Servlet,注解配置) |
| 控制器 | Action 类(STUDIO 生成壳,PG 填业务) | @Controller 方法(开发者全程写) |
| 业务层 | Service + Logic 两层(壳 + 手写) | @Service 单层(DI 注入) |
| 数据层 | SQL 外部化(ow+ 专属配置) | MyBatis / JPA / JdbcTemplate |
| DTO 风格 | 每层专属 DTO,类型不同 | 一个 DTO 贯穿 |
| 配置方式 | Excel 定义表 → STUDIO 生成 | 注解 + application.yml |
| 视图层 | JSP + Taglib(2009 主流) | JSON / REST(2025 主流) |
| 异常处理 | SystemException / BusinessException + MessageID | @RestControllerAdvice + @ExceptionHandler |
| 拦截器 | ow+ 自定义拦截器接口 | HandlerInterceptor / Servlet Filter |
| 生态 | 几乎无(闭源) | 庞大(Spring 全家桶) |
| 上手成本 | 2 周做模块 | 1 天起步 |
| 可迁移性 | 弱(离开 NRI 项目归零) | 强(任何 Java 项目通用) |
下面从五个角度分别展开。
一、请求链路对比:流水线 vs 插拔
最直观的差异——同一个 GET /user/42,两个框架怎么走完。
ow+ 的设计哲学:让”每个环节该做什么”用 XML 配置 + 生成代码锁死,开发者只能按框架规定的方式填空。
Spring MVC 的设计哲学:只规定”入口和边界”,把”中间怎么做”以接口形式留给开发者扩展。
实际差异:
| 环节 | ow+ | Spring MVC |
|---|---|---|
| 入口配置 | web.xml 里配 ActionServlet + URL pattern | @SpringBootApplication 注解 + 自动注册 |
| URL → Handler | struts-config.xml / 框架自带配置 | @RequestMapping("/user/{id}") |
| 参数转换 | BeanUtils.copyProperties 框架自动 | HttpMessageConverter + 自定义 Converter |
| 业务入口 | Action 类继承自框架基类 | 普通 POJO + @Controller 注解 |
| 业务层 | Service(壳)+ Logic(手写) | @Service 一层搞定 |
| 视图返回 | 字符串逻辑视图名 → ViewResolver | @ResponseBody 直接写 JSON,跳过视图 |
| 拦截器 | XxxInterceptor 继承自框架接口 | HandlerInterceptor 实现 pre/post/after |
关键观察:ow+ 的链路是封闭式流水——每一站都有”必须这样做”的规定;Spring MVC 的链路是开放式接力——每一站都有”可以这样做”的口子。两种风格没有绝对优劣,前者适合 200 人外包团队,后者适合 3-10 人的敏捷团队。
二、核心组件对比:可见的工具 vs 隐形的接口
ow+ 的核心调度其实是 STUDIO——你看不到它,但它生成的代码决定了所有组件怎么工作。
Spring MVC 的核心调度是 DispatcherServlet——所有”我该找谁干活”的问题都由它处理,并且所有参与者都是接口,可以替换。
具体差异:
| 组件 | ow+ | Spring MVC |
|---|---|---|
| 调度中心 | STUDIO(离线工具)+ ActionServlet(运行时) | DispatcherServlet |
| URL 路由 | XML 配置文件(编译期固化) | HandlerMapping 接口(运行时计算) |
| Handler 适配 | 不需要适配器(Action 都继承同一基类) | HandlerAdapter 接口(多种 Handler 形态可共存) |
| 视图解析 | struts-config.xml 配前缀后缀 | ViewResolver 接口链(Thymeleaf/Freemarker/PDF…) |
| 数据转换 | Action 框架基类自动处理 | HttpMessageConverter(Jackson / JAXB / Form) |
| 拦截器 | 框架自定义接口 | HandlerInterceptor 标准三方法 |
Spring MVC 设计上更”面向接口”——这是它能演进出 WebFlux、GraphQL、gRPC 等各种变体的根本原因;ow+ 想扩展一个新东西(比如改用 Thymeleaf),得动框架本身,难度完全不在一个量级。
三、DTO 流转对比:一对多 vs 一对一
这是我见过最容易引发争论的差异——
ow+ 强制每层用不同类型的 DTO:画面 DTO、Action DTO、Service DTO、Logic DTO、DAO DTO,五个。
Spring MVC 几乎不限制:一个 UserDTO 从 Controller 走到 Service 再到 Repository,全程复用。
为什么要这么设计?两套逻辑完全不同:
ow+ 的逻辑:用”类型不同”做编译期防火墙——Service 层只能拿到 Service DTO,画面字段根本传不到业务层,靠编译器防止越层。
Spring MVC 的逻辑:用”职责划分”做软约束——DTO 只是一个数据载体,靠团队规约和 code review 防止越层。
实际代价:
| 代价 | ow+ | Spring MVC |
|---|---|---|
| 模板代码 | 大量(5 个 DTO + 字段映射) | 几乎无 |
| IDE 友好度 | 字段改名要改 5 处 | 改一处 |
| 学习曲线 | 陡(要搞清 5 个 DTO 的关系) | 平(一个类走到底) |
| 安全性 | 强(编译器兜底) | 弱(靠人) |
| 性能 | 差(多了几次属性拷贝) | 好 |
| 适合规模 | 200+ 人外包 | 3-50 人敏捷 |
OW X 的折中:沿用 Spring 风格(一个 DTO 走到底),但引入自家规约做补救——比如规定 Service 层的返回值必须是另一个 XxxOutDTO,用 code review + 静态检查工具兜底。这是 2020 年后 NRI 项目的实际做法。
四、开发范式对比:流水线 vs 单兵
ow+ 的开发是流水线:
SE 写 Excel 定义表 → STUDIO 生成代码 → PG 在生成代码里填空 → 单体测试
Spring MVC 的开发是单兵:
开发者写 Controller 方法 → 启动 Spring Boot → MockMvc 单测 → Postman 联调
这是角色分工的根本差异:
| 角色 | ow+ 项目 | Spring MVC 项目 |
|---|---|---|
| 系统设计 | SE(专门的人) | 开发者自己 |
| 代码生成 | STUDIO(工具) | 不需要 |
| 业务实现 | PG(专门的人) | 开发者自己 |
| 测试 | PG 单测 | 开发者 + QA |
ow+ 这种角色分工适合大型外包项目——SE 把设计做完、PG 把代码填好,分工明确、上手快、产出稳定;但代价是个人成长受限:PG 写三年可能都不会设计一个完整的业务模块。
Spring MVC 这种”单兵”模式适合产品团队——每个人都从设计做到上线,能力成长快;但代价是对个人能力要求高:你得懂架构、懂业务、懂测试。
五、八大维度详细对比
1. 控制器与路由
// ow+ Action(继承框架基类)
public class UserSearchAction extends BaseAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest req, HttpServletResponse res) {
UserSearchForm f = (UserSearchForm) form;
List<UserDTO> users = userService.search(f.getKeyword());
req.setAttribute("users", users);
return mapping.findForward("success");
}
}
// Spring MVC Controller(普通 POJO)
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/search")
public List<UserDTO> search(@RequestParam String keyword) {
return userService.search(keyword);
}
}
ow+ 的 Action 必须继承基类(受约束),方法签名固定(不能选参数);Spring MVC 的 Controller 任何类都行,方法签名随便写。
2. 数据绑定
// ow+:画面提交自动绑定到 FormBean(由 Excel 定义)
// FormBean 字段上由 STUDIO 根据 Excel 注解加上校验
public class UserSearchForm extends ActionForm {
private String keyword; // STUDIO 已加 @NotBlank
// getter / setter
}
// Spring MVC:@RequestParam / @PathVariable / @RequestBody 显式声明
@GetMapping("/search")
public List<UserDTO> search(@RequestParam(required = false) String keyword) { ... }
@PostMapping("/save")
public Result save(@Valid @RequestBody UserSaveDTO dto) { ... }
Spring MVC 把”绑定什么”完全交给开发者写注释,更灵活但也更容易漏。
3. 事务管理
<!-- ow+:在 XML 配置 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
// Spring:注解声明
@Transactional(rollbackFor = Exception.class)
public void saveOrder(OrderDTO order) { ... }
ow+ 的 XML 事务更”集中”,适合全局策略统一;Spring 的 @Transactional 更”就近”,但容易出现自调用失效、AOP 不生效等陷阱。
4. 异常处理
// ow+:throw BusinessException 携带 MessageCode
throw new BusinessException("E00101", "余额不足");
// 框架自动翻译成用户可见的错误页
// Spring:@RestControllerAdvice + @ExceptionHandler
@RestControllerAdvice
public class GlobalHandler {
@ExceptionHandler(InsufficientBalanceException.class)
public Result<Void> handle(InsufficientBalanceException e) {
return Result.fail("E00101", "余额不足");
}
}
两者本质一样,Spring 的方式更显式、更易测试;ow+ 的方式更”约定俗成”——但新人不知道有哪些 MessageCode,需要查文档。
5. SQL 与数据层
// ow+:SQL 写在特定 XML 里
// UserDao.xml.xml
<select id="searchByKeyword" resultClass="UserDTO">
SELECT * FROM T_USER WHERE NAME LIKE '%' || ? || '%'
</select>
// Spring + MyBatis(ow+ 的很多设计参考自 MyBatis)
@Mapper
public interface UserMapper {
@Select("SELECT * FROM t_user WHERE name LIKE CONCAT('%', #{kw}, '%')")
List<UserDTO> searchByKeyword(@Param("kw") String keyword);
}
ow+ 的 SQL 写在专属 XML 文件,与 MyBatis 思想同源——这个事实很多人不知道。学 ow+ 的 SQL 经验直接等于学 MyBatis。
6. 视图层
| 时代 | ow+ | Spring MVC |
|---|---|---|
| 2009 | JSP + Struts Taglib(主流) | JSP + Spring Taglib |
| 2015 | 仍是 JSP 为主 | 开始大量用 Thymeleaf |
| 2020 | JSP + 部分 Thymeleaf 改造 | JSON / REST 主导 |
| 2025 | OW X 项目:前后端分离为主 | 几乎纯 REST |
ow+ 的视图层是”时代遗物”——2009 主流的 JSP + Taglib 在 2025 年已经边缘化。OW X 项目的视图层实际上已经是前后端分离的 React/Vue + REST。
7. 拦截器与过滤器
// ow+:继承框架的拦截器接口
public class AuthInterceptor extends AbstractInterceptor {
protected String doIntercept(ActionInvocation inv) throws Exception {
// 检查登录
if (notLoggedIn(inv)) {
return "login"; // 返回逻辑视图名
}
return inv.invoke();
}
}
// Spring:实现 HandlerInterceptor
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
// 检查登录
if (notLoggedIn(req)) {
res.sendRedirect("/login");
return false;
}
return true;
}
}
结构相似,Spring 多了 preHandle 返回 false 的短路能力,更灵活。
8. 测试
| 维度 | ow+ | Spring MVC |
|---|---|---|
| 单测入口 | extends BaseActionTest,手动 mock Service | @WebMvcTest + @MockBean |
| 不启容器 | 是(ow+ 单元测试不依赖 AP Server) | @WebMvcTest 启用 MockMvc 不启 Tomcat |
| 集成测试 | 起 ow+ 测试容器 | @SpringBootTest(webEnvironment = RANDOM_PORT) |
| 覆盖率工具 | 自家规约工具 | JaCoCo / SonarQube |
ow+ 单元测试不依赖 AP Server 是 2009 年时一大卖点(参日経 xtech 2009 报道);Spring MVC 的 @WebMvcTest 在 2014 年后也达到了同等效果。
六、可迁移性矩阵:你换工作时哪些经验能用
这是全文最实用的一张图——你下次面试的时候,按这张图定位自己的”卖点”。
绿区(跨行业通用):任何 Java 岗都用得上,简历上直接强调:
- 分层架构思想、单一职责
- 复杂 SQL 调优(手写 SQL 的硬功夫)
- REST / 前后端分离设计
- 测试金字塔意识
- 拦截器 / 过滤器 / AOP 的取舍
橙区(行业可迁移):保险 / 金融 / 对日开发圈能用:
- ow+ 的分层与异常码体系(翻译成”统一异常处理”)
- 大规模团队协作经验
- 对日开发规范(設計書レビュー・単体テスト・障害対応)
- DTO 契约设计
红区(NRI 项目专属):换工作立即归零——简历上少写或换种说法:
- STUDIO 工具操作
- o3w / ow+ 版本号
- Action/Service/Logic 类名
一句话翻译术:把”我在 ow+ 项目里填了 3 年 Action 代码”翻译成”我做过 3 年大型金融系统的 Web 后端开发,深入理解分层架构、复杂 SQL 调优和统一异常处理”——招聘官立刻听懂。
七、OW X 是怎么取两者之长的
OW X 是 NRI 在 2018 年推出的过渡框架——它本质上就是 Spring Boot 加一层 NRI 规约。我在两篇文章里都提过,这里把”它具体怎么融合两者”展开:
| 维度 | OW X 的做法 |
|---|---|
| 底层 | Spring Boot 3.x + Spring Security + Spring Cloud(部分项目) |
| 控制器 | @Controller / @RestController(Spring 风格) |
| 业务层 | @Service(Spring 风格)+ NRI 的”Logic 切分”习惯保留 |
| DTO | 一个 DTO 贯穿(Spring 风格)+ NRI 规约要求”服务层 DTO 与 Repository 层分开” |
| 异常 | @RestControllerAdvice(Spring)+ MessageID 体系(NRI 保留) |
| 视图 | 前后端分离为主,老模块保留 JSP |
| 拦截器 | HandlerInterceptor(Spring)+ NRI 规约的”必须有的拦截器清单” |
| 部署 | Docker / Kubernetes(Spring Boot 友好) |
| 安全 | Spring Security + NRI 自家 ID/角色体系 |
| 长期支持 | NRI 承诺 10 年 LTS(涵盖 Spring 与相关 OSS) |
OW X 项目对你的意义:
- 你学 ow+ 的分层思想、SQL 经验、复杂业务设计——这些都迁移到 OW X 继续有用;
- 你学 ow+ 的 STUDIO 操作、Action 继承——这些归零;
- 你需要主动补 Spring 经验——OW X 项目里”会用 Spring 全家桶”的人正在变成抢手资源。
八、给求职面试的回答模板
把这两组框架讲清楚,等于把自己的对日经验翻译成市场语言。面试时这么这样讲:
8.1 当面试官问”你用过什么框架”
"我过去 4 年在 NRI 体系的 ow+ 项目里做 Java 后端开发,这个项目是日方的闭源框架,
底层基于 Java EE。它的分层和异常处理设计得很严谨——每个业务模块都有
Action、Service、Logic 三层,每层用不同的 DTO 类型做隔离。
最近一年项目在做 OW X 迁移,底层切到 Spring Boot,
我也在补 Spring 全家桶的经验。
我认为 ow+ 的强约束和 Spring 的灵活性我都熟悉,能适应不同的团队风格。"
8.2 当面试官问”ow+ 和 Spring 区别”
直接对照本文第三、四、五节挑你最熟的两个维度讲:
"我理解下来最大的差异在两点:
一是 DTO 设计——ow+ 强制每层一个 DTO,类型不同、靠编译器防越层;
Spring 一个 DTO 走到底,靠团队规约和 code review 防越层。
二是开发流程——ow+ 是 SE 填 Excel 定义表、STUDIO 生成代码、
PG 在生成代码里填业务;Spring 是开发者一个人写完 Controller 到 Service。
前者适合大规模外包、产出稳定,后者适合敏捷团队、成长快。"
8.3 当面试官追问”你从 ow+ 学到了什么”
"在 ow+ 项目里我学到最多的是三件事:
一是分层和边界——每层 DTO 不同确实繁琐,但防止了业务逻辑溢到画面层;
二是 SQL 调优——ow+ 用 SQL 外部化、不走全自动 ORM,
复杂报表 SQL 必须自己写,这块硬功夫我比较扎实;
三是大型团队协作——200+ 人项目怎么保证代码风格一致,
怎么靠工具而不是靠人来兜底规则。"
这三个全部落在绿区和橙区——是你简历上最值钱的卖点。
九、一页清单
请求链路:ow+ 流水线 / Spring MVC 插拔
组件分工:ow+ STUDIO 隐形调度 / Spring MVC 接口可见
DTO 流转:ow+ 每层专属 / Spring MVC 贯穿
开发范式:ow+ SE + PG / Spring MVC 单兵
异常处理:ow+ MessageID / Spring @RestControllerAdvice
SQL 风格:ow+ 专属 XML / Spring + MyBatis 同源思想
视图层:ow+ JSP 为主 / Spring REST 为主
拦截器:ow+ AbstractInterceptor / Spring HandlerInterceptor
测试:ow+ 不启 AP Server / Spring @WebMvcTest
迁移性:ow+ 弱(离开 NRI 归零)/ Spring 强(跨项目通用)
OW X:取两者之长,Spring 底座 + NRI 规约
简历翻译:把 ow+ 经验翻译成"分层 + SQL + 团队协作"
后续可以挖的方向
- OW X 项目的具体规约(异常码体系、MDC 日志上下文、TraceId 传递)
- Spring Boot 3.x 在 OW X 项目里的应用
- 从 ow+ 转 Spring 的实战改造案例(已有项目如何平滑切换)
- MyBatis 与 ow+ SQL 外部化的细节对比
把本文第八节的三个模板背下来,能覆盖对日 Java 转型面试 80% 的框架类问题。
评论
还没有评论,来留第一条吧。