springmvc經典教程(3)

springmvc教程系列

springmvc史上最好教程(2)

springmvc史上最好教程(1)

一、 註解開發-基礎

1.1 需求

使用springmvc+mybatis架構實現商品信息維護。

 

 

1.2 商品修改

1.2.1 dao

使用逆向工程自動生成的代碼:

ItemsMapper.Java

ItemsMapper.xml

 

1.2.2 service

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. //根據id查詢商品信息  

  2.   

  3. public Items findItemById(int id) throws Exception;  

  4.   

  5. //修改商品信息  

  6.   

  7. public void saveItem(Items items)throws Exception;  



 

1.2.3 controller

修改商品信息顯示頁面:

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. @RequestMapping(value="/editItem")  

  2.   

  3. public String editItem(Model model, Integer id) throws Exception{  

  4.   

  5. //調用service查詢商品信息  

  6.   

  7. Items item = itemService.findItemById(id);  

  8.   

  9. model.addAttribute("item", item);  

  10.   

  11. return "item/editItem";  

  12.   

  13. }  



 

修改商品信息提交:

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. //商品修改提交  

  2.   

  3. @RequestMapping("/editItemSubmit")  

  4.   

  5. public String editItemSubmit(Items items)throws Exception{  

  6.   

  7. System.out.println(items);  

  8.   

  9.    

  10.   

  11. itemService.saveItem(items);  

  12.   

  13. return "success";  

  14.   

  15. }  



 

 

1.2.4 頁面

/WEB-INF/jsp/item/itemsList.jsp

/WEB-INF/jsp/item/editItem.jsp

 

 

1.3 @RequestMapping

 

通過RequestMapping註解可以定義不同的處理器映射規則。


1.3.1 URL路徑映射

@RequestMapping(value="/item")@RequestMapping("/item

value的值是數組,可以將多個url映射到同一個方法

 

1.3.2 窄化請求映射

class上添加@RequestMapping(url)指定通用請求前綴, 限制此類下的所有方法請求url必須以請求前綴開頭,通過此方法對url進行分類管理。

 

如下:

@RequestMapping放在類名上邊,設置請求前綴 

@Controller

@RequestMapping("/item")

 

方法名上邊設置請求映射url

@RequestMapping放在方法名上邊,如下:

@RequestMapping("/queryItem ")


訪問地址爲:/item/queryItem

 

 

1.3.3 請求方法限定

1、限定GET方法

@RequestMapping(method = RequestMethod.GET)

 

如果通過Post訪問則報錯:

HTTP Status 405 - Request method 'POST' not supported

 

例如:

@RequestMapping(value="/editItem",method=RequestMethod.GET)

2、 限定POST方法

 

@RequestMapping(method = RequestMethod.POST)

 

如果通過Post訪問則報錯:

HTTP Status 405 - Request method 'GET' not supported

 

3、GETPOST都可以

@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})

 

 

1.4 controller方法返回值

1.4.1 返回ModelAndView

controller方法中定義ModelAndView對象並返回,對象中可添加model數據、指定view

 

1.4.2 返回void

controller方法形參上可以定義requestresponse,使用requestresponse指定響應結果:

使用request轉向頁面,如下:

request.getRequestDispatcher("頁面路徑").forward(request, response);

通過response頁面重定向:

response.sendRedirect("url")

通過response指定響應結果,例如響應json數據如下:

response.setCharacterEncoding("utf-8");

response.setContentType("application/json;charset=utf-8");

response.getWriter().write("json串");

 

 

1.4.3 返回字符串

1.4.3.1 邏輯視圖名

 

controller方法返回字符串可以指定邏輯視圖名,通過視圖解析器解析爲物理視圖地址。

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. //指定邏輯視圖名,經過視圖解析器解析爲jsp物理路徑:/WEB-INF/jsp/item/editItem.jsp  

  2.   

  3. return "item/editItem";  



 

1.4.3.2 Redirect重定向

Contrller方法返回結果重定向到一個url地址,如下商品修改提交後重定向到商品查詢方法,參數無法帶到商品查詢方法中。

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. //重定向到queryItem.action地址,request無法帶過去  

  2. return "redirect:queryItem.action";  



 

