zoukankan      html  css  js  c++  java
  • 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";
        }
    }
    
    作者: 唐浩荣
    本文版权归作者和博客园共有,欢迎转载,但是转载需在博客的合适位置给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    外校培训前三节课知识集合纲要(我才不会告诉你我前两节只是单纯的忘了)
    floyd算法----牛栏
    bfs开始--马的遍历
    (DP 线性DP 递推) leetcode 64. Minimum Path Sum
    (DP 线性DP 递推) leetcode 63. Unique Paths II
    (DP 线性DP 递推) leetcode 62. Unique Paths
    (DP 背包) leetcode 198. House Robber
    (贪心 复习) leetcode 1007. Minimum Domino Rotations For Equal Row
    (贪心) leetcode 452. Minimum Number of Arrows to Burst Balloons
    (字符串 栈) leetcode 921. Minimum Add to Make Parentheses Valid
  • 原文地址:https://www.cnblogs.com/tanghaorong/p/14508131.html
Copyright © 2011-2022 走看看