四、SpringMVC数据绑定

1 单个简单数据类型

1.1 提交

提交单个基本数据类型方式有两种,一是通过URl进行提交,二是通过构建表单进行提交。

  • 方式1:URL

    <a href="../user/add?userName=tom&userAge=22&userSex=1">URL提交数据</a>
    
  • 方式二:表单

    • 输入框需要提供name属性,springMVC控制器是通过name属性取值。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="../user/add"method="post">
    <p>姓名</p><input type="text"name="userName"/>
    <p>年龄</p><input type="text"name="useAge"/>
    <p>性别</p><input type="text"name="userSex"/>
    <p><input type="submit" value="提交"></p>
</form>
</body>
</html>

注意

当前目录结构如下:
在这里插入图片描述

<form action="user/add"method="post">

请求路径为:http://localhost:8080/demo2_war/pages/user/add

<form action="/user/add"method="post">

请求路径为:http://localhost:8080/user/add

<form action="../user/add"method="post">

正确请求路径为http://localhost:8080/demo2_war/user/add

1.2 接收

无论通过URL还是通过表单,接收方式一样。但需要注意以下几点。

  • 如果控制器方法中接收数据的参数名与请求传值的key一致,则自动复制。

  • 如果不一致,使用@RequestParam注解进行关联。该注解共有四个属性值

    • vaule name的别名,请求参数的名称,绑定请求参数,基本等价与name。
    • name 绑定请求参数名称,等价于vaule
    • required,指定参数是否为必须,默认为true,如果请求路劲没有传入该参数,则会报错。
    • defaultValue 设置参数默认值,如果设置了值, 则required=ture不会生效,自动变成required=false
  • 也可以直接使用对象接收数据,前提是对象是属性名必须与name一致

package com.yiwu.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/add")
    public String addUser(String userName,Integer userAge,@RequestParam("userSex") Integer s){
        System.out.println("访问到了插入用户````");
        System.out.println(userName);
        System.out.println(userAge);
        System.out.println(s);
        return "success";
    }
    @RequestMapping("/delete")
    public String deleteUser(){
        System.out.println("访问到了删除用户");
        return "success";
    }
}

或使用类对象作为参数

@RequestMapping("/add3")
public String addUser2(User user){
    System.out.println("访问到了插入用户````");

    System.out.println(user);
    return "success";
}

其中User类为

package com.yiwu.pojo;

public class User {
    String userName;
    Integer userAge;
    Integer ueerSex;

 //set方法
 //get方法
}

2 多个简单数据类型

存在前端需要传递多个同名参数到服务器的情况,如传递一组ID值等。

1.1 提交

<form action="../user/info" method="post">
    <input name="uid" value="1" type="checkbox">张三<br/>
    <input name="uid" value="2" type="checkbox">李四<br/>
    <input name="uid" value="3" type="checkbox">王二<br/>
    <input type="submit" value="查询详情">
</form>

1.2 接收

接收方式一,以数组方式接收

@RequestMapping("/info")
public String info(String[] uid){
  for (String id:uid){
      System.out.println(id);
  }
  return null;
}

接收方式二,以集合List方式接收,需要使用注解@RequestParam

@RequestMapping("/info")
public String info(@RequestParam("uid") List<String> uid){
  for (String id:uid){
      System.out.println(id);
  }
  return null;
}

3 自定义类型

自定义数据类型,并且自定义类型的属性中有为List类型,属性为map,数组,集合的情况。

如实体用户更改为

public class User {
  String userName;
    Integer userAge;
    Integer userSex;
    IdCard idcard;
    List<Order> orders;
    List<Integer> orderIDs;
 }   

其中 IdCard为:

public class IdCard{
	int id;
    int idcardNum;
}

Order 为

public class Order {
	int id;
	int OrderNum;
}

3.1 提交

<form action="../user/info" method="post">
    姓名:<input name="userName" value="1" type="text"><br/>
    年龄:<input name="userAge" value="2" type="text"><br/>
    姓别:<input name="userSex" value="3" type="text"><br/>
    
    用户Id号:<input name="idcard.idcardNum" value="2" type="text"><br/>
    
    订单Id:<input name="orderIDs" value="1" type="checkbox"><br/>
    订单Id:<input name="orderIDs" value="2" type="checkbox"><br/>
    订单Id: <input name="orderIDs" value="3" type="checkbox"><br/>
    
    定单1:<input name="orders[0].OrderNum" value="3" type="text"><br/>
    订单2:<input name="orders[1].OrderNum" value="3" type="text"><br/>
    <input type="submit" value="提交数据">
</form>

若List泛型为基本数据类型,则name为属性名

若泛型为自定义类型,name名要与实体类的层级结构保持一致。

若属性为Map类型,如

HashMap<String,user> userInfo;其中user为自定义类型,有age,sex等属性。

则前端页面的name属性,应该为userInfo[“张三”].Age,userInfo[“张三”].Sex

3.2 接收

@RequestMapping("/info")
public String info(User user){
    System.out.println(user);
  return null;
}

4 JSON数据类型

JSON 是一种轻量级的数据交换格式。JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。他由花括号括起来的逗号分割的成员构成,成员是字符串键和上文所述的值由逗号分割的键值对组成。

1.要实现从JSON字符串转换为JS对象,使用 JSON.parse() 方法:

var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //结果是 {a: 'Hello', b: 'World'}

2.要实现从JS对象转换为JSON字符串,使用 JSON.stringify() 方法:

var json = JSON.stringify({a: 'Hello', b: 'World'}); //结果是 '{"a": "Hello", "b": "World"}'

4.1 提交

1使用jQuery,导入 jquery-3.3.1.min.js,放至pages下的js文件夹内。(jquery下载地址https://jquery.com/download/)

2放行静态资源,<mvc:resources mapping="/pages/**" location="/pages/"/>

3请求行、请求头、请求体都可以用来传值

<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>

<form  method="post">
    <p>姓名</p><input type="text" id="userName" name="userName"/>
    <p>年龄</p><input type="text" id="userAge" name="userAge"/>
    <p>性别</p><input type="text" id="userSex" name="userSex"/>
    <p><input type="button" value="提交" onclick="submitInfo()"></p>
</form>

<script>
    function submitInfo(){
        var obj={}
         obj.userName = $("#userName").val();
         obj.userAge = $("#userAge").val();
         obj.userSex = $("#userSex").val();
         console.log(JSON.stringify(obj))
         console.log(obj)
         $.ajax(
             {
                 //请求行
                 url:"../user/add4",
                 //url:"../user/add4?userName=zhangsan&userAge=2&userSex=1",
                 type:"post",
                 //请求头
                 headers:{
                     token:"xxxx"
                 },
                 contentType:"application/json",
                 //请求体
                 data:JSON.stringify(obj),
                 success:function (res){
					 //打印响应数据
                     console.log(JSON.parse(res));
                     console.log(res);
                 }
             }
         )
    }
</script>

4.2 接收

引入jackson依赖。用于序列化和反序列化json,也就是json与java数据之间的转换。

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

🔴接收请求行中的数据,同表单或URL简单数据类型。

🔴**接收请求头中的数据,控制器形参使用RequestHeader("token") token**修饰

 @RequestMapping("/add")
    public String addUser(@RequestHeader("token")String token, String userName, Integer userAge, @RequestParam("userSex") Integer s){
        System.out.println(token);
        System.out.println(userName);
        System.out.println(userAge);
        System.out.println(s);
        return "success";
    }

🔴接收请求体中的数据。

    @RequestMapping("/add4")
    @ResponseBody
    public List<User> addUser4(@RequestBody User user){
        System.out.println("访问到了插入用户````");
        System.out.println(user);
        //响应数据给前端
        List<User> users = new ArrayList<User>();
        users.add(new User("aaa",21,0));
        users.add(new User("bbb",33,1));
        return users;
    }

5 控制器处理请求

5.1 转发、重定向

处理同步请求,如理URL,表单from,根据处理结果进行重定向或转发,处理器方法的返回类型为String或者ModelAndView

重定向不回自动加上前缀或后缀。

package com.yiwu.controllers;

import com.yiwu.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/test01")
    public String test01(){
        //两种写法
        //return "forward:../success.jsp";
        return "success";
    }

    @RequestMapping("/test02")
    public String test02(){
        return "redirect:../success.jsp";
    }
    @RequestMapping("/test03")
    public ModelAndView test03(){
        //两种写法
        //ModelAndView modelAndView = new ModelAndView("success");
        ModelAndView modelAndView = new ModelAndView("forward:../success.jsp");
        return modelAndView;
    }
    @RequestMapping("/test04")
    public ModelAndView test04(){
        ModelAndView modelAndView = new ModelAndView("redirect:../success.jsp");
        return modelAndView;
    }
}

<a href="../user/test01">转发测试1</a><br/>
<a href="../user/test02">重定向测试1</a><br/>
<a href="../user/test03">转发测试2</a><br/>
<a href="../user/test04">重定向测试2</a><br/>

重定向地址栏会发生变化,转发地址栏不会发生变化;

请求转发(forward)整个过程是一个请求,一个响应

过程:客户首先发送一个请求到服务器端,服务器端发现匹配的servlet,并指定它去执行,当这个servlet执行完之后,把请求转发给指定的test.jsp,整个流程都是在服务器端完成的,而且是在同一个请求里面完的,因此servlet和jsp共享的是同一个request,在servlet里面放的所有东西,在jsp中都能取出来,因此,jsp能把结果getAttribute()出来。

重定向(sendRedirect)两个请求,两个响应。
过程:客户发送一个请求到服务器,服务器匹配servlet,这和请求转发一样,当这个servlet处理完之后,立即向客户端返回这个响应,响应行告诉客户端你必须要再发送一个请求,去访问test.jsp,紧接着客户端受到这个请求后,立刻发出一个新的请求,去请求test.jsp,这里两个请求互不干扰,相互独立,

两者的不同的适用场景:
请求转发只需要请求一次服务器,可以提高访问速度。
重定向可以跳转到任意服务器,可以用在系统间的跳转。

5.2 传递数据

对于同步请求的转发响应,我们可以传递参数到转发的页面

  • 返回类型为String
    • 在控制器方法中定义一个Model类型的参数
    • 在return页面之前,向model中添加键值对,添加的键值对就会被传递到转发的页面
  • 返回值为ModelAndView
    • modelAndView.addObject(“key1”,“value”);

jsp页面:

<a href="../user/test06">返回值为String,参数为Model,传值测试1</a><br/>

<a href="../user/test07">返回值为ModelAndView,传值测试2</a><br/>


   @RequestMapping("/test06")   
public String test06(Model model) {

        User temUser = new User("aaa",20,0);
        model.addAttribute("key1","vvvvv");
        model.addAttribute("user",temUser);
        return "test";
    }

    @RequestMapping("/test07")
    public ModelAndView test07() {
        User temUser = new User("bbb",20,1);
        ModelAndView modelAndView = new ModelAndView("test");
        modelAndView.addObject("key1","xxxx");
        modelAndView.addObject("user",temUser);
        return modelAndView;

    }

test.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
	${key1}
<br>
	${user.userName}
	${user.userAge}
</body>
</html>

5.3 处理异步请求

直接在控制器方法返回响应的对象

在对应的controller的方法上添加注解@ResponseBody,让这个方法返回值不走视图解析器,直接返回一个字符串;除了这个注解外,我们还可以使用注解@RestController代替类上的@Controller注解,它的作用就是设置这个controller类中的所有的处理方法返回的值都不走视图解析器,而是直接返回一个字符串

  • 在控制器方法前添加一个 @ResponseBody 注解,将返回的对象转换成JSON格式返回给ajax请求,json的键为属性名,value为属性值。
  • 也可以在控制器类前添加 @ResponseBody 注解,则所有方法都是响应ajax请求,
@RequestMapping("/test05")
@ResponseBody
public List<User> test05(){
    List<User> users = new ArrayList<User>();
    User user = new User();
    user.setUserAge(22);
    user.setUserSex(1);
    user.setUserName("hahah");
    users.add(user);
    return users;
}

<input id = "btn3" type="button" value="处理异步请求测试"/><br>

<span>姓名: </span><p id = "userName"></p>
<span>年龄: </span><p id = "userAge"></p>
<span>性别: </span><p id = "userSex"></p>

<script type="text/javascript">
    $("#btn3").click(function (){
        $.ajax({
            url:"../user/test05",
            type:"post",
            contentType:"application/json",
            dataType:"json",
            success:function (res){
                console.log(res);
                //写法一
                //$("#userName").text(res[0]["userName"])
                //写法2
                $("#userName").text(res[0]["userName"])
                $("#userAge").text(res[0]["userAge"])
                $("#userSex").text(res[0]["userSex"])
            }
        });
    });
</script>

在这里插入图片描述在这里插入图片描述在这里插入图片描述

6 RestFul风格

概念

Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。互联网所有的事物都可以被抽象为资源。

资源操作

可以通过不同的请求方式来实现不同的效果。例如请求地址一样,请求方式不一样,功能可能不一样;一般情况下

  • POST表示添加
  • DELETE表示删除
  • PUT表示更新
  • GET表示查询。

案例:查询id为3用户

  • 传统方式下的访问路径可能是

    • localhost:8080/demo2_war/user/getuser?id=3
  • 使用RestFul风格,设置请求方式为GET

    • localhost:8080/demo2_war/user/getuser/3

第一步,编写控制器

@RequestMapping(value = "/test09/{name}/{age}",method = {RequestMethod.GET})
public String test09(@PathVariable String name ,@PathVariable int age) {
    System.out.println(name);
    System.out.println(age);
    return null;
}

第二步,编写前端页面

<input id = "btn4" type="button" value="restFul风格默认get请求"/><br>
<script type="text/javascript">
    $("#btn4").click(function (){
        $.ajax({
            url:"../user/test09/abc/22",
            type:"get",
            contentType:"application/json",
            dataType:"json",
            success:function (res){

            }
        });
    });
</script>

第四步、验证不同的请求方式,同样的请求地址,可以到达不同的处理器方法。

更改步骤3的请求方式进行验证。

@RequestMapping(value = "/test09/{name}/{age}",method = {RequestMethod.GET})
    public String test09(@PathVariable String name ,@PathVariable int age) {
        System.out.println("GET");
        System.out.println(name);
        System.out.println(age);
        return null;
    }

    @RequestMapping(value = "/test09/{name}/{age}",method = {RequestMethod.PUT})
    public String test10(@PathVariable String name ,@PathVariable int age) {
        System.out.println("PUT");
        System.out.println(name);
        System.out.println(age);
        return null;
    }

    @RequestMapping(value = "/test09/{name}/{age}",method = {RequestMethod.DELETE})
    public String test11(@PathVariable String name ,@PathVariable int age) {
        System.out.println("DELETE");
        System.out.println(name);
        System.out.println(age);
        return null;
    }

    @RequestMapping(value = "/test09/{name}/{age}",method = {RequestMethod.POST})
    public String test12(@PathVariable String name ,@PathVariable int age) {
        System.out.println("POST");
        System.out.println(name);
        System.out.println(age);
        return null;
    }

注意点:

  • 所有的地址栏请求默认都会是HTTP GET类型

  • 使用下述注解可以代替 @RequestMapping,无须指定请求方式。

    • @GetMapping
    • @PostMapping
    • @PutMapping
    • @DeleteMapping
  • 例如

@GetMapping(“/add1/{a}/{b}”)
等价于
@RequestMapping(value = “/add1/{a}/{str}”,method = {RequestMethod.GET})

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老去的90后

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值