SpringMVC 和 Struts2 就像武林中的两大门派,虽然都是处理 Web 请求的高手(MVC 框架),但招式风格和内功心法大不相同。来,咱们用最接地气的方式掰扯掰扯,保准你笑着记住!
核心区别一句话概括:
Struts2 像是个 “中央集权” 的大家长,啥事儿都得经过它规定的流程(拦截器栈);SpringMVC 则像是个 “自由灵活” 的居委会,搭好平台让大家(各种组件)按约定自己玩儿(依赖注入+IoC),它主要当个协调员(DispatcherServlet)。
详细版 “找不同” (带段子和例子):
出身和 “靠山”:
核心控制器 (Front Controller - “门卫大爷”):
FilterDispatcher
(老版本) 或 StrutsPrepareAndExecuteFilter
(新版本)。它是一个强大的过滤器(Filter)。所有请求都得先过它这关,它负责整个请求生命周期的调度,权力很大。DispatcherServlet
。它是一个标准的 Servlet。它更像一个总协调员,收到请求后自己不干所有活,而是把任务分派给其他组件(HandlerMapping, Controller, ViewResolver 等)。控制器 (Controller - “业务处理员”):
ActionSupport
)。Action 类本身在 Struts2 中默认是多例的(每次请求创建一个新实例)。@Controller
注解标记的类(或者实现 Controller
接口,但注解方式更流行)。不需要继承特定类,就是一个普通的 POJO (Plain Old Java Object)。控制器方法用 @RequestMapping
等注解标记。SpringMVC 的控制器默认是单例的(由 Spring IoC 容器管理),更轻量高效。public class LoginAction extends ActionSupport {
private String username; // 属性!自动封装请求参数
private String password;
public String execute() throws Exception {
// 业务逻辑
if ("admin".equals(username) && "123456".equals(password)) {
return SUCCESS; // 返回字符串结果,对应struts.xml里的result
} else {
return ERROR;
}
}
// Getter/Setter 必须!用于参数封装
}
像是一个有固定工位和固定任务清单(继承 ActionSupport
带来的功能) 的员工。每次来新活(请求),就克隆一个新员工来处理(多例)。@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService; // 轻松注入其他Spring管理的Bean!
@GetMapping("/login") // 更精细的映射
public String login(@RequestParam String username,
@RequestParam String password,
Model model) {
// 业务逻辑,通常调用Service
boolean success = userService.authenticate(username, password);
if (success) {
model.addAttribute("message", "登录成功!");
return "welcome"; // 返回视图名
} else {
model.addAttribute("error", "用户名或密码错误!");
return "login";
}
}
}
像一个自由职业者,挂靠在 Spring 平台(@Controller
)。平台给他派活(@RequestMapping
指定他能接什么活)。他干活需要的工具(UserService
),平台直接提供(@Autowired
依赖注入)。他本身是个固定员工(单例),高效复用。请求参数处理 (“收快递”):
ModelDriven
接口封装到模型对象。耦合性相对较高(Action 类里一堆属性)。@RequestParam
:获取单个请求参数。@PathVariable
:获取 RESTful 风格的 URL 路径变量。@RequestBody
:获取请求体内容(如 JSON,自动绑定到对象)。@ModelAttribute
:绑定到模型对象(也可以用于非请求参数的预加载)。HttpServletRequest
, HttpSession
等:直接获取原生对象。@RequestParam
)”、“放厨房第二个柜子(@PathVariable
)”、“整个包裹给我我亲自拆(HttpServletRequest
)” 或者 “按说明书组装好放客厅(自动绑定到POJO)”。拦截机制 (“关卡检查”):
DispatcherServlet
)问你去哪,然后你直接去办事员(Controller)那。但保安可以在你进办事员门前(preHandle
)、出办事员门后(postHandle
)、离开大楼时(afterCompletion
)对你进行抽查(HandlerInterceptor)。更自由,检查点可选!视图技术 (“展示成果”):
ViewResolver
和 View
接口实现。开发者配置好 ViewResolver
(如 InternalResourceViewResolver
对应 JSP, FreeMarkerViewResolver
对应 FreeMarker),控制器只需要返回一个逻辑视图名(字符串),ViewResolver
负责找到真正的视图实现(View
对象)来渲染。在视图中,通常使用 JSTL/EL 表达式 (JSP) 或模板引擎自己的语法来访问模型数据(放在 Model
/ ModelMap
/ ModelAndView
对象中的数据)。更标准,更符合 Servlet/JSP 规范。ViewResolver
和 View
)说:“这是给客户的报告(逻辑视图名 'report'
)”。讲解员根据客户类型(配置的视图技术),决定是用普通话讲(JSP+EL)、用英语讲(FreeMarker)还是放幻灯片(PDF 视图),并用客户能理解的方式(EL/模板语法)展示报告内容(模型数据)。配置方式 (“定规矩”):
struts.xml
文件。Action、Result、Interceptor、常量配置等都在这里。虽然支持注解,但核心配置还是 XML 为主。比较集中,但也可能变得庞大。*-servlet.xml
文件配置 HandlerMapping
, ViewResolver
, 拦截器等。@Configuration
类,结合 @EnableWebMvc
和实现 WebMvcConfigurer
接口来配置所有 MVC 相关组件。干净、类型安全、现代!@Controller
, @RequestMapping
, @RequestParam
, @PathVariable
, @ResponseBody
等注解在代码中声明式配置,极大简化开发。结合 Java 配置,XML 几乎可以消失。struts.xml
),所有流程写得清清楚楚,改制度就得翻手册。SpringMVC 定规矩,你可以选择写手册(XML),也可以选择开个会口头宣布(Java 配置),或者给每个员工发个电子备忘录(注解),方式灵活,与时俱进。性能和社区:
终极总结 & 面试金句:
幽默收尾:
面试时如果被问到,可以笑着说:“这就像问现在出门是骑马(Struts2)还是开车(SpringMVC)。虽然马儿也曾风光无限,但时代变了,老司机们都开 SpringMVC 这辆 ‘Spring Boot 超跑’ 了!当然,如果贵司马厩里(老系统)还有几匹 Struts2 的千里马需要照顾,我也略懂驯马术(维护经验)。”
记住这些核心点,结合生动的类比,面试官想不给你加分都难!加油!