SpringMVC系列之参数传递【前后端参数传递的方式详解】

· spring mvc参数传递的方式有哪些?

一、前端向后台传递参数的方式:
  1. 通过 Servlet api 中的 HttpServletRequest对象
  2. 基本数据类型 + String类型
  3. Array 数组
  4. Java Bean 对象
  5. List 集合
  6. Map 集合
  7. JSON 格式
二、后台向前端通过request域传递值的方式:
  1. Servlet api 中的 HttpServletRequest对象
  2. ModelAndView 对象
  3. ModelMap 对象
  4. Model 对象
  5. Map 集合

· spring mvc参数传递方式的具体代码实现?

以下代码,只给出前端页面和后端SpringMVC中Controller的具体代码实现。基本的SpringMVC配置可以另外查看专门讲解 SpringMVC配置文件 书写的文章。

一、前端向后台传递参数的方式

1.通过 Servlet api 中的 HttpServletRequest对象

这种方式想必是学习了Java Web之后,最熟悉的一种获取前端页面传递参数的方式。直接在服务器端,使用对HttpServletRequest对象进行操作即可。我们曾几何时,都是这样干的String name = request.getParameter("name");通过request对象的getParameter()方法直接获取指定的key属性名,即可获取到对应的value属性值,然后赋值给了name变量。

在SpringMVC的Controller中,这种传统方式也是存在的。具体代码如下:

	import org.springframework.stereotype.Controller;
	import javax.servlet.http.HttpServletRequest;
	
	@Controller
	@RequestMapping("/param")
	public class ParamController{
	
		@RequestMapping("/servlet")
	    public String servlet(HttpServletRequest request){
	        String name = request.getParameter("name");
	        System.out.println("name:" + name);
	        request.setAttribute("result", "hello " + name);
	        return "hello";
	    }
	  
    }

这种方式需要注意的点,无非就是在Controller具体的请求处理方法中,需要传入一个HttpServletRequest对象,来作为当前方法的形参,然后就可以在此方法中,使用这个request对象了,这个对象跟之前传统的方法中的request对象是一致的。通过它,可以获取到很多的内容,getSession(),getHeader(),getAttribute()等等。

在前端页面中,访问的时候,只需要指定url的路径,然后利用key=value的形式访问即可。无需书写其他的代码,例如:

http://localhost:8080/param/servlet?name=golden3young

这样,后端接收到name参数的之后,使用System.out.println("name:" + name);即可将值打印到控制台上。至于最后两行的代码,是解析视图的内容,后续进行讲解,这里不做展开。

2. 基本数据类型 + String类型

所谓基本数据类型和String类型传值,是什么意思呢?其实就是,我们可以在SpringMVC的Controller中具体请求处理方法中,直接使用基本数据类型或者String类型的参数进行对映,只要前端页面和方法中指定的参数名称是完全一致的,这里包括大小写,那么前端这个参数名称所赋有的值,就会传递到后台的请求处理方法中。其实这其中,是SpringMVC底层的拦截器帮我们实现的,它会将请求中传来的所有参数,跟我们所定义的请求处理方法中的参数进行对比,如果发现是一模一样的,它就会从请求中把那个参数的值拿出来赋给我们处理方法中的那个变量,于是,我们就可以直接使用了。当然,这个转换的过程比较复杂,也同样存在一些问题,稍后会告诉大家。

SpringMVC的Controller中,具体的请求处理方法:

	@RequestMapping("/simple")
    public String simple(int id, String name, ModelMap modelMap){
        System.out.println("id:" + id);
        System.out.println("name:" + name);
        modelMap.addAttribute("result", "Hello " + name + "," + id);
        return "hello";
    }

为了讲解的清晰,我将Controller类声明和导包的代码都省略了,只给出核心的请求处理方法的代码。
这里,我们可以看出,Controller中定义了,请求路径为/simple的请求,将直接执行simple()这个方法,而这个方法,我们给了3个形参,id,name,modelMap,这里,我们只关注int id, String name 即可,这两个参数的类型一个是int,属于基本数据类型之一;另一个是String字符串类型。那么这么写的意义是什么呢?其实就是前端页面在传递值的时候,如果有参数名为id或者name的属性,则会直接将属性的值赋给这两个变量。

前端页面,在访问时,只需要给出指定的url和传递指定名称的参数即可,例如:

http://localhost:8080/param/simple?id=1&name=golden3young

通过上面的url,可以看出,请求直接奔向/param/simple,而对应的方法恰好就是simple()方法,同时前端请求通过key=value的格式传递了两个参数,id 和 name, 而我们的simple()方法中,恰好就有同名的id 和 name,那么我们simple()方法中的id和name将获得前端请求传来的值,1 和 golden3young。同时,它们的类型,也会被转变成方法中定义的int和String类型。

有的同学可能发现了,前端请求在传递过程中,明明都是通过字符串格式传递的,而为什么到了Controller的simple()方法中,就变成了int和String类型?是怎么转换的?其实,这就是SpringMVC的过滤器为我们做的事情。它不光接收映射同名的参数,而且还会将类型帮助我们转换成功。但是,类型的转换,存在着问题,比如:int类型是整数类型,刚才传来的参数id就是int类型,而值恰好是1,则不会出现问题,可是如果将值改成abc等非数字的内容呢?那肯定是会报错的,因为数字格式异常,无法进行转换。同时,还有传递的时候忘记传递id属性而只传了name属性,或者id属性只给了key,而没有value值,这些情况,都会导致错误的出现。

罗列一下几种错误:

http://localhost:8080/param/simple?id=&name=golden3young

此时,id为空字符串,那么SpringMVC底层在为我们转换的时候,是将空串转成int类型,那肯定是会报错的。页面报错400.

http://localhost:8080/param/simple?name=golden3young

此时,我们没有传递id这个属性,那么SpringMVC底层在匹配的时候,一旦没有找到前端传来的属性,那么就会直接给Controller的方法中的参数赋值成null,那么把null转成int类型,同样也是会报错的。页面报错500.

那像以上几种情况,都需要大家在前端参数传递的时候,注意不要遗漏并且给出正确类型的数值。这里加一个小的拓展。有些情况,我们可能无法断定前端一定会传过来某一个属性,有可能不传,那这种情况,我们可以进行规范。使用的注解是@RequestParam,后续会介绍。

3. Array 数组

这种方式,简单来说,就是在前端页面通过发送数组格式的数据,后台Controller的处理方法中,在接收参数的时候,直接转换成数组格式。跟 基本数据类型和String类型的 思想是一样的,但是转换的类型是不同的。
那这种方式,我们在前端页面中,经常用到的地方,其实就是form表单中的多选框,因为多选框的name都是一样的,但是值有多个,传递到后端页面后,传统方式是进行截取,而现在SpringMVC可以帮助我们完成底层的工作,直接给我们一个array数组。

前端页面代码:

<form action="${pageContext.request.contextPath}/param/array" method="post">
     爱好:
     <input type="checkbox" name="hobby" value="唱歌" />唱歌
     <input type="checkbox" name="hobby" value="跳舞" />跳舞
     <input type="checkbox" name="hobby" value="书法" />书法
     <input type="checkbox" name="hobby" value="滑雪" />滑雪
     <br>
     <input type="submit" value="提交" />
</form>

Controller中的处理方法:

	@PostMapping("/array")
    public String array(String[] hobby, Map<String, String> map){
       for(String hobbyStr : hobby){
           System.out.println(hobbyStr);
       }

       //使用 java.util.Map 向request域传值 【本例不必关注】
       map.put("result","测试数组传参");
       return "hello";
    }

通过前后端代码的比对,相信大家不难看出,前端参数的name为hobby,value的值为多个不同的值,而后端Controller中的方法中,指定了同名hobby的一个String数组类型的参数,于是乎,SpringMVC底层,就把从前端传递过来的多个hobby的值,以数组的格式存放到了hobby数组中。我们使用了for循环进行了遍历打印。 后两行的代码同样无需关注。

4. Java Bean对象

通过上面3种方式的介绍,大家其实也能感觉出来,SpringMVC大大简化了我们将请求中的参数进行转换的这样一个过程,我们只需要吃现成的即可。那么同样有这样一个问题,如果前端页面一次性要传递多个参数,比如十个以上,包括:id,age,name,birthday,gender,school,city,province,area,salary,married等等参数,如果按照上面学过的方法,我们需要把这所有的参数都写在执行方法的形参位置处即可。如:

	@RequestMapping("/bean")
    public String testBean(int id, int age, String name, String birthday, String school,
    String city, String area, double salary, boolean married){
       .....
    }

放眼望去,可以说是非常长,写起来同样也是非常麻烦,如果执行方法不光这一个,还有多个,都需要接收这些参数,那我们写起来就会浪费大量的无用功的时间。这时,我们就用到面向对象的编程思想,也就是创建一个对象,让这些参数都成为这个对象的属性,然后,SpringMVC就会将前端传来的这些参数的名称与我们指定的对象(Java Bean)的属性进行名称的对比,如果一致,那么就进行赋值,于是乎,我们先创建一个对象,用来存放所有的参数:

@Data
public class User{
	private int id;
	private int age;
	private String name;
	private String birthday;
	private String school;
	private String city;
	private String area;
	private double salary
	private boolean married;
}

那么这样,Controller中处理方法的代码就简化成了这样:

	@RequestMapping("/bean")
    public String testBean(User user){
       .....
    }

然后,我们只需要在方法中,调用user.getter方法,来获取所有的属性值或者说参数值。
当然,这里有的同学可能会问,那底层是怎么实现的呢?SpringMVC底层其实还是将请求中的参数剥离出来,然后调用我们指定的这个对象(Java Bean)的setter方法来为同名的属性进行赋值,当我们用的时候,直接使用getter方法来用。有同学会问,那你刚才写的User类中没有写getter和setter啊,其实这里,我偷了个懒,使用的是lombok插件,它会自动为我们生成getter和setter,有兴趣的同学,可以自己学一下,非常简单。

那前端页面在传参的时候,还是保证访问指定的url,然后传递同名的参数即可,没有其他的变化,例如:

http://localhost:8080/param/bean?id=1&name=golden3young&age=18&married=false

根据我上面的url请求来看,后端springMVC在接收值的时候,只能映射到id,name,age,married这4个参数的值给User对象的同名属性,而其他的属性由于我没有传值,所以都会保持初始默认值,那这个默认值,就是Java基础部门的内容了,也就是所有Java类型的默认值。

5. List集合

以List集合参数类型接收前端传来的参数,其实就是将前端传来的参数在后端Controller中自动进行类型的转换,转换成Java中的List集合类型来存储前端传来的参数。想要springmvc自动将接收的参数转换成List集合类型,有两种方法:

  1. 将List集合定义在Java Bean中
  2. 接收JSON格式数组
-1- 将List集合定义在Java Bean中

这种方式比较简单直接,需要先创建一个Bean对象,然后将我们需要接收的参数定义成这个Bean对象的一个属性,这里要求参数的name需要与属性名完全一致,这样springmvc底层就可以自动的将名称相同的参数和bean中对象的属性进行映射赋值,我们只需要使用即可。

这里,我们看一下后端的代码实现

  • 创建一个User对象(Java Bean)
public class User {
    private List<Integer> idList;
    // 必须有 getter 和 setter方法
    public void setIdList(List<Integer> idList){
		this.idList = idList;
	}
	public List<Integer> getIdList(){
		return this.idList;
	}
}

将想要接收的参数名称定义成这个类对象的一个属性,属性的类型需要定义成List集合形式,至于泛型也是可以自动进行转换的,可以根据自己的需求进行调整,不单单是String类型。例如这里,我们让它自动接收前端传来名为idList的多个参数,然后自动将其存储在List集合中,并且所有的idList参数都由字符串自动转成Integer类型。而我们只需要在Controller中,定义一下Bean对象参数即可,代码如下:

@RequestMapping("/testList")    
    public String testList(User user, Map<String, Object> map){
        List<Integer> idList = user.getIdList();
        idList.forEach(id -> System.out.println(id));
		
		// 以下代码与本例无关
        map.put("result","测试List传参");
        return "hello";
    }

在Controller的处理方法中,我们只需要在方法参数列表中,声明一个User user对象,将我们刚才写有idList属性的类对象引入即可,不需要直接引入idList属性,而是引用包含它的Bean 对象,这样,我们就可以直接在方法中,使用user这个对象了,通过getIdList()属性,拿到转换后的List类型的参数。

前端页面在传递List类型参数的时候,可以直接用form表单传递,代码:

<h2>测试List传参</h2>
   <form action="${pageContext.request.contextPath}/param/testList" method="post">
       ID:
       <input type="checkbox" name="idList" value="1" />1
       <input type="checkbox" name="idList" value="2" />2
       <input type="checkbox" name="idList" value="3" />3
       <input type="checkbox" name="idList" value="4" />4
       <br>
       <input type="submit" value="提交" />
   </form>

这里的代码是典型的发送List集合类型参数的前端代码,使用的是form表单中的checkbox多选框,由于多选框的值有多个,并且name属性相同,那么后端在接收起来时,就不再是一对一的关系,而是一个属性(字段)有多个值,那么正好可以使用List集合来存放。

如果前端页面不想使用form表单提交,那么还有第二种方式,可以通过js代码来发送JSON格式的数组信息来进行数据的提交,更加的灵活。

-2- 接收JSON格式数组

后端接收前端多个参数时,不仅是通过Bean对象的属性来进行转换存储,还可以直接接收,无需借助任何的变量类型。但是,这里就对前端传递参数的格式有了要求,也就是说,如果想在后端Controller中接收到前端传递的多个参数,并转换成List集合形式,那么就需要前端按照规范来进行传递,那到底是什么规范呢?那就是JSON格式。

先来看一下后端对于请求的处理方法:

	@RequestMapping(value = "/jsonToList", method = RequestMethod.POST)
    @ResponseBody	// 此注解与本例无关
    public String jsonToList(@RequestBody List<String> hobby){
        for(String hob: hobby){
            System.out.println(hob);
        }

		// 以下代码与本例无关
        // Spring MVC 可以将json格式的字符串转换成json
        return "{\"code\":200,\"msg\":\"SUCCESS\"}";    //JSON格式的字符串
    }

详细剖析一下这个方法,首先@RequestMapping注解定义value属性来指定拦截的路径,为/jsonToList,method属性来指定拦截请求的类型为POST类型,其他的类型不作拦截。紧接着定义了一个名为jsonToList的处理方法,参数列表中定义了一个List< String>类型的变量名为hobby,这其实就是前端一会传来的参数,名字就是hobby,并且有多个,统一存放在List< String>类型的hobby变量中,但是这里非常重要的一点就是,这里使用了 @RequestBody 注解,只有加上这个注解,才能告诉springmvc底层,它需要自动为我们完成参数的转换映射赋值,否则,我们定义的List类型的hobby变量,是没有办法将前端传来的参数装到自己肚子里的,这个工作是springmvc底层帮我们做的,需要的就是 @RequestBody 这个注解, 将它加载参数声明前面即可。

那这样,后端就可以直接在方法中使用变量了。我们看一下前端发送参数时的代码:

const path = '${pageContext.request.contextPath}';
// 将Json数据转换成List
   function testJsonToList(){
       //定义一个json数组  new  Array()
       let hobby = ['唱歌','跳舞','喝酒','烫头']
       $.ajax({
           url: path + '/param/jsonToList',
           type: 'post',
           data: JSON.stringify(hobby), //数组也是js对象
           dataType: 'json',   //简写 application/json
           contentType: 'application/json',
           success: res=>{
               alert('code:' + res.code + ', msg:' + res.msg)
           }
       })
   }

以上代码片段是写在前端< script>标签中的,即脚本代码。这里进行一下剖析,以便大家理解。

定义了一个名为testJsonToList的方法,其中首先定义了一个名为hobby的数组,这个数组有4个值,分别是唱歌、跳舞、喝酒、烫头。数组名为hobby,与后端controller中我们定义的List名称完全一致(只有这样才能完成自动映射);同时,需要注意的是,这里我们将参数是封装在一个数组对象中,格式是:用 [ ] 将内容包裹在内。思考一下:为什么要用数组进行存储呢? 下面会给出解释。
接下来发送ajax请求,指定 url 到实现约定的地址;
type 指定为POST类型;
data 为我们要传递的参数,这里我们使用了 JSON.stringify() 方法,这个发送是JSON所持有的,作用是将一个js对象转换成JSON格式,为什么要转换成JSON格式?这是本例在开头就说好的,后端想要直接接收多个同名参数并存放到List集合中,前端发送参数时就必须按规定发送,规定就是JSON格式,这里的JSON.stringify() 其作用就是帮助我们完成格式的转换,换句话说,就是我们可以直接在前端定义一个js支持的数组对象或者是Js对象都可以,然后通过这个方法让它自动为我们完成转换;当然,我们也可以自己直接将内容写成JSON格式,例如:{“hobby:”:“唱歌”,“hobby”:“跳舞”,“hobby”:“喝酒”,“hobby”:“烫头”},但是这样书写如果字段比较多的时候,会比较的繁琐,所以不如直接写一个js中的数组对象,然后使用 JSON.stringify() 来帮助我们完成格式的转换。
dataType 为我们传递数据的格式,毋庸置疑是JSON格式,所以写成’application/json’,当然简写就是’json‘.
contentType 为指定编码格式。服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。使用 POST 提交数据方案,包含了 Content-Type 和消息主体编码方式两部分。application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数。
sucess 为回调函数,此处代码与本例无关,不作过多解释。

>> 总结 > 发送JSON格式直接到后端Controller,无非需要注意两点:

后端Controller的执行方法中,需要给参数列表加上@RequestBody注解,并确保存储变量与前端发送参数的name保持一致。
前端发送的内容,必须是JSON格式,可以自己手写JSON格式也可以使用JSON.stringify来转换成JSON格式。ajax请求中,需要修改dataType和contentType,值都是’application/json’,可以不使用简写。

6. Map集合

以Map集合参数类型接收前端传来的参数,其实就是将前端传来的参数在后端Controller中自动进行类型的转换,转换成Java中的Map集合类型来存储前端传来的参数。想要springmvc自动将接收的参数转换成Map集合类型,有两种方法:

  1. 将Map集合定义在Java Bean中
  2. 接收JSON格式对象
-1- 将Map集合定义在Java Bean中

有了List集合的介绍,这里直接上代码,先看一下Bean对象:

public class User {

    private Map<String, String> userMap;
    
    public Map<String, String> getUserMap() {
        return userMap;
    }

    public void setUserMap(Map<String, String> userMap) {
        this.userMap = userMap;
    }
}

定义一个Map类型的结合,用于存储前端出来名为userMap的多个参数。

接下来,看一下Controller中的处理方法:

    @PostMapping("/testMap")
    public String testMap(User user){
        Map<String, String> userMap = user.getUserMap();
        System.out.println(userMap);
		...
    }

这里剖析一下:@PostMapping注解为指定只拦截POST请求,同时拦截的Url为 /testMap,执行方法名成testMap,参数列表中直接定义User user对象,与List集合完全相同。于是,在方法中,就可以直接使用user对象,使用getUserMap()方法就可以拿取到userMap这个对象中的内容,我们使用System.out.println()将其遍历打印出来。

接下来,看一下前端页面的传递参数代码:

const path = '${pageContext.request.contextPath}';

function testMap(){
    $.ajax({
        url: path + '/param/testMap',
        type: 'POST',
        data: "userMap['id']=100&userMap['name']=zs",    // Map<String, String> {id=1,name=zs}
        dataType: 'text',
        success: function(res){
            alert(res)
        },
        error: function (err) {
            alert(err)
        }
    })
}

这里对上述代码片段进行一下剖析,在前端< script >代码中,定义名为testMap的方法;
url: 发送ajax请求到指定的Url与后台的controller中的testMap方法对应。
type: 指定请求类型为POST
data: 指定参数传递的内容,这里的格式需要大家记住,Map集合由于是键值对类型的格式,所以在发送中,需要采用 name[‘key’]=value的格式进行发送,name为当前属性的name值,在这里也就是userMap,对应了后台controller方法中的Map集合类型的userMap变量,[‘id’]为第一个Key,对应的value就是100,而第二个key是’name’ 对应的值为 zs,这里需要注意的是,如果参数大于1个,那么参数直接需要用&符号进行连接,最终将所有的内容,写在双引号中。
dataType: 此时的数据类型仅仅为text文本格式

-2- 接收JSON格式对象

除了上述通过规范传递内容的格式,来发送传递内容外,还可以将发送内容的格式定义为JSON格式。JSON格式就不需要我们手动的规范传递的参数格式了,也就不再需要自己去写 这种:data: "userMap['id']=100&userMap['name']=zs",代码,因为一旦字段多的时候,写起来非常的麻烦。

接下来,看一下后台Controller的代码:

	@PostMapping("/jsonToMap")
    public User jsonToMap(@RequestBody Map<String, Object> map){
        // {id: 1, hobby: ['踢球','跳舞'], user: {id:1, name:'zs'}}  -- json格式
        System.out.println(map);
        ...
    }

此时,我们在参数列表中定义了 一个Map集合名为map,key的泛型为String,value的泛型为Object,也就是说,value的类型可以是任意类型。(其实这里的变量名称map,可以是任意的名称,不需要再与前端保持一致了,因为这里的映射规则是key和value的键值对了)

接下来,看一下前端页面的代码:

const path = '${pageContext.request.contextPath}';

//将json数据转换成Map
 function testJsonToMap(){
     let obj = {id: 1, hobby: ['唱歌', '跳舞', '打游戏'], user: {id: 1, name:'四哥'}}

     $.ajax({
         url: path + '/param/jsonToMap',
         type: 'POST',
         data: JSON.stringify(obj),
         dataType: 'json',
         contentType: 'application/json',
         success: res=>{
             alert(res.id + res.name + res.age)
         }
     })
 }

可以看出,由于此时后端接收参数的类型变成了Map集合类型,也就是键值对类型,需要有一个key和一个value来组合对应。那么前端拥有这种格式的类型,数组已经无法满足了,因为数组的值是一个整体,没有办法体现出一个个键值对(Key=value),此时!前端唯一能有这种格式的,就剩下Js对象了!使用js对象,就可以模拟出key=value的格式,如上代码中所写:let obj = {id: 1, hobby: ['唱歌', '跳舞', '打游戏'], user: {id: 1, name:'四哥'}} ,定义了一个js对象名为obj,这个js对象的键值对之间都用逗号(,)隔开,第一对为id:1,key为id,value为1;第二对,key为hobby,value为数组对象 [‘唱歌’, ‘跳舞’, ‘打游戏’];第三对,key为user,value为js对象{id: 1, name:‘四哥’}。

最终整个对象被{ }包裹,由此可以看出,此时参数传递对应的关键所在已经变成了key和value的对应,此时的key在后端会被自动映射成String类型,而value则被映射成Object类型,如果我们需要将Value的Object类型进行进一步的转换,可以在后端使用强制类型转换,非常的方便。

同时,此时我们也不需要自己手写key=value的格式数据了,直接使用js对象即可。

接下来就是发送ajax请求,
url: 指定到规定的请求地址
type: 必须修改成post
data: 传递的参数,这里使用JSON.stringify()来帮助我们将js对象转换成json格式的数据
dataType: 数据的类型,当然是’json’,这是简写。
contentType: 请求头中规定的编译格式,为’application/json’
success: 回调函数

>> 总结 > 发送JSON格式直接到后端Controller,无非需要注意两点:

后端Controller的执行方法中,需要给参数列表加上@RequestBody注解,并确保存储变量与前端发送参数的name保持一致。
前端发送的内容,必须是JSON格式,可以自己手写JSON格式也可以使用JSON.stringify来转换成JSON格式。ajax请求中,需要修改dataType和contentType,值都是’application/json’,可以不使用简写。

7. JSON 格式

