一個案例帶你快速入門SSM開發

經過上篇文章Spring、Spring MVC與Mybatis整合工程搭建我們便將SSM的環境搭建了,接下來我們便利用這個工程來開發項目帶你快速學會使用SSM整合框架進行開發。我們同樣采用的是注解處理器映射器與注解處理器適配器進行開發。

寫在前面的話:源代碼請點擊這里前往我的github

你也可以前往我的個人博客查看更多有用的文章:http://codingxiaxw.cn

1.實現商品的列表展示

1.1提出需求

功能描述:在頁面中展示商品列表。

1.2編寫表

sql語句見github中.sql文件。

1.3持久層mapper的編寫

編寫好數據庫后我們便可以通過MyBatis逆向工程快速生成對單表映射的sql,包括mapper.java、mapper.xml和pojo類。

根據逆向工程生成的這三個文件與單表都是一對一的關系,例如通過Items表會生成ItemsMapper.java、ItemsMapper.xml和Items.java的pojo類,這里我們為了便于需求的擴展,所以另外自己編寫一個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;
    }   
}

然后自己編寫一個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片段
    建議是以單表為單位定義查詢條件
    建議將常用的查詢條件都寫出來
     -->
    <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的配置我們已經在springmvc.xml中通過spring組件掃描器


    <!--
    MapperScannerConfigurer:mapper的掃描器,將包下邊的mapper接口自動創建代理對象,
    自動創建到spring容器中,bean的id是mapper的類名(首字母小寫)
     -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 配置掃描包的路徑
        如果要掃描多個包,中間使用半角逗號分隔
        要求mapper.xml和mapper.java同名且在同一個目錄
         -->
        <property name="basePackage" value="mapper"/>
        <!-- 使用sqlSessionFactoryBeanName -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

進行了統一的配置。

接口里面調用xml文件中查詢表中所有商品列表信息的sql語句,然后我們便可以進行業務邏輯層的代碼編寫.

1.4業務邏輯層service的編寫

首先我們在service包下創建一個商品的service接口ItemsService.java文件,里面編寫的方法和ItemsCustomMapper.java中的方法對應以實現商品列表的查詢:

public interface ItemsService {

    //商品的查詢列表
    public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo)
            throws Exception;
}

然后編寫其實現類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);
    }
}

代碼中通過Spring框架的DI注入依賴對象mapper即itemsMapperCustom對象,然后調用itemsMapperCustom的findItemsList方法實現商品列表查詢,然后在spring配置文件applicationContext-service.xml中要進行service的配置,添加如下標簽:

<!--商品配置的service-->
    <bean id="itemsService" class="service.impl.ItemsServiceImpl"/>

便可。接下來便應該完成控制層Controller.java的代碼編寫了。

1.5控制層Controller的編寫

在controller包下創建一個ItemsController.java,里面編寫代碼:

@Controller
public class ItemsController {

    //注入service
    @Autowired
    private ItemsService itemsService;

    @RequestMapping("/queryItems")
    public ModelAndView queryItems() throws Exception {
        //調用servie來查詢商品列表
        List<ItemsCustom> itemsList=itemsService.findItemsList(null);

        ModelAndView modelAndView=new ModelAndView();
        modelAndView.addObject("itemsList",itemsList);
        //指定邏輯視圖名itemsList
        modelAndView.setViewName("itemsList");

        return modelAndView;
    }
}

通過@Autowired注解完成service的依賴注入,通過@Controller注解將Controller自動添加到spring容器IOC中,通過@RequestMapping("/queryItems")注解指明訪問該Controller的url。

至于itemsList.jsp的頁面編寫代碼如下:

<%@ 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>商品價格</td>
    <td>生產日期</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>

然后我們運行服務器,輸入網址http://localhost:8080/SpringMvcMybatis/queryItems.action,發現無法看到頁面,這是因為我們的spring配置文件沒有得到加載,需要在web.xml文件中加入如下內容進行spring容器的配置:

    <!--配置spring容器監聽器-->
    <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>

然后重新運行服務器并輸入網址,看到如下頁面,說明成功使用SSM框架完成開發顯示商品列表的項目:


到此,我們便通過SSM的整合工程項目,完成了對商品列表的查詢。接下來我們再實現對商品的另一個功能:修改商品信息。

2.實現商品信息的修改

2.1需求

功能描述:商品信息修改。操作流程:1.在商品列表頁面點擊修改連接。2.打開商品修改頁面,顯示了當前商品的信息(根據商品id查詢商品信息)。3.修改商品信息,點擊提交(更新商品信息)。

