springmvc请求参数的绑定和常用的注解

请求参数的绑定

请求参数的绑定说明

绑定机制

​ 表单提交的数据都是k=v格式的 username=haha&password=123

​ SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的

​ 要求:提交表单的name和参数的名称是相同的

支持的数据类型

基本数据类型和字符串类型

	@Controller
	@RequestMapping(value = "/user")
	public class UserController {
	
	    /***
	     * 接收基本数据类型和String
	     * 此时可以访问 http://localhost:18081/user/add?id=9&name=传智播客
	     * 注意:此时请求地址的id和name和addUser(int id,String name)中的入参名字要一致才能接到参数。
	     * @return
	     */
	    @RequestMapping(value = "/add")
	    public String addUser(int id,String name){
	        System.out.println("ID:"+id+",NAME:"+name);
	        return "success";
	    }
	}

实体类型(JavaBean)

创建User实体Bean

public class User {
	private String name;
	private Integer age;
	//get...set...
}

修改addUser方法

@Controller
@RequestMapping(value = "/user")
public class UserController {
	
	 /***
	  * 这里直接接收一个User 对象即可
	  * 注意:
	  *      页面表单需要和user对应的属性名字一致
	  *      姓名:<input name="name" />  name="name"和User的name属性名一样
	  *      年龄:<input name="age" />  name="age"和User的age属性名一样
      * @return
	 */
	@RequestMapping(value = "/add")
	public String addUser(User user){
	    System.out.println("AGE:"+user.getAge()+",NAME:"+user.getName());
	    return "success";
	 }
}

创建index.jsp,在index.jsp中加入如下表单

<form action="/user/add" method="post">
	    <div>
	        名字:<input name="name" >
	    </div>
	    <div>
	        年龄:<input name="age" >
	    </div>
	    <div>
	        <input type="submit" value="提交">
	    </div>
	</form>
集合数据类型(Map、List)

接收Map类型

在上面案例中,修改addUser方法,注意需要加上一个注解@RequestParam来接收Map数据

 @Controller
  @RequestMapping(value = "/user")
  public class UserController {
      /***
       * 接收Map
       * @return
       */
      @RequestMapping(value = "/add")
      public String addUser(@RequestParam Map userMap){
          System.out.println(userMap);
          return "success";
      }
  }
接收List类型

在上面案例中,把addUser方法修改一下,注意需要加上一个注解@RequestParam来接收List数据

 @Controller
  @RequestMapping(value = "/user")
  public class UserController {
      /***
       * 接收List
       *      注意:接收List,需要在方法中加入注解@RequestParam
       *            一会儿页面传过来的表单参数名字也要和方法名字id一致
       *            例如:
       *                  ID1:<input name="id">
       *                  ID2:<input name="id">
       *                  ID3:<input name="id">
       * @return
       */
      @RequestMapping(value = "/add")
      public String addUser(@RequestParam List<Integer> id){
          System.out.println(id);
          return "success";
      }
  }

修改index.jsp表单

 <form action="/user/add">
      <div>
          ID1:<input name="id" >
      </div>
      <div>
          ID2:<input name="id" >
      </div>
      <div>
          ID3:<input name="id" >
      </div>
      <div>
          <input type="submit" value="提交">
      </div>
  </form>

入参参数总结

  1. 提交表单的name和参数的名称是相同的
  2. 如果接收JavaBean则必须和JavaBean的属性名相同
  3. 区分大小写

实体引用类型(JavaBean)
比如现在有一个User对象,它里面有个属性IdCard,也可以直接接收,只需要页面表单的名字和JavaBean属性名字保持一致即可。

定义JavaBean

创建IdCard
public class IdCard {
    //身份证号
    private String number;
    //身份证地址
    private String address;

    //get..set..
}

修改User
public class User {
    private String name;
    private Integer age;
    //引用IdCard作为子属性
    private IdCard idCard;
	
	//get.. set..
}

修改addUser方法
@Controller
@RequestMapping(value = "/user")
public class UserController {
    /***
     * 接收引用JavaBean
     *      注意:页面填充表单的时候,name的值仍然要和后台接收的JavaBean的属性名一样。
     *            但如果有引用属性填充,就写[引用属性名].[引用属性自身对应属性名]
     *      例如:
     *          身份证号:<input name="idCard.number" >
     *          地址:<input name="idCard.address" >
     *
     * @return
     */
    @RequestMapping(value = "/add")
    public String addUser(User user){
        System.out.println("用户" + user.getName() + "今年" + user.getAge() + "岁,住在" + user.getIdCard().getAddress() + ",身份证号是" + user.getIdCard().getNumber());
        return "success";
    }
}

修改index.jsp的表单

<form action="/user/add">
    <div>
        名字:<input name="name" >
    </div>
    <div>
        年龄:<input name="age" >
    </div>
    <div>
        身份证号:<input name="idCard.number" >
    </div>
    <div>
        地址:<input name="idCard.address" >
    </div>
    <div>
        <input type="submit" value="提交">
    </div>
</form>

给JavaBean集合属性数据封装
如果JavaBean有集合属性,JSP页面编写方式:list[0].属性

我们在上面案例基础上添加一个Mobile对象,再在User中添加一个集合属性List mobiles属性。

创建Mobile并修改User
我们保持addUser方法不变,只修改JavaBean和页面即可。

创建Mobile
public class Mobile {
    //手机名字
    private String mobileName;
    //手机价格
    private Float price;
    //get..set..
}

修改User
public class User {
    private String name;
    private Integer age;
    //引用IdCard作为子属性
    private IdCard idCard;
    //一个人买了多个手机
    private List<Mobile> mobiles;

	//get.. set..
}

addUser方法不变,我们可以打印一些信息
@Controller
@RequestMapping(value = "/user")
public class UserController {
    /***
     * 接收引用JavaBean
     *      注意:页面填充表单的时候,name的值仍然要和后台接收的JavaBean的属性名一样。
     *            但如果有引用属性填充,就写[引用属性名].[引用属性自身对应属性名]
     *      例如:
     *          身份证号:<input name="idCard.number" >
     *          地址:<input name="idCard.address" >
     *
     * 接收的JavaBean里如果存在List集合,则页面需要每次用下标来告诉程序是第几个,其他的用法和单个JavaBean用法一样
     *      例如:
     *          第1个手机名字:<input name="mobiles[0].mobileName" >
     *          第1个手机价格:<input name="mobiles[0].price" >
     *
     *          第2个手机名字:<input name="mobiles[1].mobileName" >
     *          第2个手机价格:<input name="mobiles[1].price" >
     * @return
     */
    @RequestMapping(value = "/add")
    public String addUser(User user){
        System.out.println("用户" + user.getName() + "今年" + user.getAge() + "岁,住在" + user.getIdCard().getAddress() + ",身份证号是" + user.getIdCard().getNumber());
        for (Mobile mobile : user.getMobiles()) {
            System.out.println(mobile.getMobileName()+"花了"+mobile.getPrice());
        }
        return "success";
    }
}

修改index.jsp的表单

<form action="/user/add">
    <div>
        名字:<input name="name" >
    </div>
    <div>
        年龄:<input name="age" >
    </div>
    <div>
        身份证号:<input name="idCard.number" >
    </div>
    <div>
        地址:<input name="idCard.address" >
    </div>

    <div>
        第1个手机名字:<input name="mobiles[0].mobileName" >
    </div>
    <div>
        第1个手机价格:<input name="mobiles[0].price" >
    </div>
    <div>
        第2个手机名字:<input name="mobiles[1].mobileName" >
    </div>
    <div>
        第2个手机价格:<input name="mobiles[1].price" >
    </div>
    <div>
        <input type="submit" value="提交">
    </div>
</form>

