springmvc教程--注解开发基础详解
springmvc教程系列
springmvc史上最好教程(2)
springmvc史上最好教程(1)
一、 注解開發-基礎
1.1?需求
使用springmvc+mybatis架構實現商品信息維護。
1.2?商品修改
1.2.1?dao
使用逆向工程自動生成的代碼:
ItemsMapper.java
ItemsMapper.xml
1.2.2?service
//根據id查詢商品信息public Items findItemById(int id) throws Exception;//修改商品信息public void saveItem(Items items)throws Exception;1.2.3?controller
修改商品信息顯示頁面:
@RequestMapping(value="/editItem")public String editItem(Model model, Integer id) throws Exception{//調用service查詢商品信息Items item = itemService.findItemById(id);model.addAttribute("item", item);return "item/editItem";}修改商品信息提交:
//商品修改提交@RequestMapping("/editItemSubmit")public String editItemSubmit(Items items)throws Exception{System.out.println(items);itemService.saveItem(items);return "success";}?
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、GET和POST都可以
@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})
1.4?controller方法返回值
1.4.1?返回ModelAndView
controller方法中定義ModelAndView對象并返回,對象中可添加model數據、指定view。
1.4.2?返回void
在controller方法形參上可以定義request和response,使用request或response指定響應結果:
使用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方法返回字符串可以指定邏輯視圖名,通過視圖解析器解析為物理視圖地址。
//指定邏輯視圖名,經過視圖解析器解析為jsp物理路徑:/WEB-INF/jsp/item/editItem.jspreturn "item/editItem";1.4.3.2?Redirect重定向
Contrller方法返回結果重定向到一個url地址,如下商品修改提交后重定向到商品查詢方法,參數無法帶到商品查詢方法中。
//重定向到queryItem.action地址,request無法帶過去 return "redirect:queryItem.action";redirect方式相當于“response.sendRedirect()”,轉發后瀏覽器的地址欄變為轉發后的地址,因為轉發即執行了一個新的request和response。
由于新發起一個request原來的參數在轉發時就不能傳遞到下一個url,如果要傳參數可以/item/queryItem.action后邊加參數,如下:
/item/queryItem?...&…..
1.4.3.3?forward轉發
controller方法執行后繼續執行另一個controller方法,如下商品修改提交后轉向到商品修改頁面,修改商品的id參數可以帶到商品修改方法中。
//結果轉發到editItem.action,request可以帶過去return "forward:editItem.action";forward方式相當于“request.getRequestDispatcher().forward(request,response)”,轉發后瀏覽器地址欄還是原來的地址。轉發并沒有執行新的request和response,而是和轉發前的請求共用一個request和response。所以轉發前請求的參數在轉發后仍然可以讀取到。
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向頁面傳遞數據,如下:
//調用service查詢商品信息 Items item = itemService.findItemById(id); 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:默認值,表示如果請求中沒有同名參數時的默認值
定義如下:
public String editItem(@RequestParam(value="item_id",required=true) String id) {}形參名稱為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
說明:對于布爾類型的參數,請求的參數值為true或false。
1.5.5?自定義參數綁定
1.5.5.1?需求
根據業務需求自定義日期格式進行參數綁定。
1.5.5.2?propertyEditor
1.5.5.2.1?使用WebDataBinder?
在controller方法中通過@InitBinder標識方法為參數綁定方法,通過WebDataBinder注冊屬性編輯器,問題是此方法只能在單個controller類中注冊。
/*** 注冊屬性編輯器(字符串轉換為日期)*/@InitBinderpublic void initBinder(WebDataBinder binder) throws Exception {binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));}1.5.5.2.2 使用WebDataBinder?
在controller方法中通過@InitBinder標識方法為參數綁定方法,通過WebDataBinder注冊屬性編輯器,問題是此方法只能在單個controller類中注冊。
如下:
編寫CustomPropertyEditor:
public class CustomPropertyEditor implements PropertyEditorRegistrar {@Overridepublic void registerCustomEditors(PropertyEditorRegistry registry) {registry.registerCustomEditor(Date.class, new CustomDateEditor(newSimpleDateFormat("yyyy-MM-dd HH-mm-ss"),true));}}配置如下:
<!-- 注冊屬性編輯器 --><bean id="customPropertyEditor" class="com.sihai.ssm.propertyeditor.CustomPropertyEditor"></bean> <!-- 自定義webBinder --><bean id="customBinder"class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"><property name="propertyEditorRegistrars"><list><ref bean="customPropertyEditor"/></list></property></bean><!--注解適配器 --><beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="webBindingInitializer" ref="customBinder"></property> </bean>1.5.5.3?Converter
1.5.5.3.1?自定義Converter
public class CustomDateConverter implements Converter<String, Date> {@Overridepublic Date convert(String source) {try {SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");return simpleDateFormat.parse(source);} catch (Exception e) {e.printStackTrace();}return null;}}1.5.5.3.2?配置方式1
<!--注解適配器 --><beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="webBindingInitializer" ref="customBinder"></property> </bean><!-- 自定義webBinder --><bean id="customBinder"class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"><property name="conversionService" ref="conversionService" /></bean><!-- conversionService --><bean id="conversionService"class="org.springframework.format.support.FormattingConversionServiceFactoryBean"><!-- 轉換器 --><property name="converters"><list><bean class="cn.itcast.ssm.controller.converter.CustomDateConverter"/></list></property></bean>1.5.5.3.3?配置方式2
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven><!-- conversionService --><bean id="conversionService"class="org.springframework.format.support.FormattingConversionServiceFactoryBean"><!-- 轉換器 --><property name="converters"><list><bean class="cn.itcast.ssm.controller.converter.CustomDateConverter"/></list></property></bean>1.5.6?pojo
1.5.6.1?簡單pojo
將pojo對象中的屬性名于傳遞進來的屬性名對應,如果傳進來的參數名稱和對象中的屬性名稱一致則將參數值設置在pojo對象中
頁面定義如下;
<input type="text" name="name"/>
<input type="text" name="price"/>
Contrller方法定義如下:
@RequestMapping("/editItemSubmit")public String editItemSubmit(Items items)throws Exception{System.out.println(items);請求的參數名稱和pojo的屬性名稱一致,會自動將請求參數賦值給pojo的屬性。
1.5.6.2?包裝pojo
如果采用類似struts中對象.屬性的方式命名,需要將pojo對象作為一個包裝對象的屬性,action中以該包裝對象作為形參。
包裝對象定義如下:
Public class QueryVo {private Items items;}頁面定義:
<input type="text" name="items.name" />
<input type="text" name="items.price" />
Controller方法定義如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{System.out.println(queryVo.getItems());1.5.6.3 ModelAttribute
@ModelAttribute作用如下:
1、綁定請求參數到pojo并且暴露為模型數據傳到視圖頁面
此方法可實現數據回顯效果。
// 商品修改提交@RequestMapping("/editItemSubmit")public String editItemSubmit(@ModelAttribute("item") Items items,Model model)頁面:
<tr><td>商品名稱</td><td><input type="text" name="name" value="${item.name }"/></td></tr><tr><td>商品價格</td><td><input type="text" name="price" value="${item.price }"/></td></tr>?
?
如果不用@ModelAttribute可以使用model.addAttribute("item", items)完成數據回顯。
2、將方法返回值暴露為模型數據傳到視圖頁面
//商品分類@ModelAttribute("itemtypes")public Map<String, String> getItemTypes(){Map<String, String> itemTypes = new HashMap<String,String>();itemTypes.put("101", "數碼");itemTypes.put("102", "母嬰");return itemTypes;}頁面:
商品類型:
<select name="itemtype"><c:forEach items="${itemtypes }" var="itemtype"><option value="${itemtype.key }">${itemtype.value }</option></c:forEach></select>1.5.7?集合類
1.5.7.1?字符串數組
頁面定義如下:
頁面選中多個checkbox向controller方法傳遞
<input type="checkbox" name="item_id" value="001"/><input type="checkbox" name="item_id" value="002"/><input type="checkbox" name="item_id" value="002"/>傳遞到controller方法中的格式是:001,002,003
Controller方法中可以用String[]接收,定義如下:
public String deleteitem(String[] item_id)throws Exception{System.out.println(item_id);}1.5.7.2?List
List中存放對象,并將定義的List放在包裝類中,action使用包裝對象接收。
List中對象:
成績對象
Public class QueryVo {Private List<Items> itemList;//訂單明細//get/set方法..}包裝類中定義List對象,并添加get/set方法如下:
頁面:
<tr><td><input type="text" name=" itemList[0].id" value="${item.id}"/></td><td><input type="text" name=" itemList[0].name" value="${item.name }"/></td><td><input type="text" name=" itemList[0].price" value="${item.price}"/></td></tr><tr><td><input type="text" name=" itemList[1].id" value="${item.id}"/></td><td><input type="text" name=" itemList[1].name" value="${item.name }"/></td><td><input type="text" name=" itemList[1].price" value="${item.price}"/></td></tr>Contrller方法定義如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{System.out.println(queryVo.getItemList());}1.5.7.3?Map
在包裝類中定義Map對象,并添加get/set方法,action使用包裝對象接收。
包裝類中定義Map對象如下:
Public class QueryVo {private Map<String, Object> itemInfo = new HashMap<String, Object>();//get/set方法..}頁面定義如下:
<tr><td>學生信息:</td><td>姓名:<inputtype="text"name="itemInfo['name']"/>年齡:<inputtype="text"name="itemInfo['price']"/>.. .. ..</td></tr>Contrller方法定義如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{System.out.println(queryVo.getStudentinfo());}1.6?問題總結
1.6.1?404
頁面找不到,視圖找不到。
HandlerMapping根據url沒有找到Handler。
1.6.2?Post時中文亂碼
在web.xml中加入:
<filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>以上可以解決post請求亂碼問題。
對于get請求中文參數出現亂碼解決方法有兩個:
修改tomcat配置文件添加編碼與工程編碼一致,如下:
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>另外一種方法對參數進行重新編碼:
String userName newString(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")ISO8859-1是tomcat默認編碼,需要將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。
總結
以上是生活随笔為你收集整理的springmvc教程--注解开发基础详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springmvc教程(3)
- 下一篇: springmvc教程(4)