1. 程式人生 > >SprimgMVC學習筆記(三)—— 引數繫結

SprimgMVC學習筆記(三)—— 引數繫結

一、預設支援的引數型別

1.1 需求

  開啟商品編輯頁面,展示商品資訊。

  

1.2 需求分析

  編輯商品資訊,首先要顯示商品詳情

  需要根據商品id查詢商品資訊,然後展示到頁面。

  請求的url:/itemEdit.action

  引數:id(商品id)

  響應結果:商品編輯頁面,展示商品詳細資訊。

1.3 ItemService介面

  /**
     * 根據商品id查詢商品資訊
     * @param id
     * @return
     */
    Item queryItemById(int id);

1.4 ItemServiceImpl實現類

@Override
public Item queryItemById(int id) {
    Item item = this.itemMapper.selectByPrimaryKey(id);
    
    return item;
}

1.5 ItemController

  頁面點選修改按鈕,發起請求:http://127.0.0.1:8080/springmvc-web/itemEdit.action?id=1

  需要從請求的引數中把請求的id取出來。Id包含在Request物件中。可以從Request物件中取id。

  想獲得Request物件只需要在Controller方法的形參中新增一個引數即可。Springmvc框架會自動把Request物件傳遞給方法。

/**
 * 根據id查詢商品
 * 
 * @param request
 * @return
 */
@RequestMapping("/itemEdit")
public ModelAndView queryItemById(HttpServletRequest request) {
    // 從request中獲取請求引數
    String strId = request.getParameter("id");
    Integer id = Integer.valueOf(strId);

    // 根據id查詢商品資料
    Item item = this.itemService.queryItemById(id);

    
// 把結果傳遞給頁面 ModelAndView modelAndView = new ModelAndView(); // 把商品資料放在模型中 modelAndView.addObject("item", item); // 設定邏輯檢視 modelAndView.setViewName("itemEdit"); return modelAndView; }

1.5 預設支援的引數型別

  處理器形參中新增如下型別的引數處理介面卡會預設識別並進行賦值。

  • HttpServletRequest:通過request物件獲取請求資訊

  • HttpServletResponse:通過response處理響應資訊
  • HttpSession:通過session物件得到session中存放的物件

1.6 Model/ModelMap

  • Model(開發中常用

  除了ModelAndView以外,還可以使用Model來向頁面傳遞資料,Model是一個介面,在引數裡直接宣告model即可。

  如果使用Model則可以不使用ModelAndView物件,Model物件可以向頁面傳遞資料,View物件則可以使用String返回值替代。

  不管是Model還是ModelAndView,其本質都是使用Request物件向jsp傳遞資料。

/**
 * 根據id查詢商品,使用Model
 * 
 * @param request
 * @param model
 * @return
 */
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, Model model) {
    // 從request中獲取請求引數
    String strId = request.getParameter("id");
    Integer id = Integer.valueOf(strId);

    // 根據id查詢商品資料
    Item item = this.itemService.queryItemById(id);

    // 把結果傳遞給頁面
    // ModelAndView modelAndView = new ModelAndView();
    // 把商品資料放在模型中
    // modelAndView.addObject("item", item);
    // 設定邏輯檢視
    // modelAndView.setViewName("itemEdit");

    // 把商品資料放在模型中
    model.addAttribute("item", item);

    return "itemEdit";
}
  • ModelMap

  ModelMap是Model介面的實現類,也可以通過ModelMap向頁面傳遞資料。

  使用Model和ModelMap的效果一樣,如果直接使用Model,springmvc會例項化ModelMap。

/**
 * 根據id查詢商品,使用ModelMap
 * 
 * @param request
 * @param model
 * @return
 */
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, ModelMap model) {
    // 從request中獲取請求引數
    String strId = request.getParameter("id");
    Integer id = Integer.valueOf(strId);

    // 根據id查詢商品資料
    Item item = this.itemService.queryItemById(id);

    // 把結果傳遞給頁面
    // ModelAndView modelAndView = new ModelAndView();
    // 把商品資料放在模型中
    // modelAndView.addObject("item", item);
    // 設定邏輯檢視
    // modelAndView.setViewName("itemEdit");

    // 把商品資料放在模型中
    model.addAttribute("item", item);

    return "itemEdit";
}