redirect方式相當於“response.sendRedirect()”,轉發後瀏覽器的地址欄變爲轉發後的地址,因爲轉發即執行了一個新的requestresponse

由於新發起一個request原來的參數在轉發時就不能傳遞到下一個url,如果要傳參數可以/item/queryItem.action後邊加參數,如下:

/item/queryItem?...&…..

 

 

1.4.3.3 forward轉發

controller方法執行後繼續執行另一個controller方法,如下商品修改提交後轉向到商品修改頁面,修改商品的id參數可以帶到商品修改方法中。

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. //結果轉發到editItem.action,request可以帶過去  

  2.   

  3. return "forward:editItem.action";  



 

forward方式相當於“request.getRequestDispatcher().forward(request,response)”,轉發後瀏覽器地址欄還是原來的地址。轉發並沒有執行新的requestresponse,而是和轉發前的請求共用一個requestresponse。所以轉發前請求的參數在轉發後仍然可以讀取到。

 

 

 

 

 

1.5 參數綁定

 

1.5.1 默認支持的參數類型

處理器形參中添加如下類型的參數處理適配器會默認識別並進行賦值。

1.5.1.1 HttpServletRequest

通過request對象獲取請求信息

1.5.1.2 HttpServletResponse

通過response處理響應信息

1.5.1.3 HttpSession

通過session對象得到session中存放的對象

1.5.1.4 Model

通過model向頁面傳遞數據,如下:

 

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. //調用service查詢商品信息  

  2. Items item = itemService.findItemById(id);  

  3. model.addAttribute("item", item);  



 

頁面通過${item.XXXX}獲取item對象的屬性值。

 

 

1.5.2 參數綁定介紹

 

註解適配器對RequestMapping標記的方法進行適配,對方法中的形參會進行參數綁定,早期springmvc採用PropertyEditor(屬性編輯器)進行參數綁定將request請求的參數綁定到方法形參上,3.X之後springmvc就開始使用Converter進行參數綁定。

 

1.5.3 @RequestParam

@RequestParam用於綁定單個請求參數。


value參數名字,即入參的請求參數名字,如value=“item_id”表示請求的參數區中的名字爲item_id的參數的值將傳入;

required是否必須,默認是true,表示請求中一定要有相應的參數,否則將報;

TTP Status 400 - Required Integer parameter 'XXXX' is not present

 

defaultValue默認值,表示如果請求中沒有同名參數時的默認值

 

定義如下:

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. public String editItem(@RequestParam(value="item_id",required=true) String id) {  

  2.   

  3. }  



 

形參名稱爲id,但是這裏使用value=" item_id"限定請求的參數名爲item_id,所以頁面傳遞參數的名必須爲item_id

注意:如果請求參數中沒有item_id將跑出異常:

HTTP Status 500 - Required Integer parameter 'item_id' is not present

 

這裏通過required=true限定item_id參數爲必需傳遞,如果不傳遞則報400錯誤,可以使用defaultvalue設置默認值,即使required=true也可以不傳item_id參數值

 

1.5.4 簡單類型

當請求的參數名稱和處理器形參名稱一致時會將請求參數與形參進行綁定。

1.5.4.1 整型

public String editItem(Model model,Integer id) throws Exception

1.5.4.2 字符串

例子略

 

1.5.4.3 單精度/雙精度

例子略

 

1.5.4.4 布爾型

處理器方法:

public String editItem(Model model,Integer id,Boolean status) throws Exception

 

請求url:

http://localhost:8080/springmvc_mybatis/item/editItem.action?id=2&status=false

 

說明:對於布爾類型的參數,請求的參數值爲truefalse

 

 

1.5.5 自定義參數綁定

1.5.5.1 需求

根據業務需求自定義日期格式進行參數綁定。

 

1.5.5.2 propertyEditor

1.5.5.2.1 使用WebDataBinder 

controller方法中通過@InitBinder標識方法爲參數綁定方法,通過WebDataBinder註冊屬性編輯器,問題是此方法只能在單個controller類中註冊。

 

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. /** 

  2.  

  3.  * 註冊屬性編輯器(字符串轉換爲日期) 

  4.  

  5.  */  

  6.   

  7. @InitBinder  

  8.   

  9. public void initBinder(WebDataBinder binder) throws Exception {  

  10.   

  11. binder.registerCustomEditor(Date.classnew CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));  

  12.   

  13. }  



 

 

