Hey, Nice to meet You. 

必有过人之节.人情有所不能忍者,匹夫见辱,拔剑而起,挺身而斗,此不足为勇也,天下有大勇者,猝然临之而不惊,无故加之而不怒.此其所挟持者甚大,而其志甚远也.          ☆☆☆所谓豪杰之士,

SpringMVC入门学习(三)----SpringMVC绑定参数(普通类型和POJO类型)

1、参数绑定综述

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

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

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

  1. HttpServletRequest可以通过request对象获取请求信息。
  2. HttpServletResponse可以通过response对象处理响应信息。
  3. HttpSession可以通过session对象得到session中存放的对象。
  4. Model是一个接口,ModelMap是一个接口实现,它的作用就是将Model数据填充到request域,跟ModelAndView类似(ModelAndView表示封装了Model和View的对象,推荐使用它)。

在参数绑定过程中,如果遇到上面类型就直接进行绑定。也就是说,我们可以在Controller的方法的形参中直接定义上面这些类型的参数,然后SpringMVC会自动绑定。

注意:从前端发送过来的请求参数都是String类型的,所以SpringMVC还提供了一些默认的格式转换器,这些格式转换器会自动根据数据类型进行类型转换。比如age会自动由字符串转换成了int类型。

2、简单类型参数绑定

对于简单类型的参数,这些类型是直接在Controller类的方法中定义,当用户发送请求后,Spring MVC在处理key/value信息时,就会以key名寻找Controller类的方法中具有相同名称的形参并进行绑定,例如下面的例子,从前台页面提交图书的信息,然后在后台打印传来的数据。具体Controller代码如下:

注意:Controller中的形参需要与前台提交的name属性一样才能完成绑定,如果请求中不包含其中的某个形参,此时是不会报错的,默认使用该参数时要进行空校验。

[1]、创建用于处理前台请求的Controller处理器:

//@Controller:表示一个Controller实例,该实例由Spring容器管理
@Controller
public class BookController {
    //配置请求的地址
    @RequestMapping(value = "book", method = RequestMethod.POST)
    public String getInfo(Integer id, String name, String publisher) {
        System.out.println("获取到的数据为:ID--" + id + ",名称--" + name + ",出版社--" + publisher);
        //成功后跳转的页面
        return "success";
    }
}

[2]、编写用于提交图书信息的页面(index.jsp):

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>首页</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/book" method="post">
    <table>
        <tr>
            <td>图书ID:</td>
            <td><input type="text" name="id"></td>
        </tr>
        <tr>
            <td>图书名称:</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>出版社:</td>
            <td><input type="text" name="publisher"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="提交">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

[3]、然后启动Tomcat进行测试:

image

image

3、单一POJO类型绑定

上面简单参数类型绑定都是需要在Controller中编写一个个的形参才能完成绑定,但是我们在实际开发中一般不这么干,因为有可能前台提交的数据项很多而且复杂,如果这样写就要在Controller中编写大量形参来接收,极大的降低了开发效率,平时一般都会使用POJO类型来绑定数据。

[1]、创建一个Book实体类:

public class Book {
    //书的ID
    private Integer id;
    //书名
    private String name;
    //出版社
    private String publisher;

    //getter,setter和toString省略
}

[2]、将上面Controller代码中接收的参数修改为一个pojo类型,如下所示:

//@Controller:表示一个Controller实例,该实例由Spring容器管理
@Controller
public class BookController {
    //配置请求的地址
    @RequestMapping(value = "book", method = RequestMethod.POST)
    public String getInfo(Book book) {
        System.out.println("获取到的数据为:ID--" + book.getId()
                + ",名称--" + book.getName()
                + ",出版社--" + book.getPublisher());
        //成功后跳转的页面
        return "success";
    }
}

实现的效果和上面简单参数类型一模一样,但是一定要注意:前端提交的name属性必须与POJO里面的属性一致,这样SpringMVC才会自动帮我们绑定数据,否则会绑定失败!!!

4、嵌套POJO类型绑定

嵌套POJO类型就是在一个Java实体类中包含了其它的实体类,此时Spring MVC依然可以解析并成功绑定该类型的包装类。

[1]、首先创建一个用于嵌套的Author类,表示图书的作者信息,新建的Author类如下:

/**
 * Author实体
 */
public class Author {
    private String name;//作者名称
    private String age;//作者年龄

    //getter,setter和toString省略
}

[2]、创建Book类,里面添加了一个嵌套的pojo类型属性author:

public class Book {
    //书的ID
    private Integer id;
    //书名
    private String name;
    //出版社
    private String publisher;
    //图书作者
    private Author author;

    //getter,setter和toString省略
}

[3]、Controller类:当前端页面发出请求后,处理器适配器会解析这种格式的name,将该参数当做POJO类的成员参数绑定起来,作为Controller方法的形参。这样在Controller方法中就可以通过POJO类获取其POJO类的其他类的对象。

//@Controller:表示一个Controller实例,该实例由Spring容器管理
@Controller
public class BookController {
    //配置请求的地址
    @RequestMapping(value = "book", method = RequestMethod.POST)
    public String getInfo(Book book) {
        System.out.println("获取到的数据为:ID--" + book.getId()
                + ",名称--" + book.getName()
                + ",出版社--" + book.getPublisher()
                + ",作者信息--" + book.getAuthor());
        //成功后跳转的页面
        return "success";
    }
}

