• SpringMVC学习系列(5) 之 数据绑定-2


    在系列(4)中我们介绍了如何用@RequestParam来绑定数据,下面我们来看一下其它几个数据绑定注解的使用方法。

    1.@PathVariable 用来绑定URL模板变量值,这个我们已经在系列(3)中介绍了使用方法,这里不在赘述。

    2.@CookieValue 用来绑定Cookie中的数据。下面我们用获取Cookie中的sessionId做测试:

    在DataBindController添加cookiebind action,代码如下:

    //@CookieValue Test
    @RequestMapping(value="/cookiebind", method = {RequestMethod.GET})
    public String cookieBind(HttpServletRequest request, Model model, @CookieValue(value="JSESSIONID", defaultValue="") String jsessionId){
        
        model.addAttribute("jsessionId", jsessionId);
        return "cookiebindresult";
    }

    在views文件夹中添加一个cookiebindresult.jsp视图,代码如下:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!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>Insert title here</title>
    </head>
    <body>
        ${jsessionId}
    </body>
    </html>

    运行测试:

    1

    可以看到已经获取到了sessionId。

    注:@CookieValue 与@RequestParam 一样也有3个参数,其含义与的@RequestParam 参数含义相同。

    3.@RequestHeader 用来绑定请求头中的数据,我们用@RequestHeader获取User-Agent 来做演示:

    在DataBindController添加requestheaderbind action,代码如下:

    //@RequestHeader Test
    @RequestMapping(value="/requestheaderbind", method = {RequestMethod.GET})
    public String requestHeaderBind(HttpServletRequest request, Model model, @RequestHeader(value="User-Agent", defaultValue="") String userAgent){
        
        model.addAttribute("userAgent", userAgent);
        return "requestheaderbindresult";
    }

    在views文件夹中添加一个requestheaderbindresult.jsp视图,代码如下:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!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>Insert title here</title>
    </head>
    <body>
        ${userAgent}
    </body>
    </html>

    运行测试:

    2

    可以看到已经获取到了User-Agent 。

    注:@RequestHeader 与@RequestParam 一样也有3个参数,其含义与的@RequestParam 参数含义相同。

    4.@ModelAttribute 绑定数据到模型中。在系列(4)的modelAutoBind action中我们将表单提交的数据添加到Model中的代码如下:

    @RequestMapping(value="/modelautobind", method = {RequestMethod.POST})
    public String modelAutoBind(HttpServletRequest request, Model model, AccountModel accountModel){
        
        model.addAttribute("accountmodel", accountModel);
        return "modelautobindresult";
    }

    而借助于@ModelAttribute 我们可以更简单的讲数据添加到Model中,把上面的代码修改为:

    @RequestMapping(value="/modelautobind", method = {RequestMethod.POST})
    public String modelAutoBind(HttpServletRequest request, @ModelAttribute("accountmodel") AccountModel accountModel){
        
        return "modelautobindresult";
    }

    运行测试:

    3

    可以看到依然成功的绑定了提交的数据。

    5.Model中的数据作用域是Request级别的,也就是说在一个Request请求中是获取不到其它Request请求的Model的数据的。但我们可以用@SessionAttributes 把数据存储到session中,来保持多次请求间数据,这样就可以来实现比如分步骤提交表单等需求。下面我们来看如何分2步把数据绑定到AccountModel中:

    在DataBindController上添加:

    @SessionAttributes(value = "sessionaccountmodel")

    在DataBindController添加usernamebind和passwordbind action,代码如下:

    //@SessionAttributes Test
    @ModelAttribute("sessionaccountmodel")
    public AccountModel initAccountModel(){
        
        return new AccountModel();
    }
    
    @RequestMapping(value="/usernamebind", method = {RequestMethod.GET})
    public String userNameBind( Model model, AccountModel accountModel){
        
        model.addAttribute("sessionaccountmodel", new AccountModel());
        return "usernamebind";
    }
    
    @RequestMapping(value="/usernamebind", method = {RequestMethod.POST})
    public String userNameBindPost( @ModelAttribute("sessionaccountmodel") AccountModel accountModel){
        
        //重定向到密码绑定测试
        return "redirect:passwordbind";
    }
    
    @RequestMapping(value="/passwordbind", method = {RequestMethod.GET})
    public String passwordBind(@ModelAttribute("sessionaccountmodel") AccountModel accountModel){
        
        return "passwordbind";
    }
    
    @RequestMapping(value="/passwordbind", method = {RequestMethod.POST})
    public String passwordBindPost(@ModelAttribute("sessionaccountmodel") AccountModel accountModel, SessionStatus status){
        
        //销毁@SessionAttributes存储的对象
        status.setComplete();
        //显示绑定结果
        return "sessionmodelbindresult";
    }

    由于我们在controller上指定了@SessionAttributes,所以在@ModelAttribute(“xxx”)注解的参数会直接在@SessionAttributes中查找名为”xxx”的对象,如果没有找到则调用@ModelAttribute(“xxx”)注解的方法返回对象并存入@SessionAttributes(如果没有找到且没有@ModelAttribute(“xxx”)注解的方法就会抛出HttpSessionRequiredException)。当执行到最后一步就可以调用SessionStatus .setComplete()方法把@SessionAttributes中保存对象销毁了(不会清除HttpSession中的数据)。

    在views文件夹中添加usernamebind.jsp、passwordbind.jsp和sessionmodelbindresult.jsp视图内容分别如下:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <form:form modelAttribute="sessionaccountmodel" method="post">     
            用户名:<form:input path="username"/><br/>
            <input type="submit" value="Submit" />
        </form:form>  
    </body>
    </html>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <form:form modelAttribute="sessionaccountmodel" method="post">     
            密 码:<form:password path="password"/><br/>
            <input type="submit" value="Submit" />
        </form:form>  
    </body>
    </html>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!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>Insert title here</title>
    </head>
    <body>
        用户名:${sessionaccountmodel.username}<br/>
        密 码:${sessionaccountmodel.password}
    </body>
    </html>

    运行测试:

    4

    5

    6

    可以看到我们已经成功的分2步把数据绑定到AccountModel中了。

    注:

    @SessionAttributes有value和types两个参数其中value指明要对象的名称,types指定要绑定对象的类型,如@SessionAttributes(value = "sessionaccountmodel", types=AccountModel.class)两者是and关系,需要同时满足。也可以同时指定多个value和types 如:@SessionAttributes(value = {"aa", "aa"} , types={XXX.class, YYY.class}) 。

    6.@RequestBody 调用合适的MessageConvert来把非application/x-www-form-urlencoded请求中的内容转换为指定的对象它通常与@ResponseBody合用,@ResponseBody与.@RequestBody刚好相反,他把指定的对象转换为合适的内容(请求头为Accept:application/json 则返回json数据)并返回。这里我们用一个ajax请求做演示:

    由于Spring默认解析json用的是Jackson,所以我们这里要把jackson-core-asl-1.9.13.jar和jackson-mapper-asl-1.9.13.jar两个包添加到我们项目。

    修改AccountModel让其继承Serializable接口,并添加一个空的构造函数(为了Jackson做转换)。

    在DataBindController添加requestBodyBindaction,代码如下:

    //@RequestBody Test
    @RequestMapping(value="/requestbodybind", method = {RequestMethod.GET})
    public String requestBodyBind(Model model){
        
        model.addAttribute("accountmodel", new AccountModel());
        return "requestbodybind";
    }
    
    @RequestMapping(value="/requestbodybind", method = {RequestMethod.POST})
    public @ResponseBody AccountModel requestBodyBind(@RequestBody AccountModel accountModel){
                
        return accountModel;
    }

    在views文件夹中添加requestbodybind.jsp视图内容如下:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    
    <html>
    <head>
    
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <form:form modelAttribute="accountmodel" method="post">     
            用户名:<form:input path="username"/><br/>
            密 码:<form:password path="password"/><br/>
            <input type="button" id="submit" value="Submit" />
        </form:form> 
        
        <script type="text/javascript">
            $(function() { 
                $("#submit").click(function() {   
                    var postdata = '{"username":"' + $('#username').val() + '","password":"' + $('#password').val() + '"}';   
                    $.ajax({  
                        type : 'POST',  
                        contentType : 'application/json',  
                        url : 'http://localhost:8080/SpringMVCLesson/databind/requestbodybind',  
                        processData : false,  
                        dataType : 'json',  
                        data : postdata,  
                        success : function(data) {  
                            alert('username : '+data.username+'
    password : '+data.password);  
                        },  
                        error : function() {  
                            alert('error...');  
                        }  
                    }); 
                });
            });
        </script> 
    </body>
    </html>

    运行测试:

    7

    结果正确,证明转换成功。

    7.@RequestPart 绑定“multipart/form-data“类型数据,支持javax.servlet.http.Part文件上传,并可可以进行类型转换,详见官方文档:

    http://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/htmlsingle/#new-in-3.1-mvc-requestpart

    代码下载:http://pan.baidu.com/s/1hqqVLTa 

    数据绑定部分的内容到此结束。

    注: 之前没注意前11篇的示例代码,不知道为什么当时打包上传上去的是没有.project项目文件的,导致下载后不能直接导入eclipse运行,虚拟机又 被我删掉了,这些示例代码也没有备份,但是代码文件还在的,所以可以新建一个Dynamic Web Project把对应的配置文件和controller还有view导入就可以了,给大家造成的不便说声抱歉。

  • 相关阅读:
    面试题58:翻转字符串
    面试题57_2:和为S的连续正数序列
    面试题57:和为S的数字
    面试题56:数组中数字出现的次数
    面试题55_2:平衡二叉树
    面试题54:二叉搜索树的第k大节点
    面试题55_1:二叉树的深度
    tortoisegit 本地创建的分支 push github
    TortoiseGit 拉取分支
    tortoiseGIT 本地分支创建合并
  • 原文地址:https://www.cnblogs.com/liukemng/p/3736948.html
Copyright © 2020-2023  润新知