1.5.5.2.2 使用WebDataBinder 

controller方法中通過@InitBinder標識方法爲參數綁定方法,通過WebDataBinder註冊屬性編輯器,問題是此方法只能在單個controller類中註冊。


 

如下:

編寫CustomPropertyEditor

 

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. public class CustomPropertyEditor implements PropertyEditorRegistrar {  

  2.   

  3.    

  4.   

  5. @Override  

  6.   

  7. public void registerCustomEditors(PropertyEditorRegistry registry) {  

  8.   

  9. registry.registerCustomEditor(Date.class, new CustomDateEditor(new  

  10.   

  11.  SimpleDateFormat("yyyy-MM-dd HH-mm-ss"),true));  

  12.   

  13. }  

  14.   

  15.    

  16.   

  17. }  



 

配置如下:

 

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. <!-- 註冊屬性編輯器 -->  

  2.   

  3. <bean id="customPropertyEditor" class="com.sihai.ssm.propertyeditor.CustomPropertyEditor"></bean>   

  4.   

  5. <!-- 自定義webBinder -->  

  6.   

  7. <bean id="customBinder"  

  8.   

  9. class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">  

  10.   

  11. <property name="propertyEditorRegistrars">  

  12.   

  13. <list>  

  14.   

  15. <ref bean="customPropertyEditor"/>  

  16.   

  17. </list>  

  18.   

  19. </property>  

  20.   

  21. </bean>  

  22.   

  23.    

  24.   

  25. <!--註解適配器 -->  

  26.   

  27. <bean  

  28.   

  29. class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">  

  30.   

  31.  <property name="webBindingInitializer" ref="customBinder"></property>   

  32.   

  33. </bean>  

  34.   

  35.    

  36.   

  37.    



 

1.5.5.3 Converter

