鼎鼎大名的Spring框架3.0版在12月5日由其作者之一——Juergen Hoeller先生在博客里宣告問世,并命為里程碑版,給Spring粉絲們帶來了震撼的快感。筆者即開“快車”拉了兩個包回來,遺憾的是參考文檔至今還沒有出來(僅有API文檔),這為學習Spring 3.0帶來了非常大的困難,但沒有阻擋筆者對新產品的興趣。
Spring之父Rod Johnson先生早在2003年就預言EJB將死(觀點頗具爭議),攻擊EJB之臃腫是在虐待程序員。然而EJB 3.0出來后幾乎宣判Spring死刑,但自2.0版以后Spring火爆程度已經超過EJB,兩者的爭斗至今仍不停息,這也是Spring 3.0連文檔還沒有整理出來就匆匆推出的原因。當然,Spring與EJB有很多各自獨特優勢之處,例如EJB的分布式運算、標準規范,Spring的IoC、AOP切面編程、偶合集成、MVC等等,取各自之長在企業中應用如虎添翼。Spring目前已經加入了J2EE規范,J2EE世界將更加精彩......
或許是用膩了Struts1那死板的WEB框架,才對Spring MVC愛不釋手,尤其是2.5版本以后,支持全注解配置方式,已經使很久沒有再寫過xml文件了。
3.0版是完全兼容2.5,因此了解2.5版的@MVC則更容易接受。正如Arjen Poutsma小伙子在他的博客里說的那樣,3.0時代將集中致力于表述性狀態轉移(REST,希望我沒有翻譯錯,金山詞霸翻譯為“休息”)的網絡服務和更容易的網絡編程。的確增加了更多的控制器類型,并增強了SOAP/WSDL/WS這些基于分布式體系結構。
先回憶下2.5注解方式的@MVC,來一個示例:
@Controller
public class ArticleController{
@RequestMapping("/articleView")
public String getArticle(@RequestParam("id") String id, HttpServletRequest request){
request.setAttribute("article", service.find(Article.class, id));
return "articleView";
}
}
ArticleController沒有實現任何接口,是一個最普通不過的pojo,如果瀏覽器來了articleView.do?id=xxx這個請求,Spring會找到getArticle()這個方法,該方法第一個參數綁定到了URL上的請求參數,第二個是J2EE標準的request對象(可見Spring MVC是非侵入式的,不像變態的Struts2),事實上還可以給定HttpServletResponse,ModelMap,甚至自己的類型,Spring都會為你將值傳入進來。通過一個邏輯層service組件根據id參數值去底層查找Article對象,并放入request作用域中,最后返回的是面頁視圖名,這個例子中是返回到articleView.jsp中。
上例再變通下:
@Controller
public class ArticleController{
@RequestMapping("/articleView_*")
public String getArticle(HttpServletRequest request){
String id = StringUtil.getParam(request.getRequestURI(),"articleView_*");
request.setAttribute("article", service.find(Article.class, id));
return "articleView";
}
}
對于articleView_aaa.do,articleView_bbbb.do,articleView_c5h8j2.do,articleView_xxx.do,這樣的請求都會由getArticle()這個方法來應付,是不是很有意思?
Spring 3.0增加了一個@ PathVariable注解來支持可變的請求路徑,將上面的代碼在3.0版中再變通下:
@Controller
public class ArticleController{
@RequestMapping("/articleView/${id}") //可以接受articleView/aaa.do,articleView/xxx.do...
public String getArticle(@PathVariable String id, HttpServletRequest request){
request.setAttribute("article", service.find(Article.class, id));
return "articleView";
}
}
再變得復雜些:
@Controller
public class ArticleController{
@RequestMapping("/articleList/${pageSize}/channel/*/category/${id}")
public String getArticles((@PathVariable Integer pageSize, @PathVariable int id, HttpServletRequest request){
Integer channelId = StringUtil.getParam(request.getRequestURI(),"channel/*/");
request.setAttribute("articles", service.findScroll(Article.class, pageSize,50,"channel=? and category=?",new Object[]{channelId,id}));
return "articleList";
}
}
它已經靈活到URL地址完全可以自己隨意編制。
根據內容協商制的視圖解析機制:
2.5版是由@MVC控制器來決定視圖解析器,3.0版將變得更加靈活,似乎可以通過擴展名來轉到不同的解析器中,例如請求一個.pdf文件將是如何效果呢?3.0版都會帶來不可思議的模式。
HTTP方法的轉換:
先看前臺頁面一段Html代碼
<form:form method="delete">
<p class="submit"><input type="submit" value="Delete Pet"/></p>
</form:form>
HTTP規范中form表單只有兩種方法——POST和GET,而3.0做了一個過濾器,可以轉換這些方法至四種——GET, PUT, POST, 和 DELETE。控制器接受請求:
@Controller("/deleteArticle")
public class ArticleController{
service.delete(Article.class, id);
return "message";
}
}
3.0版僅在MVC子集中就增加了很多新特性,如果在IoC、AOP等等其它子集所有的變革,絕對可以稱得上Srping創始人所述的里程碑版本。3.0版使用的注解列表如下:
? @Autowired
? @Component
? @Controller
? @InitBinder
? @ManagedAttribute
? @ManagedOperation
? @ManagedOperationParameters
? @ManagedOperationParameter
? @ManagedResource
? @PathVariable
? @PostConstruct
? @PreDestroy
? @Repository
? @RequestMapping
? @Required
? @Resource
? @Service
? @Transactional
目前Spring 3版本已經到了M2,應該是M3完成后將推出最終正式版本,我想很快會來臨,按照Spring的創始人羅德.約翰遜的預言,未來J2EE應用中Spring+Tomcat將占主導地位,是否引起爭議,筆者不敢點評,不過Oracle收購Sun后,Java社區將是如何,還無從知曉,似乎羅德.約翰遜對這宗收購案也有些緊張,因為Oracle不像Sun的第一個談判者IBM那樣有過開放技術的先例(可以回憶下IBM早期的主板總線開放掀起的兼容機潮至今波濤不熄)。目前國內對新東西消化尚慢,我到圖書城看了下,Spring 2.5的資料都很難找到。且很多企業都是抱著Struts1.x在做開發,盡管筆者這樣說會引來很多爭議,但Struts1時代的滅亡只是時間問題。Struts2雖然改進了很多,依筆者看,與Spring MVC相比仍有諸多的不足,尤其看不慣那種變態的侵入模式,看看它把HttpServletRequest、HttpSession、HttpServletResponse等servlet標準組件干成什么樣?開源時代,至少我不愿意接受那種變態的潛規則。
筆者對Spring框架研究膚淺,待日后了解掌握更多時會常在博客中述之。