这里所谓的JSON格式传递参数,其实已经在5、6两个模块介绍过了,这里做一下总结。
①JSON格式传递参数,我们可以手写JSON格式,或者是将js中的数据、对象进行转换,采用的是JSON.stringify()方法,可以节省我们手写的繁琐。
②htpp协议的请求方法使用post,http协议的请求头的contentType是application/json
③springmvc底层在帮我们进行JSON格式的解析和与Java属性之间的映射,springmvc 使用jackson作为默认的json转换器,所以,需要我们引入maven依赖。总共有3个jar包:jackson-core.jar ,jackson-databind.jar,jackson-annotation.jar。而jackson-databind.jar依赖于其他两个jar,于是我们在引入的时候,只需要引入jackson-databind.jar这一个jar包即可,另外两个自动引入。
④ @RequestBod注解可以将json格式数据转换成java bean,list,map。@ResponseBody注解可以将Object类型返回值转成json格式的数据

二、后台向前端通过request域传递值的方式:

1. Servlet api 中的 HttpServletRequest对象

代码:

	//servlet请求
    @RequestMapping("/servlet")
    public String servlet(HttpServletRequest request){
        String name = request.getParameter("name");
        System.out.println("name:" + name);
        // 以下为本例代码
        request.setAttribute("result", "hello " + name);
        return "hello";
    }

这种方式是最传统的方式,直接向request域中进行参数的传递,通过setAttribute()方法,来指定key和value,即可在前端页面hello.jsp中直接获取到request域中的内容。如何获取?代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
    <head>
        <title>Hello</title>
    </head>
    <body>
        <h2>${result}</h2>
    </body>
</html>
2. ModelAndView 对象

代码片段:

 public ModelAndView modelAndView(){
		ModelAndView  mv = new ModelAndView();
        // 向request域传值
        mv.addObject("result","Hello spring mvc");
        // 设置视图名称   prefix + viewName + suffix (/jsps/hello.jsp)
        mv.setViewName("hello");
        return mv;

这是SpringMVC独有的ModelAndView对象,通过声明一个ModelAndView类型的对象,就可以使用这个对象来传值或者是指定跳转的页面路径。采用addObject()方法,来规定key和value,即可在前端页面中根据key拿取到对应value的值。通过采用setViewName()方法,来传入一个页面的名称,springmvc底层的视图解析器就会将ModelAndView中的view视图进行前缀和后缀的拼接加工,并给最终的页面跳转路径。当然,这里执行方法的返回类型需要是ModelAndView类型,方法最终需要将mv对象return 。

参数列表中也可以提前声明ModelAndView对象,可直接在方法中使用。如:

 public ModelAndView modelAndView(ModelAndView mv){
        // 向request域传值
        mv.addObject("result","Hello spring mvc");
        // 设置视图名称   prefix + viewName + suffix (/jsps/hello.jsp)
        mv.setViewName("hello");
        return mv;
3. ModelMap 对象
@RequestMapping("/simple")
    public String simple(int id, String name, ModelMap modelMap){
        // modelMap 可以向request域传值【ModelAndView,Request,ModelMap】
        System.out.println("id:" + id);
        System.out.println("name:" + name);
        // 以下为本例的代码 
        modelMap.addAttribute("result", "Hello " + name + "," + id);
        return "hello";
    }

这里的ModelMap对象与request对象相似,可以采用addAttribute()方法来传递参数,向ModelMap对象中添加key和value,其实就是在向request域中添加key和value,只不过ModelMap是又将request进行了一层封装,原因是彻底与Servlet的内容分离,仅用SpringMVC的对象,就可以完成对request域的赋值。

4. Model 对象
@RequestMapping("/bean")
    public String testBean(User user, Model model){
        System.out.println(user);
        // 使用Model对象向request域传值
        model.addAttribute("result", "hello " + user.getName());
        return "hello";
    }

Model对象与ModelMap对象类型。

5. Map 集合
	@PostMapping("/array")
    public String array(String[] hobby, Map<String, String> map){
       for(String hobbyStr : hobby){
           System.out.println(hobbyStr);
       }

       //使用 java.util.Map 向request域传值
        map.put("result","测试数组传参");

       return "hello";
    }

在执行方法的参数列表中,声明一个Map集合,并向其中put()仅key和value,就可以被springmvc解析成向request域中传递值。底层就是使用request.setAttribute()在赋值。而我们无需引入request对象,仅仅使用一个简单的map集合,就可以完成对request对象的操作。彻底与Servlet解耦。

  • 22
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值