1.5.5.3.1 自定義Converter

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. public class CustomDateConverter implements Converter<String, Date> {  

  2.   

  3.    

  4.   

  5. @Override  

  6.   

  7. public Date convert(String source) {  

  8.   

  9. try {  

  10.   

  11. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");  

  12.   

  13. return simpleDateFormat.parse(source);  

  14.   

  15. catch (Exception e) {  

  16.   

  17. e.printStackTrace();  

  18.   

  19. }  

  20.   

  21. return null;  

  22.   

  23. }  

  24.   

  25.    

  26.   

  27. }  

  28.   

  29.    



1.5.5.3.2 配置方式1

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. <!--註解適配器 -->  

  2.   

  3. <bean  

  4.   

  5. class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">  

  6.   

  7.  <property name="webBindingInitializer" ref="customBinder"></property>   

  8.   

  9. </bean>  

  10.   

  11. <!-- 自定義webBinder -->  

  12.   

  13. <bean id="customBinder"  

  14.   

  15. class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">  

  16.   

  17. <property name="conversionService" ref="conversionService" />  

  18.   

  19. </bean>  

  20.   

  21. <!-- conversionService -->  

  22.   

  23. <bean id="conversionService"  

  24.   

  25. class="org.springframework.format.support.FormattingConversionServiceFactoryBean">  

  26.   

  27. <!-- 轉換器 -->  

  28.   

  29. <property name="converters">  

  30.   

  31. <list>  

  32.   

  33. <bean class="cn.itcast.ssm.controller.converter.CustomDateConverter"/>  

  34.   

  35. </list>  

  36.   

  37. </property>  

  38.   

  39. </bean>  



 

1.5.5.3.3 配置方式2

 

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. <mvc:annotation-driven conversion-service="conversionService">  

  2.   

  3. </mvc:annotation-driven>  

  4.   

  5. <!-- conversionService -->  

  6.   

  7. <bean id="conversionService"  

  8.   

  9. class="org.springframework.format.support.FormattingConversionServiceFactoryBean">  

  10.   

  11. <!-- 轉換器 -->  

  12.   

  13. <property name="converters">  

  14.   

  15. <list>  

  16.   

  17. <bean class="cn.itcast.ssm.controller.converter.CustomDateConverter"/>  

  18.   

  19. </list>  

  20.   

  21. </property>  

  22.   

  23. </bean>  



 

 

1.5.6 pojo

1.5.6.1 簡單pojo

pojo對象中的屬性名於傳遞進來的屬性名對應,如果傳進來的參數名稱和對象中的屬性名稱一致則將參數值設置在pojo對象中

 

頁面定義如下;

 

<input type="text" name="name"/>

<input type="text" name="price"/>

 

Contrller方法定義如下:

 

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. @RequestMapping("/editItemSubmit")  

  2.   

  3. public String editItemSubmit(Items items)throws Exception{  

  4.   

  5. System.out.println(items);  



請求的參數名稱和pojo的屬性名稱一致,會自動將請求參數賦值給pojo的屬性。

 

1.5.6.2 包裝pojo

如果採用類似struts中對象.屬性的方式命名,需要將pojo對象作爲一個包裝對象的屬性,action中以該包裝對象作爲形參。

包裝對象定義如下:

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. Public class QueryVo {  

  2.   

  3. private Items items;  

  4.   

  5.    

  6.   

  7. }  



 

頁面定義:

 

<input type="text" name="items.name" />

<input type="text" name="items.price" />

 

Controller方法定義如下:

 

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{  

  2.   

  3. System.out.println(queryVo.getItems());  



 

 

1.5.6.3 ModelAttribute

@ModelAttribute作用如下:

1、綁定請求參數到pojo並且暴露爲模型數據傳到視圖頁面

此方法可實現數據回顯效果。

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1.    

  2.   

  3. // 商品修改提交  

  4.   

  5. @RequestMapping("/editItemSubmit")  

  6.   

  7. public String editItemSubmit(@ModelAttribute("item") Items items,Model model)  



頁面:

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. <tr>  

  2.   

  3. <td>商品名稱</td>  

  4.   

  5. <td><input type="text" name="name" value="${item.name }"/></td>  

  6.   

  7. </tr>  

  8.   

  9. <tr>  

  10.   

  11. <td>商品價格</td>  

  12.   

  13. <td><input type="text" name="price" value="${item.price }"/></td>  

  14.   

  15. </tr>  



 

 

如果不用@ModelAttribute可以使用model.addAttribute("item", items)完成數據回顯。

 

2、將方法返回值暴露爲模型數據傳到視圖頁面

 

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. //商品分類  

  2.   

  3. @ModelAttribute("itemtypes")  

  4.   

  5. public Map<String, String> getItemTypes(){  

  6.   

  7. Map<String, String> itemTypes = new HashMap<String,String>();  

  8.   

  9. itemTypes.put("101""數碼");  

  10.   

  11. itemTypes.put("102""母嬰");  

  12.   

  13. return itemTypes;  

  14.   

  15. }  



 

頁面:

商品類型:

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. <select name="itemtype">  

  2.   

  3. <c:forEach items="${itemtypes }" var="itemtype">  

  4.   

  5. <option value="${itemtype.key }">${itemtype.value }</option>  

  6.   

  7. </c:forEach>  

  8.   

  9. </select>  



 

1.5.7 集合類

1.5.7.1 字符串數組

頁面定義如下:

頁面選中多個checkbox向controller方法傳遞

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. <input type="checkbox" name="item_id" value="001"/>  

  2.   

  3. <input type="checkbox" name="item_id" value="002"/>  

  4.   

  5. <input type="checkbox" name="item_id" value="002"/>  

  6.   

  7.    



 

傳遞到controller方法中的格式是:001,002,003

 

Controller方法中可以用String[]接收,定義如下:

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. public String deleteitem(String[] item_id)throws Exception{  

  2.   

  3. System.out.println(item_id);  

  4.   

  5. }  



 

1.5.7.2 List

List中存放對象,並將定義的List放在包裝類中,action使用包裝對象接收。

 

List中對象:

成績對象

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. Public class QueryVo {  

  2.   

  3. Private List<Items> itemList;//訂單明細  

  4.   

  5.    

  6.   

  7.   //get/set方法..  

  8.   

  9. }  



 

 

包裝類中定義List對象,並添加get/set方法如下:

 

 

頁面:

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1.    

  2.   

  3.    

  4.   

  5. <tr>  

  6.   

  7. <td>  

  8.   

  9. <input type="text" name=" itemList[0].id" value="${item.id}"/>  

  10.   

  11. </td>  

  12.   

  13. <td>  

  14.   

  15. <input type="text" name=" itemList[0].name" value="${item.name }"/>  

  16.   

  17. </td>  

  18.   

  19. <td>  

  20.   

  21. <input type="text" name=" itemList[0].price" value="${item.price}"/>  

  22.   

  23. </td>  

  24.   

  25. </tr>  

  26.   

  27. <tr>  

  28.   

  29. <td>  

  30.   

  31. <input type="text" name=" itemList[1].id" value="${item.id}"/>  

  32.   

  33. </td>  

  34.   

  35. <td>  

  36.   

  37. <input type="text" name=" itemList[1].name" value="${item.name }"/>  

  38.   

  39. </td>  

  40.   

  41. <td>  

  42.   

  43. <input type="text" name=" itemList[1].price" value="${item.price}"/>  

  44.   

  45. </td>  

  46.   

  47. </tr>  



 

 

Contrller方法定義如下:

 

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{  

  2.   

  3. System.out.println(queryVo.getItemList());  

  4.   

  5. }  



 

1.5.7.3 Map

在包裝類中定義Map對象,並添加get/set方法,action使用包裝對象接收。

包裝類中定義Map對象如下:

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. Public class QueryVo {  

  2.   

  3. private Map<String, Object> itemInfo = new HashMap<String, Object>();  

  4.   

  5.   //get/set方法..  

  6.   

  7. }  

  8.   

  9.    



 

 

頁面定義如下:

 

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. <tr>  

  2.   

  3. <td>學生信息:</td>  

  4.   

  5. <td>  

  6.   

  7. 姓名:<inputtypeinputtype="text"name="itemInfo['name']"/>  

  8.   

  9. 年齡:<inputtypeinputtype="text"name="itemInfo['price']"/>  

  10.   

  11. .. .. ..  

  12.   

  13. </td>  

  14.   

  15. </tr>  



 

Contrller方法定義如下:

 

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{  

  2.   

  3. System.out.println(queryVo.getStudentinfo());  

  4.   

  5. }  



 

 

 

 

 

1.6 問題總結

1.6.1 404

頁面找不到,視圖找不到。

 

 

 

 

 

HandlerMapping根據url沒有找到Handler

 

 

1.6.2 Post時中文亂碼

web.xml中加入:

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. <filter>  

  2.   

  3. <filter-name>CharacterEncodingFilter</filter-name>  

  4.   

  5. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  

  6.   

  7. <init-param>  

  8.   

  9. <param-name>encoding</param-name>  

  10.   

  11. <param-value>utf-8</param-value>  

  12.   

  13. </init-param>  

  14.   

  15. </filter>  

  16.   

  17. <filter-mapping>  

  18.   

  19. <filter-name>CharacterEncodingFilter</filter-name>  

  20.   

  21. <url-pattern>/*</url-pattern>  

  22.   

  23. </filter-mapping>  



 

以上可以解決post請求亂碼問題。

對於get請求中文參數出現亂碼解決方法有兩個:

 

修改tomcat配置文件添加編碼與工程編碼一致,如下:

 

[html] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. <Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>  


 

另外一種方法對參數進行重新編碼:

[java] view plain copy print?在CODE上查看代碼片派生到我的代碼片

  1. String userName new  

  2.   

  3. String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")  



 

ISO8859-1tomcat默認編碼,需要將tomcat編碼後的內容按utf-8編碼

 

 

 

1.7 struts2不同

1、 springmvc的入口是一個servlet即前端控制器,而struts2入口是一個filter過慮器。

2、 springmvc是基於方法開發(一個url對應一個方法),請求參數傳遞到方法的形參,可以設計爲單例或多例(建議單例)struts2是基於類開發,傳遞參數是通過類的屬性,只能設計爲多例。

3、 Struts採用值棧存儲請求和響應的數據,通過OGNL存取數據,springmvc通過參數解析器是將request請求內容解析,並給方法形參賦值,將數據和視圖封裝成ModelAndView對象,最後又將ModelAndView中的模型數據通過reques域傳輸到頁面。Jsp視圖解析器默認使用jstl

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章