用了Struts 2做过两个项目,开始对Struts 2厌烦了!以后,除了特殊的需要,我不会再使用Struts 2开发项目了。不是Struts 2这个框架不好,而是Struts 2我根本不需要用这么多。其实Struts 1.x对于我来讲已经是非常够用了,可能还多了呢。一个项目里面塞了N多个框架,Struts、Spring、Hibernate,其实对于学习成本来讲还是挺高的,团队每一个人素质不同,对框架的理解深度不同,其实框架多一个不如少一个。hibernate换不得,因为使用它实在是太方便了,我可以减化很多工作,Spring也没有办法换掉,对事务的支持,dao的支持,让我的工作量又可以减少。所以打算将web前框的MVC框架换掉。
谈到Struts的维护,Struts应用于项目应用得多,维护得多,其实你会觉得Struts其实不是你想像的那么好。假如某个业务模块有bug,你要做的就是,查看一下是那个.do,然后根据这个path去找一下struts-config.xml文件,接着你才知道这个path所对应的action,接着你要找到相应的action,然后查看一下其逻辑实现,有时你还要看一下jsp的显示逻辑是否正确,那么你还要再看一下action所返回的ActionForward,根据名字,你要找到相应的forward,就是转向的jsp页面,再找到jsp页面,进行修改,有时它并不是forward到一个jsp,而是forward到另外一个action,那就更麻烦了。转来转去,跳来跳去,你会搞得很头晕。其实我现在写上面这些文章,我也写得头晕。假如你的团队开发规范做得比较好,你又参与了这个项目,并且这个模块是你实现的,那你可能不需要查看这么多直接就可以找到相应的业务对象或页面做改进,但有时,在中国做软件开发并不是这么理想化,有时就是这么郁闷。就算我现在在中国最大的垂直网站任职,也同样遇到这样的问题。
对于struts、或者是webwork,可能往往action的命名跟jsp的命名规范不同,对于action的命名空间来讲,可能与最终的展示页面的路径不同。Struts与Webwork最大的毛病,就是它只写义了一个简单的开发规范,而没有办法去限制开发人员任意使用。一直以来,我最喜欢的框架就是tag library + jsp,因为我觉得它已经够用了。为什么要在一个项目里搞这么多框框架架干嘛。访问某一个path出问题了,因为这个path就是对应着一个jsp的位置,我直接就定位到那里去,jsp里面只有标签,可能复杂一点的话你在页面会有一点点jsp代码,但这个其实不防碍到你的阅读与维护。使用标签库,你可以最大限制的做到代码量的共用。对于组织结构控件、用户选择控制,工作流控件等等,其实使用标签库来实现,也挺理想的。Jstl标签库,已经提供了很多现成的,有用的标签库供你使用,事务处理方面同样有解决方案。其他的你可以考虑自己自己开发,开发一个标签库也非常容易,也降低了开发人员的学习成本与开发成本。将来有可能,你再开发一些类似于eclispe的插件,那使用拖拽的方式来进行开发,那速度更是飞快。
这时间看了Spring 2.5的新功能,对annotation支持,让我开始喜欢上Spring MVC了,现在新的项目已经开始应用上Spring MVC了。Spring MVC总体的感觉就是非常简单,最让我觉得兴奋的一点就是,InternalResourceViewResolver的应用方面,在某种程度上,它起来了一个限作的作用。并且,使用了annotation,没有了烦人的配置文件。
以下是使用Spring MVC Controller的一个例子:
import java .util .List ;
import org .springframework .beans .factory .annotation .Autowired ;
import org .springframework .stereotype .Controller ;
import org .springframework .ui .ModelMap ;
import org .springframework .web .bind .annotation .RequestMapping ;
import org .springframework .web .bind .annotation .RequestParam ;
import com .suneca .base .BaseController ;
import com .suneca .entity .User ;
import com .suneca .service .UserService ;
@Controller
public class UserController extends BaseController {
final static String NAMING_SPACE = "/system/user/" ;
@Autowired
private UserService userService ;
@RequestMapping (NAMING_SPACE + "list.html" )
public String listUsers (ModelMap model ) throws Exception {
List < ? > users = userService .listUsers ( ) ;
model .addAttribute ( "users" , users ) ;
return NAMING_SPACE + "list" ;
}
@RequestMapping (NAMING_SPACE + "create.html" )
public String createUser (ModelMap model ) throws Exception {
User user = new User ( ) ;
model .addAttribute ( "user" , user ) ;
return NAMING_SPACE + "form" ;
}
@RequestMapping (NAMING_SPACE + "update.html" )
public String updateUser (@RequestParam ( "id" ) long id ,ModelMap model ) throws Exception {
User user = userService .findUserById (id ) ;
model .addAttribute ( "user" , user ) ;
return NAMING_SPACE + "form" ;
}
@RequestMapping (NAMING_SPACE + "save.html" )
public String saveUser (User user ) throws Exception {
userService .saveUser (user ) ;
return REDIRECT + NAMING_SPACE + "list.html" ;
}
@RequestMapping (NAMING_SPACE + "delete.html" )
public String deleteUser (@RequestParam ( "id" ) long id ) throws Exception {
User user = userService .findUserById (id ) ;
userService .deleteUser (user ) ;
return REDIRECT + NAMING_SPACE + "list.html" ;
}
}
假如你访问的url是:http://www.suneca.com/system/user/delete.html
那么它将自动定位到UserController的deleteUser()方法上(@RequestMapping("/system/user/delete.html")这个注解起作用),并且自动将参数带过关来的id自动转化long型赋值给id,执行删除完之后,重定向到/system/user/list.html这个地址上。
假如你访问的url是:http://www.suneca.com/system/user/list.html,那么它将自动定位到UserController的listUser()方法上(@RequestMapping("/system/user/list.html")这个注解起作用),并且,执行相应查询之后,转到WEB-INF/pages/system/user/list.jsp页面上做显示。
之所以能够做到这些,主要也是因为InternalResourceViewResolver起了非常关键的作用。以下是InternalResourceViewResolver的配置
<property name = "viewClass" value = "org.springframework.web.servlet.view.JstlView" / >
<property name = "prefix" value = "/WEB-INF/pages/" / >
<property name = "suffix" value = ".jsp" / >
< /bean >