spring3.0 MVC

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{

@RequestMapping(method = RequestMethod.DELETE)
public String deleteArticle(@PathVariable String id, HttpServletRequest request){
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標準組件幹成什麼樣?開源時代,至少我不願意接受那種變態的潛規則。


筆者早先常用Struts1.x框架,它搭配了一套自己的ActionForm,使得編程工作量增加,雖然可以變通使用自己的Pojo,但對於沒有掌握J2EE底層工具類(BeanUtil)的開發人員來說,其類型匹配是非常複雜的事。事實上Spring MVC早在1.x版本就完全使用自己的pojo來對應表單的填充,配上屬性編輯器,可以解決類型轉換問題,完全實現領域模型驅動的設計模式。由於MVC層的控制器也是Spring容器的Bean而已,因此對整個項目的控制、擴展變得非常容易。同時上文也順便點評了Struts2,可見Spring MVC在各類MVC框架的優勢所在。本身羅德.約翰遜先生是設計模式高手,一個優秀的框架給我們帶來的遠遠不只是開發效率,還有更先進的開發模式和理念...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章