Spring MVC使用篇(七)—— 参数绑定

本文详细介绍了Spring MVC中的参数绑定,包括简单类型、包装类型和集合类型的参数绑定。简单类型参数绑定可以通过@RequestParam注解进行,支持默认值和空值处理。包装类型参数绑定可以处理单一和嵌套的包装类型,如Fruits实体类。集合类型参数绑定则涵盖数组、List和Map类型,通过特定的name属性格式进行绑定。
摘要由CSDN通过智能技术生成

1、参数绑定综述

  当用户在页面触发某种请求时,一般会将一些参数(key/value)带到后台。在Spring MVC中可以通过参数绑定,将客户端请求的key/value数据绑定到Controller处理器方法的形参上,显然,这是很关键的一个问题。

  当用户发送一个请求时,根据Spring MVC的请求处理流程,前端控制器会请求处理器映射器HandlerMapping返回一个处理器(或处理器链),然后请求处理器适配器HandlerAdapter执行相应的Handler处理器。此时,处理器适配器HandlerAdapter会调用Spring MVC提供的参数绑定组件将请求的key/value数据绑定到Controller处理器方法对应的形参上。

  关于Spring MVC的参数绑定组件,早期版本中使用PropertyEditor,其只能将字符串转换为Java对象,而后期版本中使用Converter转换器,它可以进行任意类型的转换。Spring MVC提供了很多的Converter转换器,但在特殊情况下需要自定义Converter转换器(如日期数据绑定)。

  Spring MVC中有一些默认支持的类型,这些类型可以直接在Controller类的方法中定义,在参数绑定的过程中遇到该种类型就直接进行绑定。其默认支持的类型有以下几种:HttpServletRequest、HttpServletResponse、HttpSession及Model/ModelMap。

  HttpServletRequest可以通过request对象获取请求信息。

  HttpServletResponse可以通过response对象处理响应信息。

  HttpSession可以通过session对象得到session中存放的对象。

  Model是一个接口,ModelMap是一个接口实现,它的作用就是讲model数据填充到request域。

2 、简单类型参数绑定

  在Spring MVC中还可以自定义简单类型,这些类型也是直接在Controller类的方法中定义,在处理key/value信息时,就会以key名寻找Controller类的方法中具有相同名称的形参并进行绑定。

  例如下面的例子,根据水果商品的id来获取水果的详细信息,具体Controller代码如下:

package com.ccff.controller;

import com.ccff.model.Fruits;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//基于注解的Handler类
//使用 @Controller来标识它是一个控制器
@Controller
@RequestMapping("/query")
public class FruitsController {
   
    private FruitsService fruitsService = new FruitsService();
    //根据水果id查询水果信息
    @RequestMapping(value = "/queryFruitByID.action", method = RequestMethod.GET)
    public String queryFruitByID(Model model, int id){
   
        //模拟service获取水果商品列表
        List<Fruits> fruitsList = fruitsService.queryFruitsList();
        List<Fruits> resultFruit = new ArrayList<>();
        for (Fruits fruits : fruitsList){
   
            if (fruits.getId() == id)
                resultFruit.add(fruits);
        }
        //将结果放到model中传到显示页面中
        model.addAttribute("resultFruit",resultFruit);
        return "fruits/resultFruitList";
    }         
}

class FruitsService{
   
    public List<Fruits> queryFruitsList(){
   
        List<Fruits> fruitsList = new ArrayList<Fruits>();

        Fruits apple = new Fruits();
        apple.setId(1);
        apple.setName("红富士苹果");
        apple.setPrice(2.3);
        apple.setProducing_area("山东");

        Fruits banana = new Fruits();
        banana.setId(2);
        banana.setName("香蕉");
        banana.setPrice(1.5);
        banana.setProducing_area("上海");

        fruitsList.add(apple);
        fruitsList.add(banana);
        return fruitsList;
    }
}

  可以在执行queryFruitByID请求时,为其指定一个参数id。由于通过RequestMapping的method属性指定了请求类型为GET类型,所以把项目部署在Tomcat上后,可以使用下面的URL请求:http://localhost:8080/demo/query/queryFruitByID.action?id=1就可以获得id为1的水果商品的详细信息,结果如图所示:
在这里插入图片描述
  当然,如果参数名字不为“id”,绑定就不会成功,不过可以通过使用注解的方式为请求参数指定别名。注解@RequestParam可以对自定义简单类型的参数进行绑定,即如果使用@RequestParam,就无须设置Controller方法的形参名称与request传入的参数名称一致。而不使用@RequestParam时,就需要Controller方法的形参名称与request传入的参数名称一致,这样才能够绑定成功。

  假设执行queryFruitByID请求时,传入的id属性名称为fruit_id,而Java代码使用的是驼峰命名,那么可以通过@RequestParam注解来指定绑定名称,而在形参中继续使用驼峰命名,Controller具体代码如下:

package com.ccff.controller;

import com.ccff.model.Fruits;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//基于注解的Handler类
//使用 @Controller来标识它是一个控制器
@Controller
@RequestMapping("/query")
public class FruitsController {
   
    private FruitsService fruitsService = new FruitsService();
    //根据水果id查询水果信息
    @RequestMapping(value = "/queryFruitByID.action", method = RequestMethod.GET)
    public String queryFruitByID(Model model, @RequestParam(value = "fruit_id") int fruitId){
   
        //模拟service获取水果商品列表
        List<Fruits> fruitsList = fruitsService.queryFruitsList();
        List<Fruits> resultFruit = new ArrayList<>();
        for (Fruits fruits : fruitsList){
   
            if (fruits.getId() == fruitId)
                resultFruit.add(fruits);
        }
        //将结果放到model中传到显示页面中
        model.addAttribute("resultFruit",resultFruit);
        return "fruits/resultFruitList";
    }         
}

class FruitsService{
   
    public List<Fruits> queryFruitsList(){
   
        List<Fruits> fruitsList = new ArrayList<Fruits>();

        Fruits apple = new Fruits();
        apple.setId(1);
        apple.setName("红富士苹果");
        apple.setPrice(2.3);
        apple.setProducing_area("山东");

        Fruits banana = new Fruits();
        banana.setId(2);
        banana.setName("香蕉");
        banana.setPrice(1.5);
        banana.setProducing_area("上海");

        fruitsList.add(apple);
        fruitsList.add(banana);
        return fruitsList;
    }
}

  再次将项目部署到Tomcat上后,在浏览器输入请求URL:http://localhost:8080/demo/query/queryFruitByID.action?fruit_id=1 ,可得如下结果,证明正确。
在这里插入图片描述
  当Controller方法有多个形参时,如果请求中不包含其中的某个形参,此时是不会报错的,所以使用该参数时要进行空校验。如果要求绑定的参数一定不能为空,可以使用@RequestParam注解中的required属性来指定该形参是否必须传入,required属性为“true”指定参数必须传入。

  修改Controller中的代码如下:

package com.ccff.controller;

import com.ccff.model.Fruits;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//基于注解的Handler类
//使用 @Controller来标识它是一个控制器
@Controller
@RequestMapping("/query")
public class FruitsController {
   
    private FruitsService fruitsService = new FruitsService();
    //根据水果id查询水果信息
    @RequestMapping(value = "/queryFruitByID.action", method = RequestMethod.GET)
    public String queryFruitByID(Model model, @RequestParam(value = "fruit_id", required = true) int fruitId){
   
        //模拟service获取水果商品列表
        List<Fruits> fruitsList = fruitsService.queryFruitsList();
        List<Fruits> resultFruit = new ArrayList<>();
        for (Fruits fruits : fruitsList){
   
            if (fruits.getId() == fruitId)
                resultFruit.add(fruits);
        }
        //将结果放到model中传到显示页面中
        model.addAttribute("resultFruit",resultFruit);
        return "fruits/resultFruitList";
    }         
}

class FruitsService{
   
    public List<Fruits> queryFruitsList(){
   
        List<Fruits> fruitsList = new ArrayList<Fruits>();

        Fruits apple = new Fruits();
        apple.setId(1);
        apple.setName("红富士苹果");
        apple.setPrice(2.3);
        apple.setProducing_area("山东");

        Fruits banana = new Fruits();
        banana.setId(2);
        banana.setName("香蕉");
        banana.setPrice(1.5);
        banana.setProducing_area("上海");

        fruitsList.add(apple);
        fruitsList.add(banana);
        return fruitsList;
    }
}

  在上面的例子,如果请求中没有包含fruit_id这个参数,直接请求URL:http://localhost:8080/demo/query/queryFruitByID.action ,则会报下图所示错误:
在这里插入图片描述
  在Controller方法的形参中,如果有一些参数可能为空,但是又期望它们为空时有一个默认值,此时可以使用@RequestParam注解中的defaultValue属性来指定某些参数的默认值。

  如将之前的Controller中queryFruitByID方法中的fruitId参数设置为空时的默认值为1,具体代码如下:

package com.ccff.controller;

import com.ccff.model.Fruits;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//基于注解的Handler类
//使用 @Controller来标识它是一个控制器
@Controller
@RequestMapping("/query")
public class FruitsController {
   
    private FruitsService fruitsService = new FruitsService();
    //根据水果id查询水果信息
    @RequestMapping(value = "/queryFruitByID.action", method = RequestMethod.GET)
    public String queryFruitByID(Model model, @RequestParam(value = "fruit_id"
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值