通過此案例,我們也會穿插用SSM進行注解開發的基礎知識如: @RequestMapping注解的改善、controller方法返回值、Controller方法中的參數與頁面參數的綁定。

2.2mapper的編寫

此功能涉及到的mapper為ItemsMapper.java與ItemsMapper.xml,已使用逆向工程為我們生成。

2.3service的編寫

在ItemsService接口中添加方法:

   //根據商品id查詢商品信息
    public ItemsCustom findItemsById(int id) throws Exception;
    
      //更新商品信息
    /**
     * 定義service接口,遵循單一職責,將業務參數細化(不要使用包裝類型,比如map)
     * @param id 修改商品的id
     * @param itemsCustom 修改商品的信息
     * @throws Exception
     */
    public void updateItems(Integer id,ItemsCustom itemsCustom) throws Exception;

然后是實現類ItemsServiceImpl.java:

 
    //注入依賴對象itemsMapper
     @Autowired
    private ItemsMapper itemsMapper;

    @Override
    public ItemsCustom findItemsById(int id) throws Exception {

        Items items=itemsMapper.selectByPrimaryKey(id);

        //在這里以后隨著需求的變化,需要查詢商品的其它相關信息,返回到controller
        //所以這個時候用到擴展類更好,如下
        ItemsCustom itemsCustom=new ItemsCustom();
        //將items的屬性拷貝到itemsCustom
        BeanUtils.copyProperties(items,itemsCustom);

        return itemsCustom;
    }

    @Override
    public void updateItems(Integer id,ItemsCustom itemsCustom) throws Exception {

        //在service中一定要寫業務代碼




        //對于關鍵業務數據的非空校驗
        if (id==null)
        {
            //拋出異常,提示調用接口的用戶,id不能唯恐
            //...
        }

        itemsMapper.updateByPrimaryKeyWithBLOBs(itemsCustom);
    }

說一句:對service的開發是整個系統中開發最重要的部分,所以你要把service的開發放在學習的重點上。接下來就要寫Controller的代碼了,然而寫Controller的過程中會學到很多注解開發的基礎知識。

2.4Controller的編寫之@RequestMapping的特性學習

2.4.1窄化請求映射

我們除了在Controller方法的上面加上一個@RequestMapping的注解指定url外(完成url映射),還可以在Controller類的上面指定一個@RequestMapping注解指定訪問路徑的根url,如這里我們是對商品的操作,所以可以在Controller類上面加上一個@RequestMapping的注解指定訪問商品信息的根路徑(叫“窄化請求映射”):

@Controller
//定義url的根路徑,訪問時根路徑+方法名的url
@RequestMapping("/items")
public class ItemsController {
}

使用窄化請求映射的好處:更新規范系統的url,避免url沖突。

然后繼續我們的Controller開發,添加方法:

    @RequestMapping(value = "/editItems",method = RequestMethod.GET)
    public ModelAndView editItems() throws Exception
    {
        ModelAndView modelAndView=new ModelAndView();

        //調用service查詢商品的信息
        ItemsCustom itemsCustom=itemsService.findItemsById(1);
        //將模型數據傳到jsp
        modelAndView.addObject("item",itemsCustom);
        //指定邏輯視圖名
        modelAndView.setViewName("editItem");

        return modelAndView;
    }

編寫editItem.jsp頁面:

<%@ 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>商品價格</td>
    <td><input type="text" name="price" value="${itemsCustom.price }"/></td>
</tr>
<tr>
    <td>商品簡介</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>

然后運行服務器,此時應該輸入網址http://localhost:8080/SpringMvcMybatis/items/queryItems.action而不是http://localhost:8080/SpringMvcMybatis/queryItems.action,然后點擊右邊的修改鏈接便可以進去相應的修改頁面:

2.4.2限制http請求的方法

不知道你發現沒有,我們在Controller的editItems()方法上的注解中加入的是value = "/editItems",method = RequestMethod.GET參數而不再是單單的"/editItems"參數了,這里我們便用到了使用@RequestMapping注解限制http請求的方法。如果你將這里的method = RequestMethod.GET改為method = RequestMethod.POST,然后在頁面中再點擊修改鏈接時就會報錯。

另外method屬性的屬性值為數組,我們也可以將注解中的參數改為ethod = {RequestMethod.GET,RequestMethod.POST}表示請求既可以為POST請求又可以為GET請求。

