springmvc教程系列
一、 註解開發-基礎
1.1 需求
使用springmvc+mybatis架構實現商品信息維護。
1.2 商品修改
1.2.1 dao
使用逆向工程自動生成的代碼:
ItemsMapper.Java
ItemsMapper.xml
1.2.2 service
[java] view plain copy print?
//根據id查詢商品信息
public Items findItemById(int id) throws Exception;
//修改商品信息
public void saveItem(Items items)throws Exception;
1.2.3 controller
修改商品信息顯示頁面:
[java] view plain copy print?
@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";
}
修改商品信息提交:
[java] view plain copy print?
//商品修改提交
@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方法返回字符串可以指定邏輯視圖名,通過視圖解析器解析爲物理視圖地址。
[html] view plain copy print?
//指定邏輯視圖名,經過視圖解析器解析爲jsp物理路徑:/WEB-INF/jsp/item/editItem.jsp
return "item/editItem";
1.4.3.2 Redirect重定向
Contrller方法返回結果重定向到一個url地址,如下商品修改提交後重定向到商品查詢方法,參數無法帶到商品查詢方法中。
[html] view plain copy print?
//重定向到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參數可以帶到商品修改方法中。
[html] view plain copy print?
//結果轉發到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向頁面傳遞數據,如下:
[html] view plain copy print?
//調用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:默認值,表示如果請求中沒有同名參數時的默認值
定義如下:
[html] view plain copy print?
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類中註冊。
[java] view plain copy print?
/**
* 註冊屬性編輯器(字符串轉換爲日期)
*/
@InitBinder
public 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:
[html] view plain copy print?
public class CustomPropertyEditor implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Date.class, new CustomDateEditor(new
SimpleDateFormat("yyyy-MM-dd HH-mm-ss"),true));
}
}
配置如下:
[html] view plain copy print?
<!-- 註冊屬性編輯器 -->
<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>
<!--註解適配器 -->
<bean
class="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
[java] view plain copy print?
public class CustomDateConverter implements Converter<String, Date> {
@Override
public 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
[html] view plain copy print?
<!--註解適配器 -->
<bean
class="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
[html] view plain copy print?
<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方法定義如下:
[java] view plain copy print?
@RequestMapping("/editItemSubmit")
public String editItemSubmit(Items items)throws Exception{
System.out.println(items);
請求的參數名稱和pojo的屬性名稱一致,會自動將請求參數賦值給pojo的屬性。
1.5.6.2 包裝pojo
如果採用類似struts中對象.屬性的方式命名,需要將pojo對象作爲一個包裝對象的屬性,action中以該包裝對象作爲形參。
包裝對象定義如下:
[java] view plain copy print?
Public class QueryVo {
private Items items;
}
頁面定義:
<input type="text" name="items.name" />
<input type="text" name="items.price" />
Controller方法定義如下:
[html] view plain copy print?
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItems());
1.5.6.3 ModelAttribute
@ModelAttribute作用如下:
1、綁定請求參數到pojo並且暴露爲模型數據傳到視圖頁面
此方法可實現數據回顯效果。
[html] view plain copy print?
// 商品修改提交
@RequestMapping("/editItemSubmit")
public String editItemSubmit(@ModelAttribute("item") Items items,Model model)
頁面:
[html] view plain copy print?
<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、將方法返回值暴露爲模型數據傳到視圖頁面
[java] view plain copy print?
//商品分類
@ModelAttribute("itemtypes")
public Map<String, String> getItemTypes(){
Map<String, String> itemTypes = new HashMap<String,String>();
itemTypes.put("101", "數碼");
itemTypes.put("102", "母嬰");
return itemTypes;
}
頁面:
商品類型:
[html] view plain copy print?
<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方法傳遞
[html] view plain copy print?
<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[]接收,定義如下:
[html] view plain copy print?
public String deleteitem(String[] item_id)throws Exception{
System.out.println(item_id);
}
1.5.7.2 List
List中存放對象,並將定義的List放在包裝類中,action使用包裝對象接收。
List中對象:
成績對象
[java] view plain copy print?
Public class QueryVo {
Private List<Items> itemList;//訂單明細
//get/set方法..
}
包裝類中定義List對象,並添加get/set方法如下:
頁面:
[html] view plain copy print?
<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方法定義如下:
[java] view plain copy print?
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItemList());
}
1.5.7.3 Map
在包裝類中定義Map對象,並添加get/set方法,action使用包裝對象接收。
包裝類中定義Map對象如下:
[java] view plain copy print?
Public class QueryVo {
private Map<String, Object> itemInfo = new HashMap<String, Object>();
//get/set方法..
}
頁面定義如下:
[html] view plain copy print?
<tr>
<td>學生信息:</td>
<td>
姓名:<inputtypeinputtype="text"name="itemInfo['name']"/>
年齡:<inputtypeinputtype="text"name="itemInfo['price']"/>
.. .. ..
</td>
</tr>
Contrller方法定義如下:
[java] view plain copy print?
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中加入:
[html] view plain copy print?
<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配置文件添加編碼與工程編碼一致,如下:
[html] view plain copy print?
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
另外一種方法對參數進行重新編碼:
[java] view plain copy print?
String userName new
String(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。