經(jīng)過(guò)上篇文章Spring忘巧、Spring MVC與Mybatis整合工程搭建我們便將SSM的環(huán)境搭建了顽染,接下來(lái)我們便利用這個(gè)工程來(lái)開(kāi)發(fā)項(xiàng)目帶你快速學(xué)會(huì)使用SSM整合框架進(jìn)行開(kāi)發(fā)涩澡。我們同樣采用的是注解處理器映射器與注解處理器適配器進(jìn)行開(kāi)發(fā)智蝠。
寫(xiě)在前面的話:源代碼請(qǐng)點(diǎn)擊這里前往我的github
你也可以前往我的個(gè)人博客查看更多有用的文章:http://codingxiaxw.cn
1.實(shí)現(xiàn)商品的列表展示
1.1提出需求
功能描述:在頁(yè)面中展示商品列表。
1.2編寫(xiě)表
sql語(yǔ)句見(jiàn)github中.sql文件亥揖。
1.3持久層mapper的編寫(xiě)
編寫(xiě)好數(shù)據(jù)庫(kù)后我們便可以通過(guò)MyBatis逆向工程快速生成對(duì)單表映射的sql珊擂,包括mapper.java、mapper.xml和pojo類徐块。
根據(jù)逆向工程生成的這三個(gè)文件與單表都是一對(duì)一的關(guān)系未玻,例如通過(guò)Items表會(huì)生成ItemsMapper.java、ItemsMapper.xml和Items.java的pojo類胡控,這里我們?yōu)榱吮阌谛枨蟮臄U(kuò)展扳剿,所以另外自己編寫(xiě)一個(gè)ItemsCustom.java并繼承Items.java和Items.java的包裝類ItemsQueryVo.java,代碼如下:
public class ItemsQueryVo {
//商品信息
private ItemsCustom itemsCustom;
public ItemsCustom getItemsCustom() {
return itemsCustom;
}
public void setItemsCustom(ItemsCustom itemsCustom) {
this.itemsCustom = itemsCustom;
}
}
然后自己編寫(xiě)一個(gè)ItemsCustomerMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.ItemsMapperCustom">
<!-- 商品查詢的sql片段
建議是以單表為單位定義查詢條件
建議將常用的查詢條件都寫(xiě)出來(lái)
-->
<sql id="query_items_where">
<if test="itemsCustom!=null">
<if test="itemsCustom.name!=null and itemsCustom.name!=''">
and name like '%${itemsCustom.name}%'
</if>
<if test="itemsCustom.id!=null">
and id = #{itemsCustom.id}
</if>
</if>
</sql>
<!-- 商品查詢
parameterType:輸入 查詢條件
-->
<select id="findItemsList" parameterType="po.ItemsQueryVo"
resultType="po.ItemsCustom">
SELECT * FROM items
<where>
<include refid="query_items_where"/>
</where>
</select>
</mapper>
與ItemsCustomMapper.java:
public interface ItemsMapperCustom {
// 商品查詢列表
List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo)
throws Exception;
}
至于Mapper的配置我們已經(jīng)在springmvc.xml中通過(guò)spring組件掃描器
<!--
MapperScannerConfigurer:mapper的掃描器昼激,將包下邊的mapper接口自動(dòng)創(chuàng)建代理對(duì)象庇绽,
自動(dòng)創(chuàng)建到spring容器中,bean的id是mapper的類名(首字母小寫(xiě))
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 配置掃描包的路徑
如果要掃描多個(gè)包橙困,中間使用半角逗號(hào)分隔
要求mapper.xml和mapper.java同名且在同一個(gè)目錄
-->
<property name="basePackage" value="mapper"/>
<!-- 使用sqlSessionFactoryBeanName -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
進(jìn)行了統(tǒng)一的配置瞧掺。
接口里面調(diào)用xml文件中查詢表中所有商品列表信息的sql語(yǔ)句,然后我們便可以進(jìn)行業(yè)務(wù)邏輯層的代碼編寫(xiě).
1.4業(yè)務(wù)邏輯層service的編寫(xiě)
首先我們?cè)趕ervice包下創(chuàng)建一個(gè)商品的service接口ItemsService.java文件凡傅,里面編寫(xiě)的方法和ItemsCustomMapper.java中的方法對(duì)應(yīng)以實(shí)現(xiàn)商品列表的查詢:
public interface ItemsService {
//商品的查詢列表
public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo)
throws Exception;
}
然后編寫(xiě)其實(shí)現(xiàn)類ItemsServiceImpl.java:
public class ItemsServiceImpl implements ItemsService {
//注入mapper
@Autowired
private ItemsMapperCustom itemsMapperCustom;
//商品的查詢列表
@Override
public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception {
return itemsMapperCustom.findItemsList(itemsQueryVo);
}
}
代碼中通過(guò)Spring框架的DI注入依賴對(duì)象mapper即itemsMapperCustom對(duì)象辟狈,然后調(diào)用itemsMapperCustom的findItemsList方法實(shí)現(xiàn)商品列表查詢,然后在spring配置文件applicationContext-service.xml中要進(jìn)行service的配置,添加如下標(biāo)簽:
<!--商品配置的service-->
<bean id="itemsService" class="service.impl.ItemsServiceImpl"/>
便可夏跷。接下來(lái)便應(yīng)該完成控制層Controller.java的代碼編寫(xiě)了哼转。
1.5控制層Controller的編寫(xiě)
在controller包下創(chuàng)建一個(gè)ItemsController.java,里面編寫(xiě)代碼:
@Controller
public class ItemsController {
//注入service
@Autowired
private ItemsService itemsService;
@RequestMapping("/queryItems")
public ModelAndView queryItems() throws Exception {
//調(diào)用servie來(lái)查詢商品列表
List<ItemsCustom> itemsList=itemsService.findItemsList(null);
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("itemsList",itemsList);
//指定邏輯視圖名itemsList
modelAndView.setViewName("itemsList");
return modelAndView;
}
}
通過(guò)@Autowired注解完成service的依賴注入槽华,通過(guò)@Controller注解將Controller自動(dòng)添加到spring容器IOC中壹蔓,通過(guò)@RequestMapping("/queryItems")注解指明訪問(wèn)該Controller的url。
至于itemsList.jsp的頁(yè)面編寫(xiě)代碼如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查詢商品列表</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/items/queryItem.action" method="post">
查詢條件:
<table width="100%" border=1>
<tr>
<td><input type="submit" value="查詢"/></td>
</tr>
</table>
商品列表:
<table width="100%" border=1>
<tr>
<td>商品名稱</td>
<td>商品價(jià)格</td>
<td>生產(chǎn)日期</td>
<td>商品描述</td>
<td>操作</td>
</tr>
<c:forEach items="${itemsList }" var="item">
<tr>
<td>${item.name }</td>
<td>${item.price }</td>
<td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td>${item.detail }</td>
<td><a href="${pageContext.request.contextPath }/items/editItems.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
然后我們運(yùn)行服務(wù)器猫态,輸入網(wǎng)址http://localhost:8080/SpringMvcMybatis/queryItems.action
佣蓉,發(fā)現(xiàn)無(wú)法看到頁(yè)面披摄,這是因?yàn)槲覀兊膕pring配置文件沒(méi)有得到加載,需要在web.xml文件中加入如下內(nèi)容進(jìn)行spring容器的配置:
<!--配置spring容器監(jiān)聽(tīng)器-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/config/spring/applicationContext-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
然后重新運(yùn)行服務(wù)器并輸入網(wǎng)址勇凭,看到如下頁(yè)面疚膊,說(shuō)明成功使用SSM框架完成開(kāi)發(fā)顯示商品列表的項(xiàng)目:
到此,我們便通過(guò)SSM的整合工程項(xiàng)目套像,完成了對(duì)商品列表的查詢酿联。接下來(lái)我們?cè)賹?shí)現(xiàn)對(duì)商品的另一個(gè)功能:修改商品信息。
2.實(shí)現(xiàn)商品信息的修改
2.1需求
功能描述:商品信息修改夺巩。操作流程:1.在商品列表頁(yè)面點(diǎn)擊修改連接。2.打開(kāi)商品修改頁(yè)面周崭,顯示了當(dāng)前商品的信息(根據(jù)商品id查詢商品信息)柳譬。3.修改商品信息,點(diǎn)擊提交(更新商品信息)续镇。
通過(guò)此案例美澳,我們也會(huì)穿插用SSM進(jìn)行注解開(kāi)發(fā)的基礎(chǔ)知識(shí)如: @RequestMapping注解的改善、controller方法返回值摸航、Controller方法中的參數(shù)與頁(yè)面參數(shù)的綁定制跟。
2.2mapper的編寫(xiě)
此功能涉及到的mapper為ItemsMapper.java與ItemsMapper.xml,已使用逆向工程為我們生成酱虎。
2.3service的編寫(xiě)
在ItemsService接口中添加方法:
//根據(jù)商品id查詢商品信息
public ItemsCustom findItemsById(int id) throws Exception;
//更新商品信息
/**
* 定義service接口雨膨,遵循單一職責(zé),將業(yè)務(wù)參數(shù)細(xì)化(不要使用包裝類型读串,比如map)
* @param id 修改商品的id
* @param itemsCustom 修改商品的信息
* @throws Exception
*/
public void updateItems(Integer id,ItemsCustom itemsCustom) throws Exception;
然后是實(shí)現(xiàn)類ItemsServiceImpl.java:
//注入依賴對(duì)象itemsMapper
@Autowired
private ItemsMapper itemsMapper;
@Override
public ItemsCustom findItemsById(int id) throws Exception {
Items items=itemsMapper.selectByPrimaryKey(id);
//在這里以后隨著需求的變化聊记,需要查詢商品的其它相關(guān)信息,返回到controller
//所以這個(gè)時(shí)候用到擴(kuò)展類更好恢暖,如下
ItemsCustom itemsCustom=new ItemsCustom();
//將items的屬性拷貝到itemsCustom
BeanUtils.copyProperties(items,itemsCustom);
return itemsCustom;
}
@Override
public void updateItems(Integer id,ItemsCustom itemsCustom) throws Exception {
//在service中一定要寫(xiě)業(yè)務(wù)代碼
//對(duì)于關(guān)鍵業(yè)務(wù)數(shù)據(jù)的非空校驗(yàn)
if (id==null)
{
//拋出異常排监,提示調(diào)用接口的用戶,id不能唯恐
//...
}
itemsMapper.updateByPrimaryKeyWithBLOBs(itemsCustom);
}
說(shuō)一句:對(duì)service的開(kāi)發(fā)是整個(gè)系統(tǒng)中開(kāi)發(fā)最重要的部分杰捂,所以你要把service的開(kāi)發(fā)放在學(xué)習(xí)的重點(diǎn)上舆床。接下來(lái)就要寫(xiě)Controller的代碼了,然而寫(xiě)Controller的過(guò)程中會(huì)學(xué)到很多注解開(kāi)發(fā)的基礎(chǔ)知識(shí)嫁佳。
2.4Controller的編寫(xiě)之@RequestMapping的特性學(xué)習(xí)
2.4.1窄化請(qǐng)求映射
我們除了在Controller方法的上面加上一個(gè)@RequestMapping的注解指定url外(完成url映射)挨队,還可以在Controller類的上面指定一個(gè)@RequestMapping注解指定訪問(wèn)路徑的根url,如這里我們是對(duì)商品的操作脱拼,所以可以在Controller類上面加上一個(gè)@RequestMapping的注解指定訪問(wèn)商品信息的根路徑(叫“窄化請(qǐng)求映射”):
@Controller
//定義url的根路徑瞒瘸,訪問(wèn)時(shí)根路徑+方法名的url
@RequestMapping("/items")
public class ItemsController {
}
使用窄化請(qǐng)求映射的好處:更新規(guī)范系統(tǒng)的url,避免url沖突熄浓。
然后繼續(xù)我們的Controller開(kāi)發(fā)情臭,添加方法:
@RequestMapping(value = "/editItems",method = RequestMethod.GET)
public ModelAndView editItems() throws Exception
{
ModelAndView modelAndView=new ModelAndView();
//調(diào)用service查詢商品的信息
ItemsCustom itemsCustom=itemsService.findItemsById(1);
//將模型數(shù)據(jù)傳到j(luò)sp
modelAndView.addObject("item",itemsCustom);
//指定邏輯視圖名
modelAndView.setViewName("editItem");
return modelAndView;
}
編寫(xiě)editItem.jsp頁(yè)面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>修改商品信息</title>
</head>
<body>
<form id="itemForm" action="${pageContext.request.contextPath }/items/editItemSubmit.action" method="post" >
<input type="hidden" name="id" value="${id }"/>
修改商品信息:
<table width="100%" border=1>
<tr>
<td>商品名稱</td>
<td><input type="text" name="name" value="${itemsCustom.name }"/></td>
</tr>
<tr>
<td>商品價(jià)格</td>
<td><input type="text" name="price" value="${itemsCustom.price }"/></td>
</tr>
<tr>
<td>商品簡(jiǎn)介</td>
<td>
<textarea rows="3" cols="30" name="detail">${itemsCustom.detail }</textarea>
</td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="提交"/>
</td>
</tr>
</table>
</form>
</body>
</html>
然后運(yùn)行服務(wù)器省撑,此時(shí)應(yīng)該輸入網(wǎng)址http://localhost:8080/SpringMvcMybatis/items/queryItems.action
而不是http://localhost:8080/SpringMvcMybatis/queryItems.action
,然后點(diǎn)擊右邊的修改鏈接便可以進(jìn)去相應(yīng)的修改頁(yè)面:
2.4.2限制http請(qǐng)求的方法
不知道你發(fā)現(xiàn)沒(méi)有,我們?cè)贑ontroller的editItems()方法上的注解中加入的是value = "/editItems",method = RequestMethod.GET
參數(shù)而不再是單單的"/editItems"
參數(shù)了俯在,這里我們便用到了使用@RequestMapping注解限制http請(qǐng)求的方法竟秫。如果你將這里的method = RequestMethod.GET
改為method = RequestMethod.POST
,然后在頁(yè)面中再點(diǎn)擊修改鏈接時(shí)就會(huì)報(bào)錯(cuò)跷乐。
另外method屬性的屬性值為數(shù)組肥败,我們也可以將注解中的參數(shù)改為ethod = {RequestMethod.GET,RequestMethod.POST}
表示請(qǐng)求既可以為POST請(qǐng)求又可以為GET請(qǐng)求。
2.5Controller的編寫(xiě)之Controller方法返回值學(xué)習(xí)
2.5.1返回ModerAndView
目前我們使用的方式都是返回的ModerAndView對(duì)象愕提,例如我們已經(jīng)編寫(xiě)的Controller中的queryItems()方法和editItems()方法馒稍。接下來(lái)我們看看返回字符串的方法編寫(xiě)。
2.5.2返回字符串
首先注釋掉我們返回值為ModerAndView類型的editItems()方法浅侨。如果controller方法返回jsp頁(yè)面纽谒,可以簡(jiǎn)單將方法返回值類型定義 為字符串,最終返回邏輯視圖名如输。編寫(xiě)返回值為String類型的editItems()方法鼓黔,代碼如下:
//方法返回字符串,字符串就是邏輯視圖名不见,Model作用是將數(shù)據(jù)填充到request域澳化,在頁(yè)面顯示
@RequestMapping(value = "/editItems",method = RequestMethod.GET)
public String editItems(Model model) throws Exception
{
//調(diào)用service查詢商品的信息
ItemsCustom itemsCustom=itemsService.findItemsById(1);
model.addAttribute("itemsCustom",itemsCustom);
return "editItem";
}
方法中我們需要傳入一個(gè)Model對(duì)象,作用是將數(shù)據(jù)填充到request域稳吮,在頁(yè)面顯示缎谷。然后運(yùn)行服務(wù)器,輸入http://localhost:8080/SpringMvcMybatis/items/queryItems.action
照常正確訪問(wèn)該網(wǎng)站盖高。再來(lái)介紹返回值為void的方法慎陵。
2.5.3返回void
同樣注釋掉返回值為String類型的editItems()方法,然后加入返回值為void的editItems()方法:
@RequestMapping(value = "/editItems",method = RequestMethod.GET)
public void editItems(HttpServletRequest request, HttpServletResponse response) throws Exception
{
//調(diào)用service查詢商品的信息
ItemsCustom itemsCustom=itemsService.findItemsById(id);
request.setAttribute("item",itemsCustom);
//注意如果使用request轉(zhuǎn)向頁(yè)面喻奥,這里需要指定頁(yè)面的完整路徑
request.getRequestDispatcher("/WEB-INF/jsp/editItem.jsp").forward(request,response);
}
其實(shí)這里就是運(yùn)用的原生態(tài)的Servlet的開(kāi)發(fā)方式席纽,運(yùn)行服務(wù)器,輸入http://localhost:8080/SpringMvcMybatis/items/queryItems.action
仍照常正確訪問(wèn)該網(wǎng)站撞蚕。
通過(guò)這種返回值為void的方法我們?nèi)菀纵敵鰆son润梯、xml格式的數(shù)據(jù),即通過(guò)response指定響應(yīng)結(jié)果甥厦,例如響應(yīng)json數(shù)據(jù)如下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
上面我們就通過(guò)完成商品信息的編輯功能介紹了Controller中三種返回值類型的方法纺铭。而通過(guò)返回字符串的方法,有時(shí)候會(huì)返回一些特殊的字符串(例如返回return "forward:url路徑"
或return "redirect:url路徑"
)刀疙。分別代表請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求沖定向舶赔,下面我們通過(guò)完善編輯商品信息后進(jìn)行提交的功能來(lái)講解這兩種返回特殊字符串類型的方法。在Controller中添加editItemSubmit()方法:
//商品提交頁(yè)面
//itemsQueryVo是包裝類型的pojo
@RequestMapping("/editItemSubmit")
public String editItemSubmit() throws Exception
{
//請(qǐng)求轉(zhuǎn)發(fā),使用forward進(jìn)行請(qǐng)求轉(zhuǎn)發(fā)谦秧,request數(shù)據(jù)可以共享竟纳,url地址欄不會(huì)
// return "forward:queryItems.action";
//使用redirect進(jìn)行重定向撵溃,request數(shù)據(jù)無(wú)法共享,url地址欄會(huì)發(fā)生變化的锥累。由于我們重定向的頁(yè)面queryItems.action與本頁(yè)面editItemSubmit.action在同一根目錄下缘挑,所以不需要加入根路徑
return "redirect:queryItems.action";
}
運(yùn)行服務(wù)器,然后我們便可以在editItems.jsp頁(yè)面通過(guò)點(diǎn)擊"提交"按鈕請(qǐng)求轉(zhuǎn)發(fā)或者請(qǐng)求重定向到我們的queryItems.action
頁(yè)面桶略。如上语淘,我便介紹完Contoller方法返回值的知識(shí)。接下來(lái)介紹Controller方法中的參數(shù)與頁(yè)面參數(shù)綁定的知識(shí)际歼。
2.6Controller的編寫(xiě)之方法參數(shù)與頁(yè)面參數(shù)的綁定
不知你注意到?jīng)]有惶翻,在Controller的方法中我們傳入的參數(shù)都是我們自己根據(jù)需求手動(dòng)傳入的參數(shù),而真正的需求中我們是需要將頁(yè)面中的參數(shù)傳遞到Controller的方法中的鹅心,那如何將頁(yè)面的參數(shù)綁定到Controller的方法中呢维贺?看下方參數(shù)綁定的過(guò)程圖解:
首先我們看看Controller的方法中默認(rèn)支持的形參(即之前我們根據(jù)需求手動(dòng)傳入的參數(shù),這些參數(shù)處理適配器會(huì)默認(rèn)識(shí)別并進(jìn)行賦值)有:1.HttpServletRequest:通過(guò)request對(duì)象獲取請(qǐng)求信息巴帮。 2.HttpServletResponse:通過(guò)response處理響應(yīng)信息。3.HttpSession:通過(guò)session對(duì)象得到session中存放的對(duì)象虐秋。4.Model/modelmap/map:通過(guò)model向頁(yè)面?zhèn)鬟f數(shù)據(jù)榕茧,頁(yè)面通過(guò)${item.XXXX}獲取item對(duì)象的屬性值,如下:
//調(diào)用service查詢商品信息
Items item = itemService.findItemById(id);
model.addAttribute("item", item);
但是值得我們關(guān)心的不是這些默認(rèn)的參數(shù),而是我們自定義參數(shù)傳入Controller方法的形參中客给,繼續(xù)往下面看用押。
2.6.1@RequestParam
如果request請(qǐng)求的參數(shù)名和controller方法的形參數(shù)名稱一致,適配器自動(dòng)進(jìn)行參數(shù)綁定靶剑。如果不一致可以通過(guò)
@RequestParam 指定request請(qǐng)求的參數(shù)名綁定到哪個(gè)方法形參上蜻拨。
對(duì)于必須要傳的參數(shù),通過(guò)@RequestParam中屬性required設(shè)置為true桩引,如果不傳此參數(shù)則報(bào)錯(cuò)缎讼。
對(duì)于有些參數(shù)如果不傳入,還需要設(shè)置默認(rèn)值坑匠,使用@RequestParam中屬性defaultvalue設(shè)置默認(rèn)值血崭。
例如Controller中的方法:
@RequestMapping(value = "/editItems",method = RequestMethod.GET)
public void editItems(HttpServletRequest request, HttpServletResponse response,@RequestParam(value = "item_id",required = false,defaultValue = "1") Integer id) throws Exception
{
//調(diào)用service查詢商品的信息
ItemsCustom itemsCustom=itemsService.findItemsById(id);
request.setAttribute("item",itemsCustom);
//zhuyi如果使用request轉(zhuǎn)向頁(yè)面,這里需要指定頁(yè)面的完整路徑
request.getRequestDispatcher("/WEB-INF/jsp/editItem.jsp").forward(request,response);
}
沒(méi)對(duì)形參id加上@RequestParam注解時(shí)厘灼,當(dāng)我們從頁(yè)面進(jìn)入到editItems.action時(shí)夹纫,只有從頁(yè)面?zhèn)魅氲膮?shù)名為id時(shí)該id參數(shù)值才會(huì)傳到editItems()方法的id參數(shù)值上,如果從頁(yè)面?zhèn)魅氲膮?shù)明不為id而為其他參數(shù)名時(shí)例如http://localhost:8080/SpringMvcMybatis/items/editItems.action?item_id=1
设凹,此時(shí)通過(guò)調(diào)試會(huì)發(fā)現(xiàn)editItems()方法中的id屬性值為null;而當(dāng)我們?yōu)樾螀d加上了@RequestParam注解并指定了其屬性value = "item_id"
后舰讹,若從頁(yè)面?zhèn)魅氲膮?shù)名為item_id,則該參數(shù)值會(huì)因?yàn)樘砑恿?code>value = "item_id"該屬性而被賦值給id屬性闪朱。required
屬性若設(shè)置為true月匣,則如果從頁(yè)面進(jìn)入到editItem.action時(shí)沒(méi)有傳入此參數(shù)則會(huì)報(bào)錯(cuò)钻洒。defaultvalue
屬性值表示為該參數(shù)賦默認(rèn)值。
2.6.2綁定簡(jiǎn)單類型
上述那個(gè)editItem()方法是原始的servlet開(kāi)發(fā)方法桶错,接下來(lái)我們用返回值為String 類型的方法進(jìn)行注解開(kāi)發(fā)的基礎(chǔ)知識(shí)講解航唆。
可以綁定整型、字符串院刁、單精/雙精度糯钙、日期、布爾型退腥,很簡(jiǎn)單處理任岸,我不進(jìn)行講解,通過(guò)下面綁定pojo類型你就會(huì)清楚了狡刘。
2.6.3綁定pojo類型
綁定pojo類型又可以分為綁定簡(jiǎn)單pojo類型和綁定包裝pojo類型享潜。
2.6.3.1綁定簡(jiǎn)單pojo類型
簡(jiǎn)單pojo類型只包括簡(jiǎn)單類型的屬性。綁定過(guò)程:request請(qǐng)求的參數(shù)名稱和pojo的屬性名一致嗅蔬,就可以綁定成功剑按。
修改Controller中的editItemSubmit()方法:
//商品提交頁(yè)面
//itemsQueryVo是包裝類型的pojo
@RequestMapping("/editItemSubmit")
public String editItemSubmit(Integer id,ItemsCustom itemsCustom) throws Exception
{
itemsService.updateItems(id,itemsCustom);
//請(qǐng)求轉(zhuǎn)發(fā)
// return "forward:queryItems.action";
//重定向
return "redirect:queryItems.action";
}
點(diǎn)擊提交按鈕,從editItem.jsp頁(yè)面進(jìn)入editItemSubmit.action時(shí)澜术,就會(huì)將編輯頁(yè)面的參數(shù)都映射到該方法的id形參和ItemsCustom對(duì)象中艺蝴,此時(shí)我們修改商品的信息,然后點(diǎn)擊提交按鈕鸟废,服務(wù)器反應(yīng)過(guò)程如下:點(diǎn)擊提交按鈕猜敢,頁(yè)面從editItem.jsp進(jìn)入到editItemSubmit.action并將修改后的商品信息提交到數(shù)據(jù)庫(kù)并將這些參數(shù)傳入到ItemsCustom對(duì)象的屬性中,然后重定向到queryItems.action進(jìn)行商品的列表信息展示盒延。
問(wèn)題:如果controller方法形參中有多個(gè)pojo且pojo中有重復(fù)的屬性缩擂,使用簡(jiǎn)單pojo綁定無(wú)法有針對(duì)性的綁定,比如:方法形參有items和User添寺,pojo同時(shí)存在name屬性胯盯,從http請(qǐng)求過(guò)程的name無(wú)法有針對(duì)性的綁定到items或user。要解決此種方法我們就需要用到下面的綁定包裝的pojo類型畦贸。
2.6.3.2綁定包裝的pojo類型
這里我們復(fù)制editItem.jsp頁(yè)面粘貼出一個(gè)editItem2.jsp頁(yè)面陨闹,染護(hù)修改editItem2.jsp中的參數(shù)名為itemsCustom.name、itemsCustom.price薄坏、itemsCustom.detail趋厉,修改Controller中的editItemSubmit方法中的形參為public String editItemSubmit(Integer id,ItemsCustom itemsCustom,ItemsQueryVo itemsQueryVo) throws Exception{...}
修改editItems的返回值類型為editItems2
。運(yùn)行程序胶坠,點(diǎn)擊提交按鈕君账,頁(yè)面信息成功傳入到itemsQueryVo的屬性中。成功運(yùn)行后我們還是將信息改回成原來(lái)的模樣沈善,方便后面的測(cè)試乡数。
2.6.4使用屬性編輯器完成自定義綁定
此時(shí)我們?cè)趀ditItem.jsp中添加上日期的信息展示:
<tr>
<td>商品生產(chǎn)日期</td>
<td><input type="text" name="createtime" value="<fmt:formatDate value="${itemsCustom.createtime}" pattern="yyyy-MM-dd HH-mm-ss"/>"/></td>
</tr>
然后運(yùn)行程序椭蹄,當(dāng)點(diǎn)擊提交按鈕時(shí)會(huì)報(bào)錯(cuò),你知道為什么嗎净赴?原因是因?yàn)橥ㄟ^(guò)點(diǎn)擊提交按鈕绳矩,頁(yè)面中參數(shù)名為"createtime"的參數(shù)名由于跟Controller方法中的形參ItemsCustom有相同的屬性名createtime,所以此時(shí)頁(yè)面中的日期會(huì)映射到ItemsCustom的Date屬性中,但是從頁(yè)面?zhèn)鬟^(guò)來(lái)的日期是字符串類型玖翅,而ItemsCustom的屬性是java.util.Date類型翼馆,所以當(dāng)然會(huì)報(bào)錯(cuò)。這樣的話金度,我們就必須完成日期字符串向java類型日期的轉(zhuǎn)換应媚。此時(shí)我們就需要自定義日期類型的綁定,即使用屬性編輯器來(lái)完成自定義的綁定猜极。有如下兩種方法:1.使用WebDataBinder(了解)中姜,在Controller中添加如下代碼:
//自定義屬性編輯器
@InitBinder
public void initBinder(WebDataBinder binder) throws Exception{
//Date.class必須是與controller方法形參pojo屬性一致的date類型,這里是java.util.Date
binder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"),true));
}
運(yùn)行程序跟伏,點(diǎn)擊提交按鈕后不會(huì)再出現(xiàn)報(bào)錯(cuò)信息丢胚,且editItem.jsp頁(yè)面的createtime參數(shù)也成功傳入到了ItemsCustom的createtime屬性中。使用這種方法的問(wèn)題是無(wú)法在多個(gè)controller共用受扳。那我們就來(lái)介紹第二種方法:使用WebBindingInitializer(了解)嗜桌。首先我們需要編寫(xiě)一個(gè)自定義屬性編輯器CustomPropertyEditor.java,代碼如下:
public class CustomPropertyEditor implements PropertyEditorRegistrar
{
@Override
public void registerCustomEditors(PropertyEditorRegistry binder) {
binder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"),true));
}
}
然后要在springmvc.xml文件中加入對(duì)它的配置:
<!-- 注冊(cè)屬性編輯器 -->
<bean id="customPropertyEditor" class="controller.propertyeditor.CustomPropertyEditor"></bean>
<!-- 自定義webBinder -->
<bean id="customBinder"
class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="propertyEditorRegistrars">
<list>
<ref bean="customPropertyEditor"/>
</list>
</property>
</bean>
然后要在注解適配器的配置標(biāo)簽中加入如下屬性:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer" ref="customBinder"></property>
</bean>
這樣我們便可以注釋掉第一種屬性編輯器的代碼了辞色,使用第二種方式雖然配置很繁瑣,但是很適用浮定。運(yùn)行程序相满,也成功將editItem.jsp頁(yè)面的createtime參數(shù)映射到ItemsCustom的createtime屬性中。下面我再講一種自定義綁定參數(shù)的方法桦卒。
2.6.5使用轉(zhuǎn)換器完成自定義參數(shù)綁定(想往架構(gòu)師方向發(fā)展的要掌握這種方法)
首先要定義一個(gè)轉(zhuǎn)換器CustomDateConverter.java完成日期的轉(zhuǎn)換立美,代碼如下:
public class CustomDateConverter implements Converter<String,Date> {
@Override
public Date convert(String source) {
try{
return new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").parse(source);
}catch (Exception e)
{
e.printStackTrace();
}
return null;
}
}
在定義一個(gè)StringTrimConverter.java用于去除日期字符串兩邊的空格,代碼如下:
public class StringTrimConverter implements Converter<String,String> {
@Override
public String convert(String source) {
try{
//去掉字符串兩邊的空格,如果去除后為空則返回null
if (source!=null)
{
source=source.trim();
if (source.equals(""))
return null;
}
}catch (Exception e)
{
e.printStackTrace();
}
return source;
}
}
定義好后就需要對(duì)轉(zhuǎn)換器進(jìn)行配置:思路就是先定義一個(gè)轉(zhuǎn)換器然后注入到適配器中情萤。而對(duì)于轉(zhuǎn)換器在springmvc.xml中的配置有兩種方式达传,第一種方式針對(duì)不使用<mvc:annotation-driven>
,第二種方式針對(duì)使用<mvc:annotation-driven>
,我們就來(lái)講講第二種方式棍潘。在springmvc.xml中添加如下配置:
<!--mvc的注解驅(qū)動(dòng)器,通過(guò)它可以替代下邊的處理器映射器和適配器-->
<mvc:annotation-driven conversion-service="conversionService">
</mvc:annotation-driven>
<!--轉(zhuǎn)換器-->
<!-- conversionService -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 轉(zhuǎn)換器 -->
<property name="converters">
<list>
<bean class="controller.converter.CustomDateConverter"/>
<bean class="controller.converter.StringTrimConverter"/>
</list>
</property>
</bean>
使用了注解驅(qū)動(dòng)的配置后洞慎,我們就可以注釋掉處理器映射器與處理器適配器了。運(yùn)行程序嘿棘,也成功將editItem.jsp頁(yè)面的createtime參數(shù)映射到ItemsCustom的createtime屬性中劲腿。
由于往后我們還要進(jìn)行json數(shù)據(jù)的開(kāi)發(fā),所以這里我們還是不采用使用注解驅(qū)動(dòng)的方式鸟妙,還是采用注解映射器與注解適配器的方式進(jìn)行開(kāi)發(fā)焦人。為了方便后面對(duì)高級(jí)注解知識(shí)的講解挥吵,我們這里采用的自定義綁定參數(shù)的方式是通過(guò)webBindingInitializer和convertor結(jié)合的方式,修改后的最后的springmvc.xml配置信息如下:
<!--使用spring組件掃描
一次性配置此包下所有的Handler-->
<context:component-scan base-package="controller"/>
<!--mvc的注解驅(qū)動(dòng)器花椭,通過(guò)它可以替代下邊的處理器映射器和適配器-->
<!--<mvc:annotation-driven></mvc:annotation-driven>-->
<!--注解處理器映射器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--注解的適配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer" ref="customBinder"></property>
</bean>
<!--配置視圖解析器
要求將jstl的包加到classpath-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 自定義webBinder -->
<bean id="customBinder"
class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService"/>
<!--早期的自定義屬性編輯器-->
<!--<property name="propertyEditorRegistrars">-->
<!--<list>-->
<!--<ref bean="customPropertyEditor"/>-->
<!--</list>-->
<!--</property>-->
</bean>
<!-- 注冊(cè)屬性編輯器 -->
<bean id="customPropertyEditor" class="controller.propertyeditor.CustomPropertyEditor"></bean>
<!--mvc的注解驅(qū)動(dòng)器忽匈,通過(guò)它可以替代下邊的處理器映射器和適配器-->
<!--<mvc:annotation-driven conversion-service="conversionService">-->
<!--</mvc:annotation-driven>-->
<!--轉(zhuǎn)換器-->
<!-- conversionService -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 轉(zhuǎn)換器 -->
<property name="converters">
<list>
<bean class="controller.converter.CustomDateConverter"/>
<bean class="controller.converter.StringTrimConverter"/>
</list>
</property>
</bean>
這個(gè)converter的配置是一勞永逸的配置,也就是系統(tǒng)架構(gòu)級(jí)別的配置矿辽,希望你能成功掌握丹允。
好了,通過(guò)上述的案例嗦锐,便成功的使用了SSM框架實(shí)現(xiàn)了商品信息的三個(gè)功能嫌松。希望通過(guò)這個(gè)案例,你能成功掌握SSM框架進(jìn)行簡(jiǎn)單的注解開(kāi)發(fā)奕污,而我接下來(lái)要為你們講解SSM開(kāi)發(fā)中的高級(jí)注解開(kāi)發(fā)知識(shí),還是借用這個(gè)工程進(jìn)行開(kāi)發(fā)萎羔。
3.聯(lián)系
If you have some questions after you see this article,you can tell your doubts in the comments area or you can find some info by clicking these links.