二、繫結簡單型別

  當請求的引數名稱和處理器形參名稱一致時會將請求引數與形參進行繫結。這樣,從Request取引數的方法就可以進一步簡化。

/**
 * 根據id查詢商品,繫結簡單資料型別
 * 
 * @param id
 * @param model
 * @return
 */
@RequestMapping("/itemEdit")
public String queryItemById(int id, ModelMap model) {
    // 根據id查詢商品資料
    Item item = this.itemService.queryItemById(id);

    // 把商品資料放在模型中
    model.addAttribute("item", item);

    return "itemEdit";
}

2.1 支援的資料型別

  引數型別推薦使用包裝資料型別,因為基礎資料型別不可以為null。

  • 整形:Integer、int

  • 字串:String

  • 單精度:Float、float

  • 雙精度:Double、double

  • 布林型:Boolean、boolean

    說明:對於布林型別的引數,請求的引數值為true或false。或者1或0

    請求url:http://localhost:8080/xxx.action?id=2&status=false

    處理器方法:public String editItem(Model model,Integer id,Boolean status

2.2 @RequestParam

  使用@RequestParam常用於處理簡單型別的繫結。

  • value:引數名字,即入參的請求引數名字,如value=“itemId”表示請求的引數中名字為itemId的引數的值將傳入
  • required:是否必須,預設是true,表示請求中一定要有相應的引數,否則將報錯
    TTP Status 400 - Required Integer parameter 'XXXX' is not present
  • defaultValue:預設值,表示如果請求中沒有同名引數時的預設值
@RequestMapping("/itemEdit")
public String queryItemById(@RequestParam(value = "itemId", required = true, defaultValue = "1") Integer id,
        ModelMap modelMap) {
    // 根據id查詢商品資料
    Item item = this.itemService.queryItemById(id);

    // 把商品資料放在模型中
    modelMap.addAttribute("item", item);

    return "itemEdit";
}

三、繫結pojo型別

 3.1 需求

  將頁面修改後的商品資訊儲存到資料庫中。

3.2 需求分析

  請求的url:/updateItem.action

  引數:表單中的資料。

  響應內容:更新成功頁面

3.3 使用pojo接收表單資料

  如果提交的引數很多,或者提交的表單中的內容很多的時候,可以使用簡單型別接受資料,也可以使用pojo接收資料。

  要求:pojo物件中的屬性名和表單中input的name屬性一致

  頁面定義如下:

  

  逆向工程生成的pojo如下:

  

  請求的引數名稱和pojo的屬性名稱一致,會自動將請求引數賦值給pojo的屬性。

3.4 ItemService介面

  在ItemService裡編寫介面方法

  /**
     * 根據id更新商品
     * @param item
     */
    void updateItem(Item item);

3.5 ItemServiceImpl實現類

  在ItemServiceImpl裡實現介面方法

public void updateItem(Item item) {
        /*updateByPrimaryKeySelective會對欄位進行判斷再更新(只是更新新的model中不為空的欄位,如果為Null就忽略更新),
        如果你只想更新某一欄位,可以用這個方法;
        updateByPrimaryKey對你注入的欄位全部更新,會將為空的欄位在資料庫中置為NULL*/
        itemMapper.updateByPrimaryKeySelective(item);
    }

3.6 ItemController

@RequestMapping("/updateItem")
    public String updateItem(Item item){
        // 呼叫服務更新商品
        itemService.updateItem(item);
        
        // 返回邏輯檢視
        return "success";
    }

 3.7 解決post亂碼問題

  提交發現,儲存成功,但是儲存的是亂碼

  

  在web.xml中加入:

<!-- 解決post亂碼問題 -->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 設定編碼參是UTF8 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</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"/>
  • 對引數進行重新編碼:
    // ISO8859-1是tomcat預設編碼,需要將tomcat編碼後的內容按utf-8編碼
    String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8");

四、繫結包裝pojo

4.1 需求

  使用包裝的pojo接收商品資訊的查詢條件。

4.2 需求分析

  包裝物件定義如下:

public class QueryVo {
    private Item item;
  set/get。。。
}

  頁面定義如下圖:

  

4.3 接收查詢條件

    // 繫結包裝資料型別
    @RequestMapping("/queryItem")
    public String queryItem(QueryVo queryVo){
        System.out.println(queryVo.getItem().getId());
        System.out.println(queryVo.getItem().getName());

        return "success";
    }

五、自定義引數繫結

5.1 需求

  在商品修改頁面可以修改商品的生產日期,並且根據業務需求自定義日期格式。

5.2 需求分析

  由於日期資料有很多種格式,springmvc沒辦法把字串轉換成日期型別。所以需要自定義引數繫結。

  前端控制器接收到請求後,找到註解形式的處理器介面卡,對RequestMapping標記的方法進行適配,並對方法中的形參進行引數繫結。可以在springmvc處理器介面卡上自定義轉換器Converter進行引數繫結。

  一般使用<mvc:annotation-driven/>註解驅動載入處理器介面卡,可以在此標籤上進行配置。

5.3 自定義Converter

//Converter<S, T>
//S:source,需要轉換的源的型別
//T:target,需要轉換的目標型別
public class DataConverter implements Converter<String, Date> {

    @Override
    public Date convert(String source) {
        try {
            // 把字串轉換為日期型別
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = simpleDateFormat.parse(source);
            return date;
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 如果轉換異常則返回空
        return null;
    }
}

5.4 在springmvc.xml中配置Converter

  <!-- 註解驅動 -->
    <mvc:annotation-driven conversion-service="conversionService"/>
    
    <!-- 轉換器配置 -->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="cn.itcast.ssm.converter.DataConverter"/>
            </set>
        </property>
    </bean>

 六、繫結陣列

6.1 需求

  在商品列表頁面選中多個商品,然後刪除。

6.2 需求分析

  功能要求商品列表頁面中的每個商品前有一個checkbok,選中多個商品後點擊刪除按鈕把商品id傳遞給Controller,根據商品id刪除商品資訊。

  我們演示可以獲取id的陣列即可

6.3 Controller

  Controller方法中可以用String[]接收,或者pojo的String[]屬性接收。兩種方式任選其一即可。

  定義QueryVo:

public class QueryVo {
    private Item item;
    
    // 用物件的屬性接收陣列,屬性名要同頁面的name值相同
    private Integer[] ids;

}

  ItemController:

    /**
     * 包裝型別 繫結陣列型別,可以使用兩種方式,pojo的屬性接收,和直接接收
     * @param queryVo
     * @return
     */
    @RequestMapping("/queryItem")
    public String queryItem(QueryVo queryVo,Integer[] ids){
        System.out.println(queryVo.getItem().getId());
        System.out.println(queryVo.getItem().getName());
        
        System.out.println(queryVo.getIds().length);
        System.out.println(ids.length);

        return "success";
    }

七、將表單的資料繫結到List

7.1 需求

  實現商品資料的批量修改。

7.2 需求分析

  1. 在商品列表頁面中可以對商品資訊進行修改。

  2. 可以批量提交修改後的商品資料。

7.3 定義pojo

  List中存放物件,並將定義的List放在包裝類QueryVo中

    

7.4 改造jsp頁面

 7.5 Controller

    @RequestMapping("/queryItem")
    public String queryItem(QueryVo queryVo){

        return "success";
    }

  注意接收List型別的資料必須是pojo的屬性,如果方法的形參為ArrayList型別無法正確接收到資料。

  效果: