前面基本介紹了下SpringMVC的運行原理,現在按照前面的原理一步步實現一個簡單的程序。先搭建一個簡單的web工程,將spring的jar包導入項目中。
在web.xml中配置如下:
1 <servlet> 2 <servlet-name>springmvc</servlet-name> 3 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 4 <init-param> 5 <param-name>contextConfigLocation</param-name> 6 <param-value>classpath:springmvc.xml</param-value> 7 </init-param> 8 <load-on-startup>1</load-on-startup> 9 </servlet> 10 <servlet-mapping> 11 <servlet-name>springmvc</servlet-name> 12 <url-pattern>*.action</url-pattern> 13 </servlet-mapping>
load-on-startup:表示servlet隨服務啟動;
url-pattern:*.action的請交給DispatcherServlet處理。
contextConfigLocation:指定springmvc配置的加載位置,如果不指定則默認加載WEB-INF/[DispatcherServlet 的Servlet 名字]-servlet.xml。
servlet攔截方法有如下注意點:
1、攔截固定後綴的url,比如設置為 *.do、*.action, 例如:/user/add.action 此方法最簡單,不會導致靜態資源(jpg,js,css)被攔截。
2、攔截所有,設置為/,例如:/user/add /user/add.action,此方法可以實現REST風格的url,很多互聯網類型的應用使用這種方式。但是此方法會導致靜態文件(jpg,js,css)被攔截後不能正常顯示。需要特殊處理。
3、攔截所有,設置為/*,此設置方法錯誤,因為請求到Action,當action轉到jsp時再次被攔截,提示不能根據jsp路徑mapping成功。
在classpath下的springmvc.xml中配置處理器映射器
1 <!-- 處理器映射器 --> 2 <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
1 <!-- 處理器適配器 --> 2 <bean 3 class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
public class ItemList1 implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception { // 商品列表 List<Items> itemsList = new ArrayList<Items>(); Items items_1 = new Items(); items_1.setName("技嘉筆記本"); items_1.setPrice(6000f); items_1.setDetail("P35K V3筆記本電腦!"); Items items_2 = new Items(); items_2.setName("蘋果手機"); items_2.setPrice(5000f); items_2.setDetail("iphone6plus蘋果手機!"); itemsList.add(items_1); itemsList.add(items_2); // 創建modelAndView准備填充數據、設置視圖 ModelAndView modelAndView = new ModelAndView(); // 填充數據 modelAndView.addObject("itemsList", itemsList); // 視圖 modelAndView.setViewName("order/itemsList"); return modelAndView; } }
配置處理器
1 <bean name="/items1.action" id="itemList1" class="com.luchao.controller.ItemList1"/>
1 <!-- 視圖解析器 --> 2 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 3 <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> 4 <property name="prefix" value="/WEB-INF/jsp/"/> 5 <property name="suffix" value=".jsp"/> 6 </bean>
如果不使用視圖解析器,那麼上面控制器代碼中需要指定具體的視圖名稱,如:modelAndView.setViewName("/WEB-INF/jsp/order/itemsList.jsp");可見使用視圖解析器可以增加其靈活性。
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 4 <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> 5 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 6 <html> 7 <head> 8 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 9 <title>查詢商品列表</title> 10 </head> 11 <body> 12 商品列表: 13 <table width="100%" border=1> 14 <tr> 15 <td>商品名稱</td> 16 <td>商品價格</td> 17 <td>商品描述</td> 18 </tr> 19 <c:forEach items="${itemsList }" var="item"> 20 <tr> 21 <td>${item.name }</td> 22 <td>${item.price }</td> 23 <td>${item.detail }</td> 24 </tr> 25 </c:forEach> 26 27 </table> 28 </body> 29 </html>
上面控制器實現了controller接口,才能由org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter適配器執行。並且上面的處理器映射器為org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,這是一種根據Url的名字找到處理器。如上:items1.action對應了com.luchao.controller.ItemList1這個處理類。
另一種簡單的處理器映射器:org.springframework.web.servlet.handler.SimpleUrlHandlerMapping其配置如下:
1 <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 2 <property name="mappings"> 3 <props> 4 <prop key="/items1.action">itemList1</prop> 5 <prop key="/items2.action">itemList2</prop> 6 </props> 7 </property> 8 </bean>
如果處理器實現了HttpRequestHandler,那麼則需要使用org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter適配器。
1 <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
1 public class ItemList2 implements HttpRequestHandler { 2 @Override 3 public void handleRequest(HttpServletRequest request, 4 HttpServletResponse response) throws ServletException, IOException { 5 // 商品列表 6 List<Items> itemsList = new ArrayList<Items>(); 7 8 Items items_1 = new Items(); 9 items_1.setName("技嘉筆記本"); 10 items_1.setPrice(6000f); 11 items_1.setDetail("P35K V3筆記本電腦!"); 12 13 Items items_2 = new Items(); 14 items_2.setName("蘋果手機"); 15 items_2.setPrice(5000f); 16 items_2.setDetail("iphone6plus蘋果手機!"); 17 18 itemsList.add(items_1); 19 itemsList.add(items_2); 20 // 填充數據 21 request.setAttribute("itemsList", itemsList); 22 //視圖 23 request.getRequestDispatcher("/WEB-INF/jsp/order/itemsList.jsp").forward(request, response); 24 } 25 }
//使用此方法可以通過修改response,設置響應的數據格式,比如響應json數據
1 response.setCharacterEncoding("utf-8"); 2 3 response.setContentType("application/json;charset=utf-8"); 4 5 response.getWriter().write("json串");
因為處理器有不同的實現,所以需要通過適配器來滿足其處理的需求,這是一種適配器模式的經典實現。
注解處理器映射器和注解處理器適配器配置:
1 <!--注解映射器 --> 2 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> 3 <!--注解適配器 --> 4 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
一般中開發中使用
1 <mvc:annotation-driven/>
使用 mvc:annotation-driven代替上邊注解映射器和注解適配器配置,mvc:annotation-driven默認加載很多的參數綁定方法,比如json轉換解析器就默認加載了,如果使用mvc:annotation-driven不用配置上邊的RequestMappingHandlerMapping和RequestMappingHandlerAdapter,實際開發時使用mvc:annotation-driven。
另外還需要掃描包來加載處理器,配置如下:
1 <!-- 掃描controller注解,多個包中間使用半角逗號分隔 --> 2 <context:component-scan base-package="com.luchao.controller"/>
1 @Controller 2 public class ItemList3 { 3 // 商品查詢列表 4 // @RequestMapping實現 對queryItems方法和url進行映射,一個方法對應一個url 5 // 一般建議將url和方法寫成一樣 6 @RequestMapping("/items3") 7 public ModelAndView queryItems() throws Exception { 8 9 // 調用service查找 數據庫,查詢商品列表,這裡使用靜態數據模擬 10 List<Items> itemsList = new ArrayList<Items>(); 11 // 向list中填充靜態數據 12 Items items_1 = new Items(); 13 items_1.setName("技嘉筆記本"); 14 items_1.setPrice(6000f); 15 items_1.setDetail("P35K V3筆記本電腦!"); 16 17 Items items_2 = new Items(); 18 items_2.setName("蘋果手機"); 19 items_2.setPrice(5000f); 20 items_2.setDetail("iphone6plus蘋果手機!"); 21 22 itemsList.add(items_1); 23 itemsList.add(items_2); 24 25 // 返回ModelAndView 26 ModelAndView modelAndView = new ModelAndView(); 27 // 相當 於request的setAttribut,在jsp頁面中通過itemsList取數據 28 modelAndView.addObject("itemsList", itemsList); 29 30 // 指定視圖 31 modelAndView.setViewName("order/itemsList"); 32 33 return modelAndView; 34 35 } 36 }
以上就是注解和非注解的幾種實現,其實還可以根據實際需要來實現其他的處理器映射器和處理器適配器。