Java Web 技术演进:从 Servlet 到 Spring MVC 与阿里 ROP 全面对比
全面对比 Servlet、Struts2、Spring MVC 与阿里 ROP 的技术演进
目录
Java Web 开发技术经历了从传统的 Servlet/JSP 到 MVC 框架,再到 RESTful 服务框架的演进。本文深入对比 Tomcat Servlet、Struts2、Spring MVC 和阿里 ROP 四种技术方案。
一、技术概览
1.1 四种技术定位
| 技术 | 类型 | 出现时间 | 维护状态 | 定位 |
|---|---|---|---|---|
| Servlet/JSP | 基础规范 | 1997年 | 活跃(Jakarta EE) | Java Web 基石 |
| Struts2 | MVC 框架 | 2007年 | 维护中(Apache) | 企业级 MVC 框架 |
| Spring MVC | MVC 框架 | 2005年 | 活跃(Spring) | 现代化 MVC 框架 |
| 阿里 ROP | REST 框架 | 2012年 | 停止维护 | 开放平台接口框架 |
1.2 技术演进路线
1997年 2005年 2007年 2012年 2020年
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
Servlet ──────► Spring ───────► Struts2 ───────► 阿里ROP ───────► Spring Boot
│ MVC (REST) (自动配置)
│ │
▼ ▼
JSP Spring WebFlux
(模板引擎) (响应式编程)二、Tomcat Servlet(规范基石)
2.1 核心概念
Servlet 是 Java EE 规范的核心,定义了服务端处理 HTTP 请求的标准接口。
┌─────────────────────────────────────────┐
│ HTTP Request │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ Servlet Container │
│ ┌─────────────────────────────────┐ │
│ │ ServletContext(全局上下文) │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ HttpServletRequest │ │ │
│ │ │ HttpServletResponse │ │ │
│ │ └───────────┬─────────────┘ │ │
│ │ │ │ │
│ │ ┌───────────▼───────────┐ │ │
│ │ │ HttpServlet │ │ │
│ │ │ ┌─────────────────┐ │ │ │
│ │ │ │ doGet() │ │ │ │
│ │ │ │ doPost() │ │ │ │
│ │ │ │ service() │ │ │ │
│ │ │ └─────────────────┘ │ │ │
│ │ └───────────────────────┘ │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘2.2 基础代码示例
// 传统 Servlet 写法
@WebServlet(name = "UserServlet", urlPatterns = "/user")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1. 获取参数
String userId = req.getParameter("id");
// 2. 调用业务逻辑
UserService service = new UserService();
User user = service.findById(userId);
// 3. 设置响应
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
// 4. 手动拼接 JSON(痛苦!)
PrintWriter out = resp.getWriter();
out.print("{\"id\":\"" + user.getId() + "\",\"name\":\"" + user.getName() + "\"}");
out.flush();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1. 获取请求体
BufferedReader reader = req.getReader();
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
// 2. 手动解析 JSON(痛苦!)
String json = sb.toString();
// ... 复杂的解析逻辑
// 3. 调用业务逻辑
// ...
// 4. 返回响应
resp.setStatus(HttpServletResponse.SC_CREATED);
}
}2.3 Servlet 过滤器链
// 字符编码过滤器
@WebFilter(filterName = "EncodingFilter", urlPatterns = "/*")
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 继续下一个过滤器
chain.doFilter(request, response);
}
}
// 登录验证过滤器
@WebFilter("/admin/*")
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("user") == null) {
((HttpServletResponse) resp).sendRedirect("/login");
return;
}
chain.doFilter(req, resp);
}
}2.4 优缺点分析
| 优点 | 缺点 |
|---|---|
| 规范标准,所有框架底层都基于 Servlet | 开发效率低,样板代码多 |
| 学习成本低,理解 HTTP 处理原理 | 无 MVC 分层,代码耦合严重 |
| 性能高(直接操作请求响应) | 手动处理 JSON/XML 转换 |
| 过滤器、监听器机制完善 | URL 映射配置繁琐 |
| 生态成熟(Tomcat/Jetty/Undertow) | 无依赖注入,需手动管理对象 |
三、Struts2(企业级 MVC)
3.1 核心架构
Struts2 采用 拦截器栈(Interceptor Stack) 架构,基于过滤器实现。
┌─────────────────────────────────────────┐
│ HTTP Request │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ StrutsPrepareAndExecuteFilter │
│ (核心过滤器) │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ Interceptor Stack(拦截器栈) │
│ ┌─────────────────────────────────┐ │
│ │ 1. ParamsInterceptor │ │
│ │ 参数解析、类型转换 │ │
│ │ 2. ValidationInterceptor │ │
│ │ 数据校验 │ │
│ │ 3. FileUploadInterceptor │ │
│ │ 文件上传处理 │ │
│ │ 4. ExceptionMappingInterceptor │ │
│ │ 异常映射 │ │
│ └─────────────────────────────────┘ │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ Action(控制器) │
│ execute() / 自定义方法 │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ Result(结果处理) │
│ ┌──────────┬──────────┬────────────┐ │
│ │ dispatcher│ redirect │ stream │ │
│ │ (JSP) │ (重定向) │ (文件下载) │ │
│ └──────────┴──────────┴────────────┘ │
└─────────────────────────────────────────┘3.2 代码示例
// Action 类
public class UserAction extends ActionSupport implements ModelDriven<User> {
private User user = new User();
private List<User> userList;
private UserService userService = new UserService();
// 模型驱动,自动封装表单数据到 user 对象
@Override
public User getModel() {
return user;
}
// 查询列表
public String list() {
userList = userService.findAll();
return SUCCESS; // 对应 struts.xml 中的 result
}
// 查询详情
public String detail() {
user = userService.findById(user.getId());
if (user == null) {
return ERROR;
}
return SUCCESS;
}
// 新增用户
public String save() {
// 校验(使用 Validation 框架)
if (user.getName() == null || user.getName().isEmpty()) {
addFieldError("name", "用户名不能为空");
return INPUT;
}
userService.save(user);
addActionMessage("用户创建成功");
return SUCCESS;
}
// 删除用户
public String delete() {
userService.delete(user.getId());
return SUCCESS;
}
// Getters for JSP
public List<User> getUserList() {
return userList;
}
public User getUser() {
return user;
}
}<!-- struts.xml 配置 -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- 常量配置 -->
<constant name="struts.devMode" value="true"/>
<constant name="struts.action.extension" value="action,do,"/>
<constant name="struts.objectFactory" value="spring"/>
<!-- 包配置 -->
<package name="default" namespace="/" extends="struts-default">
<!-- 全局结果 -->
<global-results>
<result name="error">/error.jsp</result>
<result name="login" type="redirect">/login.jsp</result>
</global-results>
<!-- Action 配置 -->
<action name="user_*" class="com.example.action.UserAction" method="{1}">
<result name="success">/WEB-INF/jsp/user/{1}.jsp</result>
<result name="input">/WEB-INF/jsp/user/form.jsp</result>
<result name="list">/WEB-INF/jsp/user/list.jsp</result>
<!-- 拦截器配置 -->
<interceptor-ref name="defaultStack">
<param name="validation.excludeMethods">list,detail</param>
</interceptor-ref>
</action>
<!-- REST 风格配置 -->
<action name="api/user" class="com.example.action.UserRestAction">
<result type="json">
<param name="root">result</param>
</result>
</action>
</package>
</struts>3.3 OGNL 表达式
Struts2 使用 OGNL(Object-Graph Navigation Language)进行数据绑定。
<!-- JSP 页面使用 OGNL -->
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>用户列表</title></head>
<body>
<h1>用户管理</h1>
<!-- 迭代列表 -->
<table>
<tr>
<th>ID</th>
<th>姓名</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<s:iterator value="userList" var="user">
<tr>
<td><s:property value="#user.id"/></td>
<td><s:property value="#user.name"/></td>
<td><s:property value="#user.email"/></td>
<td>
<a href="user_detail.action?id=<s:property value='#user.id'/>">查看</a>
<a href="user_delete.action?id=<s:property value='#user.id'/>">删除</a>
</td>
</tr>
</s:iterator>
</table>
<!-- 表单 -->
<s:form action="user_save" method="post">
<s:textfield name="name" label="用户名" required="true"/>
<s:password name="password" label="密码"/>
<s:textfield name="email" label="邮箱"/>
<s:submit value="保存"/>
</s:form>
<!-- 显示错误信息 -->
<s:fielderror/>
<s:actionmessage/>
</body>
</html>3.4 优缺点分析
| 优点 | 缺点 |
|---|---|
| 完整的 MVC 分层,职责清晰 | 配置繁琐(XML/注解混合) |
| 强大的拦截器机制 | OGNL 学习曲线陡峭 |
| 内置丰富的标签库 | 历史漏洞较多(需及时更新) |
| 与 Spring 集成良好 | 已被 Spring MVC 取代主流地位 |
| 插件丰富(JSON/REST/文件上传) | 开发效率低于现代框架 |
| Convention over Configuration | 启动速度较慢 |
四、Spring MVC(现代标准)
4.1 核心架构
Spring MVC 基于 DispatcherServlet,采用注解驱动开发。
┌─────────────────────────────────────────┐
│ HTTP Request │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ DispatcherServlet │
│ (前端控制器) │
│ ┌─────────────────────────────────┐ │
│ │ HandlerMapping │ │
│ │ (URL → Controller 映射) │ │
│ │ @RequestMapping("/users") │ │
│ └─────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ HandlerAdapter │ │
│ │ (调用 Controller 方法) │ │
│ └─────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ Controller (@Controller) │ │
│ │ @GetMapping("/{id}") │ │
│ │ public User get(@PathVariable)│ │
│ └─────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ ModelAndView / @ResponseBody │ │
│ └─────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ ViewResolver │ │
│ │ (视图解析器) │ │
│ │ InternalResourceViewResolver │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘4.2 代码示例
// Controller 类
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private UserMapper userMapper;
// GET /api/users
@GetMapping
public ResponseEntity<PageResult<UserDTO>> list(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String keyword) {
Page<User> userPage = userService.findAll(PageRequest.of(page - 1, size), keyword);
List<UserDTO> dtoList = userMapper.toDTOList(userPage.getContent());
return ResponseEntity.ok(PageResult.of(dtoList, userPage.getTotalElements()));
}
// GET /api/users/{id}
@GetMapping("/{id}")
public ResponseEntity<UserDTO> getById(@PathVariable Long id) {
User user = userService.findById(id);
if (user == null) {
throw new ResourceNotFoundException("User not found: " + id);
}
return ResponseEntity.ok(userMapper.toDTO(user));
}
// POST /api/users
@PostMapping
public ResponseEntity<UserDTO> create(
@Valid @RequestBody UserCreateRequest request) {
User user = userMapper.toEntity(request);
User saved = userService.save(user);
URI location = ServletUriComponentsBuilder
.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(saved.getId())
.toUri();
return ResponseEntity.created(location)
.body(userMapper.toDTO(saved));
}
// PUT /api/users/{id}
@PutMapping("/{id}")
public ResponseEntity<UserDTO> update(
@PathVariable Long id,
@Valid @RequestBody UserUpdateRequest request) {
User user = userService.findById(id);
if (user == null) {
throw new ResourceNotFoundException("User not found: " + id);
}
userMapper.updateEntity(user, request);
User updated = userService.save(user);
return ResponseEntity.ok(userMapper.toDTO(updated));
}
// DELETE /api/users/{id}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build();
}
// 文件上传
@PostMapping("/{id}/avatar")
public ResponseEntity<String> uploadAvatar(
@PathVariable Long id,
@RequestParam("file") MultipartFile file) {
String url = userService.uploadAvatar(id, file);
return ResponseEntity.ok(url);
}
}4.3 全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
// 处理资源不存在
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException e) {
ErrorResponse error = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
e.getMessage(),
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
// 处理参数校验失败
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException e) {
List<String> errors = e.getBindingResult()
.getFieldErrors()
.stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.collect(Collectors.toList());
ErrorResponse error = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
"Validation failed",
errors,
LocalDateTime.now()
);
return ResponseEntity.badRequest().body(error);
}
// 处理其他异常
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGeneric(Exception e) {
log.error("Unexpected error", e);
ErrorResponse error = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
"Internal server error",
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}4.4 拦截器与配置
// 拦截器
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String token = request.getHeader("Authorization");
if (token == null || !JwtUtil.validate(token)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("{\"error\":\"Unauthorized\"}");
return false;
}
return true;
}
}
// 配置类
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/auth/**", "/api/public/**");
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.maxAge(3600);
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 配置 JSON 转换器
MappingJackson2HttpMessageConverter converter =
new MappingJackson2HttpMessageConverter();
converter.getObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.registerModule(new JavaTimeModule());
converters.add(0, converter);
}
}4.5 优缺点分析
| 优点 | 缺点 |
|---|---|
| 注解驱动,开发效率高 | 学习曲线较陡(需要理解 Spring 生态) |
| 与 Spring 生态完美集成 | 配置相对复杂(虽然 Spring Boot 已简化) |
| RESTful 支持优秀 | 对于简单项目可能过于重量级 |
| 灵活的拦截器机制 | |
| 强大的数据绑定和验证 | |
| 广泛的社区支持和文档 |
五、阿里 ROP(RESTful 开放平台)
5.1 技术定位
ROP(Rapid Open Platform)是阿里巴巴开源的 RESTful 开放平台框架,专注于解决企业对外提供 API 服务的场景。
┌─────────────────────────────────────────────────────────────┐
│ 开放平台架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 第三方开发者 开放平台网关 内部服务 │
│ │ │ │ │
│ │ 1.注册应用 │ │ │
│ ├────────────────►│ │ │
│ │ 2.获取 AppKey │ │ │
│ │◄────────────────┤ │ │
│ │ │ │ │
│ │ 3.调用 API │ │ │
│ │ + AppKey │ │ │
│ │ + Sign 签名 │ │ │
│ │ + Timestamp │ │ │
│ ├────────────────►│ │ │
│ │ │ 4.校验签名 │ │
│ │ │ 5.限流检查 │ │
│ │ │ 6.权限校验 │ │
│ │ ├────────────────►│ │
│ │ │ │ │
│ │ │◄────────────────┤ │
│ │◄────────────────┤ 7.返回结果 │ │
│ │ │ │ │
└─────────────────────────────────────────────────────────────┘5.2 核心特性
// ROP 服务方法定义
@ServiceMethod(method = "user.get",
version = "1.0",
httpMethod = {HttpMethod.GET})
public class UserGetService implements RopRequest<UserGetRequest> {
@Autowired
private UserService userService;
@Override
public UserGetResponse execute(UserGetRequest request,
ServiceContext context) {
// ROP 自动完成:签名验证、限流、权限检查
String userId = request.getUserId();
User user = userService.getUser(userId);
if (user == null) {
// ROP 标准错误格式
throw new ServiceError("USER_NOT_FOUND", "用户不存在");
}
UserGetResponse response = new UserGetResponse();
response.setUserId(user.getId());
response.setUserName(user.getName());
response.setEmail(user.getEmail());
return response;
}
}
// 请求参数
public class UserGetRequest extends RopRequest {
@NotNull
@OpenField(desc = "用户ID", demoValue = "12345")
private String userId;
@OpenField(desc = "返回字段", demoValue = "id,name,email")
private String fields;
// Getters and Setters
}
// 响应结果
public class UserGetResponse implements RopResponse {
@OpenField(desc = "用户ID")
private String userId;
@OpenField(desc = "用户名")
private String userName;
@OpenField(desc = "邮箱")
private String email;
// Getters and Setters
}5.3 ROP 安全机制
// 签名算法示例
public class RopSignUtil {
/**
* 生成签名
* 规则:MD5(AppSecret + 所有参数按key排序后的字符串 + AppSecret)
*/
public static String sign(Map<String, String> params, String appSecret) {
// 1. 过滤空值和签名本身
Map<String, String> filtered = params.entrySet().stream()
.filter(e -> e.getValue() != null && !e.getValue().isEmpty())
.filter(e -> !"sign".equals(e.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
// 2. 按 key 排序
List<String> sortedKeys = new ArrayList<>(filtered.keySet());
Collections.sort(sortedKeys);
// 3. 拼接字符串
StringBuilder sb = new StringBuilder();
sb.append(appSecret);
for (String key : sortedKeys) {
sb.append(key).append(filtered.get(key));
}
sb.append(appSecret);
// 4. MD5 加密
return DigestUtils.md5Hex(sb.toString()).toUpperCase();
}
}
// 典型请求参数
// appKey=your_app_key
// method=user.get
// version=1.0
// timestamp=2024-01-15+10%3A30%3A00
// format=json
// userId=12345
// sign=E3F5A8B2C1D4E6F7...(32位大写MD5)5.4 ROP 配置
<!-- rop-servlet.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rop="http://www.rop.com/schema/rop"
xsi:schemaLocation="...">
<!-- ROP 核心配置 -->
<rop:annotation-driven/>
<!-- 服务注册表 -->
<rop:service-registry id="serviceRegistry"
service-expose-or-not="AUTO"/>
<!-- 安全拦截器 -->
<rop:security-interceptor app-checker="appChecker"
sign-checker="signChecker"
timestamp-checker="timestampChecker"/>
<!-- 限流配置 -->
<rop:limiting-interceptor limit-manager="limitManager"/>
<!-- 监控配置 -->
<rop:monitor-interceptor service-access-counter="accessCounter"/>
<!-- 错误处理器 -->
<bean id="errorHandler" class="com.example.rop.CustomErrorHandler"/>
</beans>5.5 优缺点分析
| 优点 | 缺点 |
|---|---|
| 完整的开放平台解决方案 | 已停止维护(2015年后无更新) |
| 内置安全机制(签名、限流、权限) | 生态封闭,社区支持少 |
| 标准化 API 格式 | 仅适合特定场景(开放平台) |
| 自动生成 API 文档 | 与现代微服务架构兼容性差 |
| 完善的监控统计 | 依赖较老的 Spring 版本 |
六、全面对比
6.1 功能特性对比
| 特性 | Servlet | Struts2 | Spring MVC | 阿里 ROP |
|---|---|---|---|---|
| 学习成本 | ⭐⭐ 低 | ⭐⭐⭐⭐ 高 | ⭐⭐⭐ 中 | ⭐⭐⭐⭐ 高 |
| 开发效率 | ⭐ 低 | ⭐⭐⭐ 中 | ⭐⭐⭐⭐⭐ 高 | ⭐⭐⭐ 中 |
| REST 支持 | ⭐⭐ 需手动 | ⭐⭐⭐ 插件 | ⭐⭐⭐⭐⭐ 原生 | ⭐⭐⭐⭐⭐ 原生 |
| 依赖注入 | ❌ 无 | ⭐⭐⭐ Spring | ⭐⭐⭐⭐⭐ Spring | ⭐⭐⭐ Spring |
| 数据验证 | ❌ 手动 | ⭐⭐⭐⭐ XWork | ⭐⭐⭐⭐⭐ JSR-303 | ⭐⭐⭐ 内置 |
| 安全性 | ⭐⭐ 需自建 | ⭐⭐⭐⭐ 拦截器 | ⭐⭐⭐⭐ 拦截器 | ⭐⭐⭐⭐⭐ 内置 |
| 生态系统 | ⭐⭐⭐⭐ 成熟 | ⭐⭐⭐ 衰退 | ⭐⭐⭐⭐⭐ 活跃 | ⭐ 已停止 |
| 微服务适配 | ⭐⭐ 困难 | ⭐⭐ 困难 | ⭐⭐⭐⭐⭐ 优秀 | ⭐⭐ 困难 |
| 性能 | ⭐⭐⭐⭐⭐ 最高 | ⭐⭐⭐ 一般 | ⭐⭐⭐⭐ 良好 | ⭐⭐⭐ 一般 |
6.2 代码量对比(实现相同功能)
假设实现用户 CRUD 接口:
| 框架 | 代码行数(约) | 配置文件 | 注解使用 |
|---|---|---|---|
| Servlet | 300+ | web.xml | ❌ |
| Struts2 | 200+ | struts.xml | 少量 |
| Spring MVC | 100+ | Java Config | 大量 |
| 阿里 ROP | 150+ | rop.xml | 中等 |
6.3 适用场景
项目规模
小型 ◄────────────────────────► 大型
传统 │ ┌──────────────────────────────┐
企业 │ │ Struts2 │
应用 │ │ (遗留系统维护) │
│ └──────────────────────────────┘
│ ┌──────────────────────────────┐
应用类型 现代 │ Spring MVC │
API │ (主流推荐方案) │
服务 │ │
│ └──────────────────────────────┘
│ ┌──────────────────────────────┐
开放 │ │ 阿里 ROP │
平台 │ │ (特定场景/历史项目) │
│ └──────────────────────────────┘
│
底层 │ ┌──────────────────────────────┐
框架 │ │ Servlet/JSP │
开发 │ │ (框架开发/特殊需求) │
│ └──────────────────────────────┘七、技术选型建议
7.1 新项目选型(2026年)
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 企业级 Web 应用 | Spring Boot + Spring MVC | 生态最完善,社区最活跃 |
| 微服务架构 | Spring WebFlux / Spring MVC | 响应式支持,云原生友好 |
| RESTful API 服务 | Spring MVC + OpenAPI | 标准化 REST 开发 |
| 前后端分离 | Spring MVC | JSON 支持优秀,CORS 配置简单 |
7.2 遗留系统维护
| 现有技术 | 建议策略 |
|---|---|
| Struts2 | 逐步迁移到 Spring MVC,关注安全漏洞 |
| Servlet/JSP | 如无重大问题可保留,新项目使用框架 |
| 阿里 ROP | 建议迁移到 Spring Cloud Gateway + 自定义安全 |
7.3 现代 Spring Boot 示例
// Spring Boot 3.x + Spring MVC
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
private final UserMapper userMapper;
@GetMapping("/{id}")
public UserDTO getUser(@PathVariable Long id) {
return userService.findById(id)
.map(userMapper::toDTO)
.orElseThrow(() -> new NotFoundException("User not found"));
}
@PostMapping
public ResponseEntity<UserDTO> create(@Valid @RequestBody CreateUserRequest request) {
User user = userService.create(request);
return ResponseEntity
.created(URI.create("/api/v1/users/" + user.getId()))
.body(userMapper.toDTO(user));
}
}
// application.yml 配置
// server:
// port: 8080
// spring:
// mvc:
// format:
// date-time: yyyy-MM-dd HH:mm:ss八、总结
| 技术 | 诞生背景 | 当前地位 | 学习建议 |
|---|---|---|---|
| Servlet | Java Web 基石 | 仍需理解原理 | ⭐⭐⭐⭐⭐ 必学 |
| Struts2 | 早期 MVC 框架 | 维护中,不推荐新项目 | ⭐⭐ 了解即可 |
| Spring MVC | 现代企业级标准 | 绝对主流 | ⭐⭐⭐⭐⭐ 必学 |
| 阿里 ROP | 开放平台特定场景 | 已停止维护 | ⭐ 历史参考 |
趋势展望:
- Servlet 规范继续演进(Jakarta EE)
- Spring MVC 与 WebFlux 并存(响应式编程)
- 云原生时代的框架演进(GraalVM 原生镜像支持)
参考资源: