一個(gè)案例帶你快速入門(mén)SSM開(kāi)發(fā)

經(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.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市碳默,隨后出現(xiàn)的幾起案子贾陷,更是在濱河造成了極大的恐慌,老刑警劉巖嘱根,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件髓废,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡该抒,警方通過(guò)查閱死者的電腦和手機(jī)慌洪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)凑保,“玉大人冈爹,你說(shuō)我怎么就攤上這事∨芬” “怎么了频伤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)芝此。 經(jīng)常有香客問(wèn)我憋肖,道長(zhǎng),這世上最難降的妖魔是什么婚苹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任岸更,我火速辦了婚禮,結(jié)果婚禮上膊升,老公的妹妹穿的比我還像新娘坐慰。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布结胀。 她就那樣靜靜地躺著赞咙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪糟港。 梳的紋絲不亂的頭發(fā)上攀操,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音秸抚,去河邊找鬼速和。 笑死,一個(gè)胖子當(dāng)著我的面吹牛剥汤,可吹牛的內(nèi)容都是我干的颠放。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼吭敢,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼碰凶!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起鹿驼,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤欲低,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后畜晰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體砾莱,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年凄鼻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了腊瑟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡块蚌,死狀恐怖扫步,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情匈子,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布闯袒,位于F島的核電站虎敦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏政敢。R本人自食惡果不足惜其徙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望喷户。 院中可真熱鬧唾那,春花似錦、人聲如沸褪尝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至避诽,卻和暖如春龟虎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沙庐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工鲤妥, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拱雏。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓棉安,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親铸抑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贡耽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)羡滑,斷路器菇爪,智...
    卡卡羅2017閱讀 134,656評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,810評(píng)論 6 342
  • 1.Spring web mvc介紹 Spring web mvc和Struts2都屬于表現(xiàn)層的框架,它是Spri...
    七弦桐語(yǔ)閱讀 11,516評(píng)論 2 38
  • 【握金釵*陌路牽魂】 細(xì)雨探春深, 柔風(fēng)問(wèn)滋味柒昏。 柳絲搖曳如醉凳宙。 桃李芬芳盡嬌媚。 山返綠职祷,水回溫氏涩, 人已累。 音...
    龍之風(fēng)閱讀 386評(píng)論 20 8
  • 在身邊太多對(duì)這個(gè)世界充滿了不滿,而感到痛苦的人了泥耀。先說(shuō)說(shuō)我自己饺汹,我曾經(jīng)對(duì)這個(gè)世界不止一點(diǎn)點(diǎn)怨恨,每天都埋怨世...
    木土肉肉閱讀 774評(píng)論 3 1