2.5Controller的編寫之Controller方法返回值學習

2.5.1返回ModerAndView

目前我們使用的方式都是返回的ModerAndView對象,例如我們已經編寫的Controller中的queryItems()方法和editItems()方法。接下來我們看看返回字符串的方法編寫。

2.5.2返回字符串

首先注釋掉我們返回值為ModerAndView類型的editItems()方法。如果controller方法返回jsp頁面,可以簡單將方法返回值類型定義 為字符串,最終返回邏輯視圖名。編寫返回值為String類型的editItems()方法,代碼如下:

    //方法返回字符串,字符串就是邏輯視圖名,Model作用是將數據填充到request域,在頁面顯示
    @RequestMapping(value = "/editItems",method = RequestMethod.GET)
    public String editItems(Model model) throws Exception
    {

    
        //調用service查詢商品的信息
        ItemsCustom itemsCustom=itemsService.findItemsById(1);

        model.addAttribute("itemsCustom",itemsCustom);

        return "editItem";
    }

方法中我們需要傳入一個Model對象,作用是將數據填充到request域,在頁面顯示。然后運行服務器,輸入http://localhost:8080/SpringMvcMybatis/items/queryItems.action照常正確訪問該網站。再來介紹返回值為void的方法。

2.5.3返回void

同樣注釋掉返回值為String類型的editItems()方法,然后加入返回值為void的editItems()方法:

    @RequestMapping(value = "/editItems",method = RequestMethod.GET)
    public void editItems(HttpServletRequest request, HttpServletResponse response) throws Exception
    {

        //調用service查詢商品的信息
        ItemsCustom itemsCustom=itemsService.findItemsById(id);

        request.setAttribute("item",itemsCustom);

        //注意如果使用request轉向頁面,這里需要指定頁面的完整路徑
        request.getRequestDispatcher("/WEB-INF/jsp/editItem.jsp").forward(request,response);
    }

其實這里就是運用的原生態的Servlet的開發方式,運行服務器,輸入http://localhost:8080/SpringMvcMybatis/items/queryItems.action仍照常正確訪問該網站。

通過這種返回值為void的方法我們容易輸出json、xml格式的數據,即通過response指定響應結果,例如響應json數據如下:

response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");

上面我們就通過完成商品信息的編輯功能介紹了Controller中三種返回值類型的方法。而通過返回字符串的方法,有時候會返回一些特殊的字符串(例如返回return "forward:url路徑"return "redirect:url路徑")。分別代表請求轉發和請求沖定向,下面我們通過完善編輯商品信息后進行提交的功能來講解這兩種返回特殊字符串類型的方法。在Controller中添加editItemSubmit()方法:

 //商品提交頁面
    //itemsQueryVo是包裝類型的pojo
    @RequestMapping("/editItemSubmit")
    public String editItemSubmit() throws Exception
    {
        //請求轉發,使用forward進行請求轉發,request數據可以共享,url地址欄不會
//        return "forward:queryItems.action";

        //使用redirect進行重定向,request數據無法共享,url地址欄會發生變化的。由于我們重定向的頁面queryItems.action與本頁面editItemSubmit.action在同一根目錄下,所以不需要加入根路徑
       return "redirect:queryItems.action";
    }

運行服務器,然后我們便可以在editItems.jsp頁面通過點擊"提交"按鈕請求轉發或者請求重定向到我們的queryItems.action頁面。如上,我便介紹完Contoller方法返回值的知識。接下來介紹Controller方法中的參數與頁面參數綁定的知識。

2.6Controller的編寫之方法參數與頁面參數的綁定

不知你注意到沒有,在Controller的方法中我們傳入的參數都是我們自己根據需求手動傳入的參數,而真正的需求中我們是需要將頁面中的參數傳遞到Controller的方法中的,那如何將頁面的參數綁定到Controller的方法中呢?看下方參數綁定的過程圖解:

首先我們看看Controller的方法中默認支持的形參(即之前我們根據需求手動傳入的參數,這些參數處理適配器會默認識別并進行賦值)有:1.HttpServletRequest:通過request對象獲取請求信息。 2.HttpServletResponse:通過response處理響應信息。3.HttpSession:通過session對象得到session中存放的對象。4.Model/modelmap/map:通過model向頁面傳遞數據,頁面通過${item.XXXX}獲取item對象的屬性值,如下:

//調用service查詢商品信息
Items item = itemService.findItemById(id);
model.addAttribute("item", item);