请求参数POST请求中文乱码的解决

在web.xml中配置Spring提供的过滤器类

<!-- 配置过滤器,解决中文乱码的问题 -->
<filter>
	<filter-name>characterEncodingFilter</filter-name>
	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
	<!-- 指定字符集 -->
	<init-param>
		<param-name>encoding</param-name>
		<param-value>UTF-8</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>characterEncodingFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

自定义类型转换器
表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明Spring框架内部会默认进行数据类型转换。但Date类型并不能实现转换,需要我们手动解决。

如果想自定义数据类型转换,可以实现Converter的接口

自定义类型转换器
package com.itheima.util;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateConverter implements Converter<String,Date>{
    /***
     * 将String类型转成Date类型
     * @param str
     * @return
     */
    public Date convert(String str) {
        try {
            //定义一个时间转换工具对象
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            //将字符串转Date并返回
            return simpleDateFormat.parse(str);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}
注册自定义类型转换器,在springmvc.xml配置文件中编写配置
<!-- 配置spring开启注解mvc的支持-->
<mvc:annotation-driven conversion-service="conversionService" />

<!--
    注册自定义类型转换器
-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <bean class="com.itheima.util.DateConverter" />
    </property>
</bean>

在控制器中使用原生的ServletAPI对象
只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象

常用的注解

RequestParam注解

作用:把请求中的指定名称的参数传递给控制器中的形参赋值
	属性
		value:请求参数中的名称
		required:请求参数中是否必须提供此参数,默认值是true,必须提供

代码如下
/**
 * 接收请求
 * @return
 */
@RequestMapping(path="/hello")
public String sayHello(@RequestParam(value="username",required=false)String name) {
	System.out.println("aaaa");
	System.out.println(name);
	return "success";
}

**

RequestBody注解

**

作用:用于获取请求体的内容(注意:get方法不可以)
属性
required:是否必须有请求体,默认值是true

代码如下
/**
 * 接收请求
 * @return
 */
@RequestMapping(path="/hello")
public String sayHello(@RequestBody String body) {
	System.out.println("aaaa");
	System.out.println(body);
	return "success";
}

**

PathVariable注解

**

作用:拥有绑定url中的占位符的。例如:url中有/delete/{id},{id}就是占位符
属性
value:指定url中的占位符名称

Restful风格的URL
	请求路径一样,可以根据不同的请求方式去执行后台的不同方法
	restful风格的URL优点
        结构清晰
        符合标准
        易于理解
        扩展方便

PathVariable案例代码如下

<a href="user/hello/1">入门案例</a>

/**
 * 接收请求
 * @return
 */
@RequestMapping(path="/hello/{id}")
public String sayHello(@PathVariable(value="id") String id) {
	System.out.println(id);
	return "success";
}	

**

RequestHeader注解

**

作用:获取指定请求头的值
	属性
value:请求头的名称

   代码如下

  @RequestMapping(path="/hello")
  public String sayHello(@RequestHeader(value="Accept") String header) {
  	System.out.println(header);
  	return "success";
  }

**

CookieValue注解

**

作用:用于获取指定cookie的名称的值
属性
   value:cookie的名称
代码
@RequestMapping(path="/hello")
public String sayHello(@CookieValue(value="JSESSIONID") String cookieValue) {
	System.out.println(cookieValue);
	return "success";
}

**

ModelAttribute注解

**
作用
出现在方法上:表示当前方法会在控制器方法执行前线执行。
出现在参数上:获取指定的数据给参数赋值。
应用场景
当提交表单数据不是完整的实体数据时,保证没有提交的字段使用数据库原来的数据。

具体的代码

**

修饰的方法有返回值

**

在上面的案例基础之上,给User中添加一个sex属性,再到UserController中添加一个parameterUser()方法,并创建User再赋值返回,方法上加上注解@ModelAttribute注解。

@Controller
@RequestMapping(value = "/user")
public class UserController {
    /***
     * 优先执行
     * @return
     */
    @ModelAttribute
    public User parameterUser(){
        User user = new User();
        user.setSex("男");
        return user;
    }

    /***
     * 此时的user已经被上面的parameterUser先执行了修改,已经给sex赋值
     */
    @RequestMapping(value = "/add")
    public String addUser(User user){
        System.out.println("用户" + user.getName() +",性别:"+user.getSex()+","+ "今年" + user.getAge() + "岁,住在" + user.getIdCard().getAddress() + ",身份证号是" + user.getIdCard().getNumber());
        for (Mobile mobile : user.getMobiles()) {
            System.out.println(mobile.getMobileName()+"花了"+mobile.getPrice());
        }
        return "success";
    }
}

**

修饰的方法没有返回值

**
在上面案例基础上,把parameterUser的返回值去掉,增加一个Map来存储数据,存储的key为user,在addUser中使用@ModelAttribute(“user”)User user获取在parameterUser()方法中赋值的数据。程序运行后,我们发现addUser方法的user参数能取到parameterUser方法赋值的数据。

@Controller
@RequestMapping(value = "/user")
public class UserController {
    /***
     * 优先执行
     * @return
     */
    @ModelAttribute
    public void parameterUser(Map<String,User> userMap){
        User user = new User();
        user.setSex("男");
        userMap.put("user",user);
    }

    /***
     * 此时的user已经被上面的parameterUser先执行了修改,已经给sex赋值
     */
    @RequestMapping(value = "/add")
    public String addUser(@ModelAttribute("user")User user){
        System.out.println("用户" + user.getName() +",性别:"+user.getSex()+","+ "今年" + user.getAge() + "岁,住在" + user.getIdCard().getAddress() + ",身份证号是" + user.getIdCard().getNumber());
        for (Mobile mobile : user.getMobiles()) {
            System.out.println(mobile.getMobileName()+"花了"+mobile.getPrice());
        }
        return "success";
    }
}

**

Model使用

**
SpringMVC会把Model(模型信息)中的的数据放入到request域对象中,页面可以通过EL表达式来取request域中的数据。我们可以先写一个案例,在后台使用Model的addAttribute方法,页面使用EL表达式取数据。

创建	ModelController
@Controller
@RequestMapping(value = "/model")
public class ModelController {

    /***
     * Model的使用
     * @param model
     * @return
     */
    @RequestMapping(value = "/add")
    public String add(Model model){
        model.addAttribute("msg","张三");
        return "success";
    }
}

success.jsp页面从request域中取数据
${msg}
${requestScope}

**

SessionAttributes注解

**

作用:用于多次执行控制器方法间的参数共享
	属性
	value:指定存入属性的名称

代码如下
@Controller
@RequestMapping(path="/user")
@SessionAttributes(value= {"username","password","age"},types= {String.class,Integer.class})		// 把数据存入到session域对象中
public class HelloController {
	
	/**
	 * 向session中存入值
	 * @return
	 */
	@RequestMapping(path="/save")
	public String save(Model model) {
		System.out.println("向session域中保存数据");
		model.addAttribute("username", "root");
		model.addAttribute("password", "123");
		model.addAttribute("age", 20);
		return "success";
	}
	
	/**
	 * 从session中获取值
	 * @return
	 */
	@RequestMapping(path="/find")
	public String find(ModelMap modelMap) {
		String username = (String) modelMap.get("username");
		String password = (String) modelMap.get("password");
		Integer age = (Integer) modelMap.get("age");
		System.out.println(username + " : "+password +" : "+age);
		return "success";
	}
	
	/**
	 * 清除值
	 * @return
	 */
	@RequestMapping(path="/delete")
	public String delete(SessionStatus status) {
		status.setComplete();
		return "success";
	}

}

发布了30 篇原创文章 · 获赞 0 · 访问量 2466

猜你喜欢

转载自blog.csdn.net/duanduan339/article/details/103372543