游客发表
打开一个2005年上线的网站老政务网站,URL里赫然躺着.do后缀——这是网站Struts留下的胎记。那会儿Java Web开发圈子里,网站Struts就是网站MVC的代名词,Apache基金会旗下最风光的网站项目之一。ActionServlet拦截请求,网站ActionForm封装表单数据,网站struts-config.xml里配置跳转关系,网站一整套流程跑下来,网站代码结构确实比裸写Servlet清爽太多。网站
但问题也埋在这套设计里。网站ActionForm是网站个纯粹的JavaBean,每个表单字段都得写getter和setter,网站一个注册页面十几个字段,网站光样板代码就上百行。网站更难受的是它跟Servlet API绑得太死,Action类的execute方法签名里直接塞着HttpServletRequest和HttpServletResponse,想脱离容器做单元测试?得靠StrutsTestCase或者自己mock,费劲。
2006年我在一个电信项目里用Struts 1.2,配置文件写到崩溃。几百个action映射散落在struts-config.xml里,改一个跳转得翻半天。后来同事推荐WebWork,说OGNL表达式和拦截器机制比Struts灵活得多。试了一下,确实——表单参数自动注入Action属性,不用再写FormBean;拦截器栈可以自由组合,权限校验、日志、事务各管各的。WebWork后来跟Struts 2合并,成了Apache Struts 2,核心就是WebWork那套XWork架构。
Struts 2的拦截器设计是个亮点。默认拦截器栈里塞了params、validation、workflow等二十多个拦截器,每个只管一件事。想加自定义逻辑?写个Interceptor接口实现,往栈里一插就行。OGNL也强大,#session.user.name这种表达式直接穿透多层作用域。但强大了也危险——2013年那个S2-016漏洞,恶意OGNL表达式能直接执行系统命令,国内一大片银行、政府网站中招。根因就是OGNL过于灵活,加上默认参数名过滤不严。
安全漏洞这事得客观看。Struts 2的RCE漏洞从2010年到现在出了几十个,S2-045、S2-052、S2-057……每次都是OGNL或者文件上传解析惹的祸。Apache修得也快,但存量系统太多,很多项目上线后根本不更新依赖。我见过一个省级社保系统,struts2-core版本还停在2.3.15,问运维为什么不升级,答曰“升级怕影响业务”。这种心态下,漏洞不找你找谁。
现在新项目基本没人用Struts了。Spring MVC轻量、Spring Boot开箱即用,谁还去折腾struts.xml和ActionSupport?但老系统还在跑。银行柜台、医院挂号、学校教务——这些地方你打开F12看请求,指不定还能撞见.action结尾的URL。维护这些系统的程序员,一边骂Struts坑多,一边还得硬着头皮改bug。有个朋友在甲方驻场,每天的工作就是给Struts 2打补丁,打完重启,重启完再打下一个。
Struts的兴衰挺典型的。它解决了Servlet时代MVC缺失的问题,但设计上的僵化和安全债又把自己拖垮了。技术选型这事,有时候不是看谁功能强,而是看谁坑少、社区活、升级顺。Struts 2的拦截器思想影响了后来一堆框架,但OGNL这个坑,算是给所有人上了一课——灵活性和安全性,天平两端得自己找平衡。
友情链接