[4]、提交图书信息的页面(index.jsp)。注意:由于Book类包含了Author类,将其作为其属性,那么在进行提交的时候,就必须在input的name属性指定为嵌套对象.属性的形式。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>首页</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/book" method="post">
    <table>
        <tr>
            <td>图书ID:</td>
            <td><input type="text" name="id"></td>
        </tr>
        <tr>
            <td>图书名称:</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>出版社:</td>
            <td><input type="text" name="publisher"></td>
        </tr>
        <tr>
            <td>作者名称:</td>
            <td><input type="text" name="author.name"></td>
        </tr>
        <tr>
            <td>作者年龄:</td>
            <td><input type="text" name="author.age"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="提交">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

[5]、再次将项目部署到Tomcat上后,测试的结果如下所示:

image

image

5、补充:@RequestMapping

@RequestMapping注解是用来映射请求,也就是通过它来指定控制器可以处理哪些URL请求。这个注解的使用非常简单,可以在类和方法上使用。

  • 用于方法上,表示映射当前Handler中的方法。
  • 用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

[1]、只用在方法上

@Controller
public class HelloController {

    //当请求地址为 /show 的时候,这个方法会被执行
    @RequestMapping(value = "/show")
    public String show1(){
        return "success";
    }

    //请求为 /show1 或者 /show2 都可以访问到该方法
    @RequestMapping(value = {"/show1","/show2"})
    public String show2(){
        return "success";
    }
}

[2]、用在类上

在我们实际的项目中,可能有很多的接口,例如用户、订单、商品等等,为了更好的区分它们,一般用户的请求都是/user/xxx格式的,订单相关的请求都是 /order/xxx 格式的,所以为了方便处理,这里的前缀(就是 /order、/user)可以统一在 Controller 上面处理。

@Controller
@RequestMapping(value = "/user")
public class HelloController {
    
    @RequestMapping(value = "/show")
    public String show1(){
        return "success";
    }
}

当类上加了 @RequestMapping 注解之后,此时,要想访问到 /show,地址就应该用 /user/show 来访问了。

[3]、请求方法限定

@RequestMapping 中的 method 属性主要用来定义接收浏览器发来的何种请求。在Spring中,使用枚举类RequestMethod来定义浏览器请求的方式。

@Controller
@RequestMapping(value = "/user")
public class HelloController {

    //表示该方法只能被 GET 请求访问
    @RequestMapping(value = "/show1",method = RequestMethod.GET)
    public String show1(){
        return "success";
    }
    //表示该方法只能被 POST 请求访问
    @RequestMapping(value = "/show2",method = RequestMethod.POST)
    public String show2(){
        return "success";
    }
    //表示该方法将同时接收通过 GET 和 POST 方式发来的请求
    @RequestMapping(value = "/show3",method = {RequestMethod.GET,RequestMethod.POST})
    public String show3(){
        return "success";
    }
}

注:如果你强行用POST请求来访问GET请求的话,或报405的错误!

[4]、带占位符的URL

这个功能是Spring 3.0 新增的功能,占位符使用{}括起来,可以通过 @PathVariable 将 URL 中的占位符绑定到控制器的处理方法的参数中。带占位符的URL示例:

@Controller
@RequestMapping(path = "/user")
public class UserController {
        
	@RequestMapping(value="/{id}", method=RequestMethod.GET)
	public String show(@PathVariable("id") Integer id) {
		return "success";
	}
}

在这个控制器中 show() 方法将可以接收 user/1、user/2、user/3等等的路径请求,请求的方法必须为GET,使用 @PathVariable 为应用实现 REST 规范提供了具大的便利条件。

6、补充:@RequestParam

@RequestParam用于将请求参数区域的数据映射到Handler方法的参数上。使用场景:例如在上面在绑定数据时,绑定的规则是:表单中name属性的值要和Handler方法中形参的值相对应,这样才能将数据绑定成功,否则服务端接收不到前端传来的数据。有时有一些特殊情况,前端的name属性值与后端Handler方法中的形参不一致,这个时候就可以通过 @RequestParam 注解来解决。

语法:@RequestParam(value=”参数名”,required=”true|false”,defaultValue=””)

  • value:请求中传入参数的名称。
  • required:该参数是否为必传项,默认为true,表示该请求路径中必须包含该参数,如果不包含就报错。
  • defaultValue:默认参数值,如果设置了该值,required=true将失效,自动为false,如果没有传该参数,就使用默认值。

@RequestParam注解的简单举例:

<!-- 表单数据,这里的name属性值为name。 -->
<input type="text" name="name">
/**
 * -@RequestParam的使用
 */
@Controller
@RequestMapping("hello")
public class HelloController {
    //表示将请求路径中参数名称为name映射为userName,相当于重命名一样
    @RequestMapping("one")
    public String show1(@RequestParam("name") String userName) {
        System.out.println(userName);
        return "success";
    }
    //表示请求路径中不一定要包含名称为name的参数
    @RequestMapping("two")
    public String show2(@RequestParam(value = "name", required = false) String userName) {
        System.out.println(userName);
        return "success";
    }
    //表示请求路径中必须包含名称为name的参数,如果name参数的值为空,则使用默认的值"hello"
    @RequestMapping("three")
    public String show3(@RequestParam(value = "name" ,required=true, defaultValue = "hello") String userName) {
        System.out.println(userName);
        return "success";
    }
}
posted @ 2021-05-13 08:03  唐浩荣  阅读(1644)  评论(0编辑  收藏  举报