Spring MVC 绑定请求参数的注解 总结

说明

请求参数的绑定说明
SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定。一般来说要求请求参数名和方法参数名相同,但是也可以通过@RequestParam注解指定请求参数的名称,然后绑定到其他名称的方法参数上

支持的数据类型

  • 基本数据类型和字符串类型
  • 实体类型(JavaBean)
  • 集合数据类型(List,map集合等)

@RequestMapping

@RequestMapping注解不仅可以指定映射的URL、请求方法等,它的params属性还可以用来指定请求参数等

@Controller
@RequestMapping(path="/user")
public class HelloController {
    @RequestMapping(path="/hello")
    public String sayHello(){
        System.out.println("Hello StringMVC");
        return "success";
    }
    
    // 对于params要求的参数,可以是URL携带的,也可以是POST请求中放到请求体中的参数
    // params属性表明请求必须携带username参数
    // @RequestMapping(value="/testRequestMapping",params = {"username"},method = RequestMethod.POST)
    
    // 请求必须携带username参数,并且值必须是hh
    @RequestMapping(value="/test1",params = {"username=hh"},method = RequestMethod.POST)
    public String test1(){
        System.out.println("测试RequestMapping注解...post");
        return "success";
    }
    
    // 可以存在相同的URI,只要请求方式不同就行
    // headers参数表示必须携带的请求头
    @RequestMapping(value="/test1",params = {"username=hh"},headers = {"Accept"})
    public String test2(){
        System.out.println("测试RequestMapping注解...");
        return "success";
    }

	// 请求必须携带username参数,并且值不能是hh
    @RequestMapping(value="/test3",params = {"username!hh"},method = RequestMethod.POST)
    public String test3(){
        System.out.println("测试RequestMapping注解...post");
        return "success";
    }
}

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

直接将方法参数名和请求参数名一 一对应,参数放在URL或者请求体中都可以

对于get请求,需要把参数放到url上注解才生效,否则得到的参数值是null
对于post请求,如果把参数放到了请求体上(当然,你也可以把参数放到url上,只是这样做不符合规范),请求参数格式需要设置成contentType:"application/x-www-form-urlencoded",如果是contentType: "application/json;charset-UTF-8"等其他类型,得到的参数值是null

通过反射的方式,当testParam方法中有名为username和password的参数时,会将请求参数username和password分别赋值给testParam方法中的参数。

ParamController.java

@Controller
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/testParam")
    public String testParam(String username,String password){
        System.out.println("执行了...");
        System.out.println("用户名:"+username);
        System.out.println("密码:"+password);
        return "success";
    }
}

index.jsp

<a href="param/testParam?username=www&password=123">绑定一般类型</a>

把请求参数封装到JavaBean中

直接用一个JavaBean作为方法参数接收就行

对于get请求,需要把参数放到url上注解才生效,,否则得到的JavaBean属性都是null
对于post请求,如果把参数放到了请求体上(当然,你也可以把参数放到url上,只是这样做不符合规范),请求参数格式需要设置成contentType:"application/x-www-form-urlencoded",如果是contentType: "application/json;charset-UTF-8"等其他类型,否则得到的JavaBean属性都是null

基本原理是调用setUsername()、setPassword()、setMoney()方法将请求参数username、password、money赋值给Account 对象的三个属性,再调用user.setUname()、user.setAge()将请求参数user.uname和user.age赋值给user对象的属性。请求参数名和对象中的属性名要相同才能找到set方法。
Account.java

public class Account implements Serializable{

    private String username;
    private String password;
    private Double money;
	// 这里还有个引用类型
    private User user;
	
	//生成getter和setter方法
	//生成toString方法
}

User.java

public class User implements Serializable{

    private String uname;
    private Integer age;
	//生成getter和setter方法
	//生成toString方法
}

index.jsp

<%--html标签的name属性要和后端JavaBean的属性名相同--%>
<form action="param/saveAccount" method="post">
     姓名:<input type="text" name="username" /><br/>
     密码:<input type="text" name="password" /><br/>
     金额:<input type="text" name="money" /><br/>
     用户姓名:<input type="text" name="user.uname" /><br/>
     用户年龄:<input type="text" name="user.age" /><br/>
     <input type="submit" value="提交" />
</form>

ParamController.java

@Controller
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/saveAccount")
    public String saveAccount(Account account){
        System.out.println("执行了...");
        System.out.println(account);
        return "success";
    }
}

把请求参数封装到JavaBean中-包含集合类型的属性

直接用一个JavaBean作为方法参数接收就行
Account.java

public class Account implements Serializable{

    private String username;
    private String password;
    private Double money;

    //包含集合类型的属性
    private List<User> list;
    private Map<String,User> map;
	
	//生成getter和setter方法
	//生成toString方法
}

User.java

public class User implements Serializable{

    private String uname;
    private Integer age;
	//生成getter和setter方法
	//生成toString方法
}

index.jsp

<form action="param/saveAccount" method="post">
    姓名:<input type="text" name="username" /><br/>
    密码:<input type="text" name="password" /><br/>
    金额:<input type="text" name="money" /><br/>

	<%--list[0].uname和list[0].age表示把uname和age的值赋值给user对象的属性,然后把user对象存到集合的0号位置--%>
    用户姓名:<input type="text" name="list[0].uname" /><br/>
    用户年龄:<input type="text" name="list[0].age" /><br/>
    
	<%--map['one'].uname和map['one'].age表示把uname和age的值赋值给user对象的属性,然后把键为'one',值为user对象的键值对存到map集合中--%>
    用户姓名:<input type="text" name="map['one'].uname" /><br/>
    用户年龄:<input type="text" name="map['one'].age" /><br/>
    <input type="submit" value="提交" />
</form>

@RequestParam

用于规定请求参数的名称、是否必须存在。一个方法中可以有多个@RequestParam注解。get和post方式都可用

对于get请求,需要把参数放到url上注解才生效,否则会报错400
对于post请求,如果把参数放到了请求体上(当然,你也可以把参数放到url上,只是这样做不符合规范),请求参数格式需要设置成contentType:"application/x-www-form-urlencoded",如果是contentType: "application/json;charset-UTF-8"等其他类型,会报错400

属性:

  • value/name:请求参数中的参数名
  • required:请求参数中是否必须提供此参数
// name属性也可以替换成value属性,表示请求参数必须有uname,并把参数值赋值给username参数
// required默认是true,表示请求必须待这个参数,取值false表示可以没有该参数,然后把参数值设置为null
@RequestMapping("/test")
public String test(@RequestParam(name="uname", required = false) String username){
    System.out.println("执行了...");
    System.out.println(username);
    return "success";
}

@RequestBody

用于获取请求体内容。一个方法中只能有一个@RequestBody注解。
属性:
required:默认是true,表示必须有请求体,所以get请求会报错;取值false,get请求得到的是null

对于post请求,请求参数格式需要设置成application/json;charset-UTF-8",否则会报错“415 – 不支持的媒体类型”

(1)

<a href="anno/testRequestBody?uname=哈哈&age=12">RequestParam</a>
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody(required = false) String user){
    System.out.println(user); //get请求,得到的值是null,如果不加required=false,则会报错
    return "success";
}

(2)

<form action="anno/testRequestBody" method="post">
    用户姓名:<input type="text" name="uname" /><br/>
    用户年龄:<input type="text" name="age" /><br/>
    <input type="submit" value="提交" />
</form>
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String user){
    System.out.println(user); //以字符串形式接受数据uname=1&age=1
    return "success";
}

(3)将请求的json字符串映射成JavaBean参数
需要引入jar包:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.0</version>
</dependency>

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.9.0</version>
</dependency>

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-annotations</artifactId>
  <version>2.9.0</version>
</dependency>
<script>
    // 页面加载,绑定单击事件
    $(function(){
        $("#btn").click(function(){
            $.ajax({
                url:"testAjax",
                contentType:"application/json;charset=UTF-8",
                //data:'{"username":"张三","password":"123","age":30}',
                data:JSON.stringify({"username":"张三","password":"123","age":30}),
                dataType:"json",
                type:"post",
                success:function(data){
                    // data服务器端响应的json的数据,进行解析
                    alert(data);
                    alert(data.username);
                    alert(data.password);
                }
            });
        });
    });
</script>
@RequestMapping("/testAjax")
public @ResponseBody User testAjax(@RequestBody User user){
    // 客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中
    user.setUsername("李四");
    user.setAge(40);
    // 返回user对象,因为有@ResponseBody注解,框架会自动将该对象的属性转成json字符串
    return user;
}

@PathVariable

用于支持Restful风格的URL,绑定url中的占位符,例如请求url中/delete/{id},这个{id}就是url占位符
属性:

  • value:指定url中的占位符
  • required:是否必须提供占位符

原来的方式:
在这里插入图片描述
restful风格的方式(即使path相同,请求方式不同,会根据请求方式映射到不同的方法中):
在这里插入图片描述
根据id查询,传统方式写法是“user?id=10”:
在这里插入图片描述

例:

<a href="anno/testPathVariable/10">testPathVariable</a>
//name属性用于指定把url中的占位符sid的值取出来赋值给id参数
@RequestMapping(value="/testPathVariable/{sid}")
public String testPathVariable(@PathVariable(name="sid") String id){
    System.out.println(id);
    return "success";
}

@RequestHeader

用于获取请求消息头信息

//获取Accept请求头的值
@RequestMapping(value="/testRequestHeader")
public String testRequestHeader(@RequestHeader(value="Accept") String header, HttpServletRequest request,HttpServletResponse response) throws IOException {
    System.out.println(header);
    return "success";
}

@ModelAttribute

  • 用在方法上,表示该方法会在控制器的方法执行之前先执行
  • 用在参数上,获取指定的数据给参数赋值
@RequestMapping(value="/testModelAttribute")
public String testModelAttribute(@ModelAttribute("abc") User user){
    System.out.println("testModelAttribute执行了...");
    System.out.println(user);
    return "success";
}

// 在执行testModelAttribute()方法之前,这个方法会先执行
// 应用场景就是,如果我们在编辑一个用户信息时,我们只传递了用户名和年龄到后台,没有日期,那这个日期字段对
// 应的属性就是null,而我们期望的是修改的时候,这个字段用原本数据库中的字段,那这个注解就能解决这个问题
// 假如请求参数是uname=‘hh’,age=10;而数据库中这条记录对应的是uname=‘sl’,age=20,data=‘3030-05-02’,那么在testModelAttribute()方法中,user参数对应的值就是uname=‘hh’,age=10,data=‘3030-05-02’
@ModelAttribute
public void showUser(String uname, Map<String,User> map){
    System.out.println("showUser执行了...");
    // 模拟从数据库中查到这个用户
    User user = new User();
    user.setUname(‘hh’);
    user.setAge(20);
    user.setDate(new Date());
    map.put("abc",user);
}

// 也可以是这种写法
@ModelAttribute
public User showUser(String uname){
    System.out.println("showUser执行了...");
    // 模拟从数据库中查到这个用户
    User user = new User();
    user.setUname(‘hh’);
    user.setAge(20);
    user.setDate(new Date());
    return user;
}

解决post请求中文乱码

SpringMVC框架提供的请求参数过滤器,在web.xml中添加过滤器:

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

自定义类型转换器

一般类型,如Account中有一个为Integer类型的属性,请求参数是字符串类型,则框架会自动将字符串类型转为整型。但是也有转换异常的情况,如Account有一个为Data类型的属性,只有请求参数字符串是’xxxx/xx/xx’格式的时候才会正常转换成Data类型,'xxxx-xx-xx’格式则不会转换成功,因此这时候就需要我们自定义类型转换器。

SpringMVC框架是一个基于组件的框架,我们可以编写一个类型转换器,然后在resources/springmvc.xml文件中配置这个类型转换器类,当需要类型转换的时候,前端控制器会找到类型转换器帮助我们完成类型转换。

Converter是类型转换的总接口,所有自定义的类型转换器类都必须实现这个接口。

StringToDateConverter.java

/**
 * 把字符串转换日期
 */
public class StringToDateConverter implements Converter<String,Date>{

    /**
     * String source    传入进来字符串
     * @param source
     * @return
     */
    public Date convert(String source) {
        System.out.println("lxzh");
        
        // 判断
        if(source == null){
            throw new RuntimeException("参数不能为空");
        }
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

        try {
            // 把字符串转换日期
            return df.parse(source);
        } catch (Exception e) {
            throw new RuntimeException("数据类型转换出现错误");
        }
    }
}

resources/springmvc.xml

<!--其它配置...-->
<!--配置自定义类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="cn.ith.utils.StringToDateConverter"/>
        </set>
    </property>
</bean>

<!--开启springmvc框架注解的支持,并开启类型转换器-->
<mvc:annotation-driven conversion-service="conversionService"/>

<!--其它配置...-->

这样,当Account中有一个为Data的属性,为这个属性赋值的时候,就会调用类型转换器类将"xxxx-xx-xx"转换成正确的日期类型。应该注意的是,框架默认的将"xxxx/xx/xx"格式字符串转成日期类型将不再起作用。

SpringMVC接收请求参数所有方式总结

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值