但是值得我們關心的不是這些默認的參數,而是我們自定義參數傳入Controller方法的形參中,繼續往下面看。

2.6.1@RequestParam

如果request請求的參數名和controller方法的形參數名稱一致,適配器自動進行參數綁定。如果不一致可以通過
@RequestParam 指定request請求的參數名綁定到哪個方法形參上。

對于必須要傳的參數,通過@RequestParam中屬性required設置為true,如果不傳此參數則報錯。

對于有些參數如果不傳入,還需要設置默認值,使用@RequestParam中屬性defaultvalue設置默認值。

例如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
    {

        //調用service查詢商品的信息
        ItemsCustom itemsCustom=itemsService.findItemsById(id);

        request.setAttribute("item",itemsCustom);

        //zhuyi如果使用request轉向頁面,這里需要指定頁面的完整路徑
        request.getRequestDispatcher("/WEB-INF/jsp/editItem.jsp").forward(request,response);
    }

沒對形參id加上@RequestParam注解時,當我們從頁面進入到editItems.action時,只有從頁面傳入的參數名為id時該id參數值才會傳到editItems()方法的id參數值上,如果從頁面傳入的參數明不為id而為其他參數名時例如http://localhost:8080/SpringMvcMybatis/items/editItems.action?item_id=1,此時通過調試會發現editItems()方法中的id屬性值為null;而當我們為形參id加上了@RequestParam注解并指定了其屬性value = "item_id"后,若從頁面傳入的參數名為item_id,則該參數值會因為添加了value = "item_id"該屬性而被賦值給id屬性。required屬性若設置為true,則如果從頁面進入到editItem.action時沒有傳入此參數則會報錯。defaultvalue屬性值表示為該參數賦默認值。

2.6.2綁定簡單類型

上述那個editItem()方法是原始的servlet開發方法,接下來我們用返回值為String 類型的方法進行注解開發的基礎知識講解。

可以綁定整型、字符串、單精/雙精度、日期、布爾型,很簡單處理,我不進行講解,通過下面綁定pojo類型你就會清楚了。

2.6.3綁定pojo類型

綁定pojo類型又可以分為綁定簡單pojo類型和綁定包裝pojo類型。

2.6.3.1綁定簡單pojo類型

簡單pojo類型只包括簡單類型的屬性。綁定過程:request請求的參數名稱和pojo的屬性名一致,就可以綁定成功。

修改Controller中的editItemSubmit()方法:

//商品提交頁面
    //itemsQueryVo是包裝類型的pojo
    @RequestMapping("/editItemSubmit")
    public String editItemSubmit(Integer id,ItemsCustom itemsCustom) throws Exception
    {


        itemsService.updateItems(id,itemsCustom);
        //請求轉發
//        return "forward:queryItems.action";



        //重定向
       return "redirect:queryItems.action";
    }

點擊提交按鈕,從editItem.jsp頁面進入editItemSubmit.action時,就會將編輯頁面的參數都映射到該方法的id形參和ItemsCustom對象中,此時我們修改商品的信息,然后點擊提交按鈕,服務器反應過程如下:點擊提交按鈕,頁面從editItem.jsp進入到editItemSubmit.action并將修改后的商品信息提交到數據庫并將這些參數傳入到ItemsCustom對象的屬性中,然后重定向到queryItems.action進行商品的列表信息展示。

問題:如果controller方法形參中有多個pojo且pojo中有重復的屬性,使用簡單pojo綁定無法有針對性的綁定,比如:方法形參有items和User,pojo同時存在name屬性,從http請求過程的name無法有針對性的綁定到items或user。要解決此種方法我們就需要用到下面的綁定包裝的pojo類型。

2.6.3.2綁定包裝的pojo類型

這里我們復制editItem.jsp頁面粘貼出一個editItem2.jsp頁面,染護修改editItem2.jsp中的參數名為itemsCustom.name、itemsCustom.price、itemsCustom.detail,修改Controller中的editItemSubmit方法中的形參為public String editItemSubmit(Integer id,ItemsCustom itemsCustom,ItemsQueryVo itemsQueryVo) throws Exception{...}修改editItems的返回值類型為editItems2。運行程序,點擊提交按鈕,頁面信息成功傳入到itemsQueryVo的屬性中。成功運行后我們還是將信息改回成原來的模樣,方便后面的測試。

2.6.4使用屬性編輯器完成自定義綁定

此時我們在editItem.jsp中添加上日期的信息展示:

<tr>
    <td>商品生產日期</td>
    <td><input type="text" name="createtime" value="<fmt:formatDate value="${itemsCustom.createtime}" pattern="yyyy-MM-dd HH-mm-ss"/>"/></td>
</tr>

然后運行程序,當點擊提交按鈕時會報錯,你知道為什么嗎?原因是因為通過點擊提交按鈕,頁面中參數名為"createtime"的參數名由于跟Controller方法中的形參ItemsCustom有相同的屬性名createtime,所以此時頁面中的日期會映射到ItemsCustom的Date屬性中,但是從頁面傳過來的日期是字符串類型,而ItemsCustom的屬性是java.util.Date類型,所以當然會報錯。這樣的話,我們就必須完成日期字符串向java類型日期的轉換。此時我們就需要自定義日期類型的綁定,即使用屬性編輯器來完成自定義的綁定。有如下兩種方法: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));
    }

運行程序,點擊提交按鈕后不會再出現報錯信息,且editItem.jsp頁面的createtime參數也成功傳入到了ItemsCustom的createtime屬性中。使用這種方法的問題是無法在多個controller共用。那我們就來介紹第二種方法:使用WebBindingInitializer(了解)。首先我們需要編寫一個自定義屬性編輯器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文件中加入對它的配置:

<!-- 注冊屬性編輯器 -->
    <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>

然后要在注解適配器的配置標簽中加入如下屬性:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="webBindingInitializer" ref="customBinder"></property> 
</bean>

這樣我們便可以注釋掉第一種屬性編輯器的代碼了,使用第二種方式雖然配置很繁瑣,但是很適用。運行程序,也成功將editItem.jsp頁面的createtime參數映射到ItemsCustom的createtime屬性中。下面我再講一種自定義綁定參數的方法。

2.6.5使用轉換器完成自定義參數綁定(想往架構師方向發展的要掌握這種方法)

首先要定義一個轉換器CustomDateConverter.java完成日期的轉換,代碼如下:

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;
    }
}

在定義一個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;
    }
}

定義好后就需要對轉換器進行配置:思路就是先定義一個轉換器然后注入到適配器中。而對于轉換器在springmvc.xml中的配置有兩種方式,第一種方式針對不使用<mvc:annotation-driven>,第二種方式針對使用<mvc:annotation-driven>,我們就來講講第二種方式。在springmvc.xml中添加如下配置:

    <!--mvc的注解驅動器,通過它可以替代下邊的處理器映射器和適配器-->
    <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="controller.converter.CustomDateConverter"/>
                <bean class="controller.converter.StringTrimConverter"/>
            </list>
        </property>
    </bean>

使用了注解驅動的配置后,我們就可以注釋掉處理器映射器與處理器適配器了。運行程序,也成功將editItem.jsp頁面的createtime參數映射到ItemsCustom的createtime屬性中。

由于往后我們還要進行json數據的開發,所以這里我們還是不采用使用注解驅動的方式,還是采用注解映射器與注解適配器的方式進行開發。為了方便后面對高級注解知識的講解,我們這里采用的自定義綁定參數的方式是通過webBindingInitializer和convertor結合的方式,修改后的最后的springmvc.xml配置信息如下:

  <!--使用spring組件掃描
    一次性配置此包下所有的Handler-->
    <context:component-scan base-package="controller"/>

    <!--mvc的注解驅動器,通過它可以替代下邊的處理器映射器和適配器-->
    <!--<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>

    <!-- 注冊屬性編輯器 -->
    <bean id="customPropertyEditor" class="controller.propertyeditor.CustomPropertyEditor"></bean>



    <!--mvc的注解驅動器,通過它可以替代下邊的處理器映射器和適配器-->
    <!--<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="controller.converter.CustomDateConverter"/>
                <bean class="controller.converter.StringTrimConverter"/>
            </list>
        </property>
    </bean>

這個converter的配置是一勞永逸的配置,也就是系統架構級別的配置,希望你能成功掌握。

好了,通過上述的案例,便成功的使用了SSM框架實現了商品信息的三個功能。希望通過這個案例,你能成功掌握SSM框架進行簡單的注解開發,而我接下來要為你們講解SSM開發中的高級注解開發知識,還是借用這個工程進行開發。

3.聯系

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.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,559評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,442評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,581評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,922評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,096評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,639評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,374評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,591評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,789評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,196評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,322評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,554評論 2 379

推薦閱讀更多精彩內容