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";
        }
    }
    
    作者: 唐浩荣
    本文版权归作者和博客园共有,欢迎转载,但是转载需在博客的合适位置给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    square(正方形)
    敌兵布阵
    Addition Chains(加法链)
    贪心算法理论
    难题,未解决
    Linux上vi(vim)编辑器使用教程
    linux下md5sum的使用
    Java读取csv文件
    S2JDBCタイプセーフAPI
    S2JDBCチュートリアル
  • 原文地址:https://www.cnblogs.com/tanghaorong/p/14508131.html
Copyright © 2011-2022 走看看