從上一篇的springmvc入門中已經看到,springmvc.xml中的配置了映射器和適配器,是使用非注解的方式來配置的,這是非注解方式的一種,這里再復習一下:
1. 非注解方式
1.1 處理器適配器
上一節中使用的處理器適配器是:org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter。即:
SimpleControllerHandlerAdapter適配器能執行實現了Controller接口的Handler,所以我們所寫的Handler需要實現Controller接口。
除了這個適配器外,還有另一個適配器,叫org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter。即可以配置:
HttpRequestHandlerAdapter適配器能執行實現了HttpRequestHandler接口的Handler,所以我們所寫的Handler需要實現HttpRequestHandler接口,這跟實現Controller接口稍微有點不同,比如我們寫一個Handler:
public class ItemsController2 implements HttpRequestHandler { @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //實際中是調用service查找數據庫,查詢商品列表,這里直接使用靜態數據來模擬了 List<Items> itemsList = new ArrayList<Items>(); //向list中填充靜態數據 Items items_1 = new Items(); items_1.setName("聯想筆記本"); items_1.setPrice(6000f); items_1.setDetail("ThinkPad T430 聯想筆記本電腦!"); Items items_2 = new Items(); items_2.setName("蘋果手機"); items_2.setPrice(5000f); items_2.setDetail("iPhone6蘋果手機!"); itemsList.add(items_1); itemsList.add(items_2); //設置模型數據 request.setAttribute("itemsList", itemsList); //設置轉發的視圖 request.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(request, response); //使用此方法可以通過修改response,設置響應的數據格式,比如響應json數據 /* response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json串");*/ } }
前面獲取數據都是一模一樣的,后面轉到視圖部分和實現Controller接口是不同的,實現HttpRequestHandler接口的話,最后這里處理和原來的servlet是一樣的,往request域中存入數據,然后跳轉到新的jsp視圖頁面。不過這種方式還可以修改response,設置響應的數據格式等。
不管是用那個適配器,一個相同點就是:每個Handler中只能有一個方法,因為要繼承Controller或者HttpRequestHandler,就要重寫相對應的那個方法,在那個方法中處理邏輯。也就是說一個Handler中不能有兩個方法或兩個以上的來處理不同的邏輯,這是弊端,但是也有它的好處,限定了程序員的編程,比較規范。
這兩個適配器可以同時使用,我測試了一下,不會沖突,我配了兩個適配器,寫了兩個Handler,分別去實現Controller和HttpRequestHandler接口,都可以被執行。
1.2 處理器映射器
上一節中使用的映射器是:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping。即:
這個映射器根據名字也可以看得出,是根據bean的name作為url進行查找,所以配置Handler的bean的時候,要配置一下name屬性,設置為要請求的url即可正確映射。
還有一種處理器映射器叫簡單映射器:org.springframework.web.servlet.handler.SimpleUrlHandlerMapping。它的映射方式是直接根據url來的,如下:
這種可以直接配url,然后對應的url指定一個Handler,使用的是該Handler對應bean的id,所以只要在bean中配好id,然后將url和這個id對應上即可。
經測試,這兩個映射器也可以一起使用,互不沖突,匹配到哪個就用哪個。
2. 注解方式
2.1 處理器適配器和映射器
在spring3.1之前使用:
注解映射器:org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
注解適配器:org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
在spring3.1之后使用:
注解映射器:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
注解適配器:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
毫無疑問,現在都已經到了版本4以上了,肯定有后者了,如果使用了注解方式的適配器和映射器,就不需要前面那些非注解的適配器和映射器了,所以只需要兩行代碼即可:
我們可以看到,上面還配了個Handler,那么url的映射怎么辦?我怎么知道對應到哪個Handler呢?不著急,這些全交給注解!下面來寫這個Handler(Controller):
@Controller public class ItemsController3 { // 商品查詢列表 // @RequestMapping實現 對queryItems方法和url進行映射,一個方法對應一個url // 一般建議將url和方法寫成一樣 @RequestMapping("/queryItems") public ModelAndView queryItems() throws Exception { // 實際中是調用service查找數據庫,查詢商品列表,這里直接使用靜態數據來模擬了 List<Items> itemsList = new ArrayList<Items>(); // 向list中填充靜態數據 Items items_1 = new Items(); items_1.setName("聯想筆記本"); items_1.setPrice(6000f); items_1.setDetail("ThinkPad T430 聯想筆記本電腦!"); Items items_2 = new Items(); items_2.setName("蘋果手機"); items_2.setPrice(5000f); items_2.setDetail("iPhone6蘋果手機!"); itemsList.add(items_1); itemsList.add(items_2); // 返回ModelAndView ModelAndView modelAndView = new ModelAndView(); // 相當于request的setAttribute,在jsp頁面中通過itemsList取數據 modelAndView.addObject("itemsList", itemsList); // 指定視圖 modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp"); return modelAndView; } @RequestMapping("/queryItems2") public ModelAndView queryItems2() throws Exception { // 實際中是調用service查找數據庫,查詢商品列表,這里直接使用靜態數據來模擬了 List<Items> itemsList = new ArrayList<Items>(); // 向list中填充靜態數據 Items items_1 = new Items(); items_1.setName("聯想筆記本2"); items_1.setPrice(6000f); items_1.setDetail("ThinkPad T430 聯想筆記本電腦!"); Items items_2 = new Items(); items_2.setName("蘋果手機2"); items_2.setPrice(5000f); items_2.setDetail("iPhone6蘋果手機!"); itemsList.add(items_1); itemsList.add(items_2); // 返回ModelAndView ModelAndView modelAndView = new ModelAndView(); // 相當于request的setAttribute,在jsp頁面中通過itemsList取數據 modelAndView.addObject("itemsList", itemsList); // 指定視圖 modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp"); return modelAndView; } }
從上面的代碼中可以看出,首先,我一個Handler中可以寫多個方法了,現在是兩個,邏輯一模一樣,就是item的名字稍微變了一下好用來測試。在類的上面加上@Controller注解,可以指定bean的名字,也可以不指定,默認為類名首字母小寫。然后url映射交給@RequestMapping類處理,可以指定url,一個url對應一個方法。
這樣就很清晰了,前臺傳了個url進來,映射器根據這個url找到Handler,然后根據Handler選擇一個適配器去執行,這里全部用的都是注解,這樣就將url和這個Handler連到一起了,也把url和具體的處理方法連到一起了,由此可見,使用注解的開發方式比較方便。開發中常用的是注解的方式。
2.2 繼續優化注解
使用注解要注意一個問題,就是注解適配器和映射器必須配對使用,也就是說,不能一個用注解,一個用非注解。要用一起用,要么都不用。其實在springmvc中還有更加簡便的注解:
只要這一個注解即可,適配器和映射器就可以省略不配了。另外,如果Controller很多的話,我們還得針對這些Controller配好多個bean,也不方便,所以springmvc中也提供了掃描包的方式來配置,如下:
所以到最后,使用注解的方法,適配器、映射器、Controller等的配置加在一起就兩行代碼!搞定!當然,視圖解析器還是和上一節一樣,自己配一下即可。
到這就基本總結完了springmvc中使用非注解方式和注解方式的適配器和映射器了,很明顯,開發中我們使用最后面的那個注解配置,非常方便。
文章列表