`
一顿饺子
  • 浏览: 51702 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring Controllor处理方法入参如何绑定 URL 参数

阅读更多
Controller 的方法标注了 @RequestMapping 注解后,它就能处理特定的 URL 请求。我们不禁要问:请求处理方法入参是如何绑定 URL 参数的呢?在回答这个问题之前先来看下面的代码:

按参数名匹配进行绑定

               
    @RequestMapping(params = "method=listBoardTopic")
    //<—— ① topicId入参是如何绑定URL请求参数的?
    public String listBoardTopic(int topicId) {
        bbtForumService.getBoardTopics(topicId);
        System.out.println("call listBoardTopic method.");
        return "listTopic";
    }

当我们发送 http://localhost//bbtForum.do?method=listBoardTopic&topicId=10 的 URL 请求时,Spring 不但让 listBoardTopic() 方法处理这个请求,而且还将 topicId 请求参数在类型转换后绑定到 listBoardTopic() 方法的 topicId 入参上。而 listBoardTopic() 方法的返回类型是 String,它将被解析为逻辑视图的名称。也就是说 Spring 在如何给处理方法入参自动赋值以及如何将处理方法返回值转化为 ModelAndView 中的过程中存在一套潜在的规则,不熟悉这个规则就不可能很好地开发基于注解的请求处理方法,因此了解这个潜在规则无疑成为理解 Spring MVC 框架基于注解功能的核心问题。

我们不妨从最常见的开始说起:请求处理方法入参的类型可以是 Java 基本数据类型或 String 类型,这时方法入参按参数名匹配的原则绑定到 URL 请求参数,同时还自动完成 String 类型的 URL 请求参数到请求处理方法参数类型的转换。下面给出几个例子:

listBoardTopic(int topicId):和 topicId URL 请求参数绑定;
listBoardTopic(int topicId,String boardName):分别和 topicId、boardName URL 请求参数绑定;

特别的,如果入参是基本数据类型(如 int、long、float 等),URL 请求参数中一定要有对应的参数,否则将抛出 TypeMismatchException 异常,提示无法将 null 转换为基本数据类型。

另外,请求处理方法的入参也可以一个 JavaBean,如下面的 User 对象就可以作为一个入参:


User.java:一个 JavaBean
               
package com.baobaotao.web;

public class User {
    private int userId;
    private String userName;
    //省略get/setter方法
    public String toString(){
        return this.userName +","+this.userId;
    }
}



下面是将 User 作为 listBoardTopic() 请求处理方法的入参:


使用 JavaBean 作为请求处理方法的入参
               
    @RequestMapping(params = "method=listBoardTopic")
    public String listBoardTopic(int topicId,User user) {
        bbtForumService.getBoardTopics(topicId);
        System.out.println("topicId:"+topicId);
        System.out.println("user:"+user);
        System.out.println("call listBoardTopic method.");
        return "listTopic";
    }



这时,如果我们使用以下的 URL 请求:http://localhost/bbtForum.do?method=listBoardTopic&topicId=1&userId=10&userName=tom

topicId URL 参数将绑定到 topicId 入参上,而 userId 和 userName URL 参数将绑定到 user 对象的 userId 和 userName 属性中。和 URL 请求中不允许没有 topicId 参数不同,虽然 User 的 userId 属性的类型是基本数据类型,但如果 URL 中不存在 userId 参数,Spring 也不会报错,此时 user.userId 值为 0。如果 User 对象拥有一个 dept.deptId 的级联属性,那么它将和 dept.deptId URL 参数绑定。

通过注解指定绑定的 URL 参数

如果我们想改变这种默认的按名称匹配的策略,比如让 listBoardTopic(int topicId,User user) 中的 topicId 绑定到 id 这个 URL 参数,那么可以通过对入参使用 @RequestParam 注解来达到目的:

通过 @RequestParam 注解指定

               
package com.baobaotao.web;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;



@Controller
@RequestMapping("/bbtForum.do")
public class BbtForumController {

    @RequestMapping(params = "method=listBoardTopic")
    public String listBoardTopic(@RequestParam("id") int topicId,User user) {
        bbtForumService.getBoardTopics(topicId);
        System.out.println("topicId:"+topicId);
        System.out.println("user:"+user);
        System.out.println("call listBoardTopic method.");
        return "listTopic";
    }

}



这里,对 listBoardTopic() 请求处理方法的 topicId 入参标注了 @RequestParam("id") 注解,所以它将和 id 的 URL 参数绑定。

绑定模型对象中某个属性

Spring 2.0 定义了一个 org.springframework.ui.ModelMap 类,它作为通用的模型数据承载对象,传递数据供视图所用。我们可以在请求处理方法中声明一个 ModelMap 类型的入参,Spring 会将本次请求模型对象引用通过该入参传递进来,这样就可以在请求处理方法内部访问模型对象了。来看下面的例子:


使用 ModelMap 访问请示对应的隐含模型对象
               
@RequestMapping(params = "method=listBoardTopic")
public String listBoardTopic(@RequestParam("id")int topicId,
User user,ModelMap model) {
     bbtForumService.getBoardTopics(topicId);
     System.out.println("topicId:" + topicId);
     System.out.println("user:" + user);
     //① 将user对象以currUser为键放入到model中
     model.addAttribute("currUser",user);
     return "listTopic";
}



对于当次请求所对应的模型对象来说,其所有属性都将存放到 request 的属性列表中。象上面的例子,ModelMap 中的 currUser 属性将放到 request 的属性列表中,所以可以在 JSP 视图页面中通过 request.getAttribute(“currUser”) 或者通过 ${currUser} EL 表达式访问模型对象中的 user 对象。从这个角度上看, ModelMap 相当于是一个向 request 属性列表中添加对象的一条管道,借由 ModelMap 对象的支持,我们可以在一个不依赖 Servlet API 的 Controller 中向 request 中添加属性。

在默认情况下,ModelMap 中的属性作用域是 request 级别是,也就是说,当本次请求结束后,ModelMap 中的属性将销毁。如果希望在多个请求中共享 ModelMap 中的属性,必须将其属性转存到 session 中,这样 ModelMap 的属性才可以被跨请求访问。

Spring 允许我们有选择地指定 ModelMap 中的哪些属性需要转存到 session 中,以便下一个请求属对应的 ModelMap 的属性列表中还能访问到这些属性。这一功能是通过类定义处标注 @SessionAttributes 注解来实现的。请看下面的代码:

使模型对象的特定属性具有 Session 范围的作用域
               
package com.baobaotao.web;


import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.SessionAttributes;

@Controller
@RequestMapping("/bbtForum.do")
@SessionAttributes("currUser") //①将ModelMap中属性名为currUser的属性
//放到Session属性列表中,以便这个属性可以跨请求访问
public class BbtForumController {

    @RequestMapping(params = "method=listBoardTopic")
    public String listBoardTopic(@RequestParam("id")int topicId, User user,
ModelMap model) {
        bbtForumService.getBoardTopics(topicId);
        System.out.println("topicId:" + topicId);
        System.out.println("user:" + user);
        model.addAttribute("currUser",user); //②向ModelMap中添加一个属性
        return "listTopic";
    }

}



我们在 ② 处添加了一个 ModelMap 属性,其属性名为 currUser,而 ① 处通过 @SessionAttributes 注解将 ModelMap 中名为 currUser 的属性放置到 Session 中,所以我们不但可以在 listBoardTopic() 请求所对应的 JSP 视图页面中通过 request.getAttribute(“currUser”) 和 session.getAttribute(“currUser”) 获取 user 对象,还可以在下一个请求所对应的 JSP 视图页面中通过 session.getAttribute(“currUser”) 或 ModelMap#get(“currUser”) 访问到这个属性。

这里我们仅将一个 ModelMap 的属性放入 Session 中,其实 @SessionAttributes 允许指定多个属性。你可以通过字符串数组的方式指定多个属性,如 @SessionAttributes({“attr1”,”attr2”})。此外,@SessionAttributes 还可以通过属性类型指定要 session 化的 ModelMap 属性,如 @SessionAttributes(types = User.class),当然也可以指定多个类,如 @SessionAttributes(types = {User.class,Dept.class}),还可以联合使用属性名和属性类型指定:@SessionAttributes(types = {User.class,Dept.class},value={“attr1”,”attr2”})。

上面讲述了如何往ModelMap中放置属性以及如何使ModelMap中的属性拥有Session域的作用范围。除了在JSP视图页面中通过传统的方法访问ModelMap中的属性外,读者朋友可能会问:是否可以将ModelMap中的属性绑定到请求处理方法的入参中呢?答案是肯定的。Spring为此提供了一个@ModelAttribute的注解,下面是使用@ModelAttribute注解的例子:

使模型对象的特定属性具有 Session 范围的作用域

               
package com.baobaotao.web;

import com.baobaotao.service.BbtForumService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.annotation.ModelAttribute;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Controller
@RequestMapping("/bbtForum.do")
@SessionAttributes("currUser") //①让ModelMap的currUser属性拥有session级作用域
public class BbtForumController {

    @Autowired
private BbtForumService bbtForumService;

    @RequestMapping(params = "method=listBoardTopic")
    public String listBoardTopic(@RequestParam("id")int topicId, User user,
ModelMap model) {
        bbtForumService.getBoardTopics(topicId);
        System.out.println("topicId:" + topicId);
        System.out.println("user:" + user);
        model.addAttribute("currUser",user); //②向ModelMap中添加一个属性
        return "listTopic";
    }


    @RequestMapping(params = "method=listAllBoard")
   //③将ModelMap中的
public String listAllBoard(@ModelAttribute("currUser") User user) {
//currUser属性绑定到user入参中。
        bbtForumService.getAllBoard();
        System.out.println("user:"+user);
        return "listBoard";
    }
}



在 ② 处,我们向 ModelMap 中添加一个名为 currUser 的属性,而 ① 外的注解使这个 currUser 属性拥有了 session 级的作用域。所以,我们可以在 ③ 处通过 @ModelAttribute 注解将 ModelMap 中的 currUser 属性绑定以请求处理方法的 user 入参中。

所以当我们先调用以下 URL 请求: http://localhost/bbtForum.do?method=listBoardTopic&id=1&userName=tom&dept.deptId=12

以执行listBoardTopic()请求处理方法,然后再访问以下URL: http://localhost/sample/bbtForum.do?method=listAllBoard

你将可以看到 listAllBoard() 的 user 入参已经成功绑定到 listBoardTopic() 中注册的 session 级的 currUser 属性上了
分享到:
评论

相关推荐

    spring mvc3.2.3+ myibatis3.2.2

    分 dao service pojo mapper controllor等层,有敢于网上下载多不适用,故作一层次分明功能较全面(列表,登录验证,增加)的功能验证性web程序以为分享,因程序为功能验证性程序,故页面之间没有全套连接,可自行...

    MALA雷达数据处理软件_软件

    MALA雷达可以对2D,3D数据进行分析、处理

    Cypress USB controllor API doucment

    CyAPI.lib provides a simple, powerful C++ programming interface to USB devices. More specifically, it is a C++ class library that provides a high-level programming interface to the CyUsb3.sys device ...

    05-vSwitch Controller用户指南.pdf

    - 在Citrix XenServer环境中,vSwitch负责处理虚拟机之间的网络流量,并确保它们能够与外部网络进行通信。 - **Controller的角色:** - vSwitch Controller是管理vSwitch配置和策略的核心组件。 - 它为用户提供...

    meiyun[spring mvc]

    本资源为纯spring mvc web简易程序,实现增加 列表 登录验证等相关功能,包分层为 dao service pojo controllor,层次分明,较大多网上下载代码简洁明了,有感于网上当下来的多不实在,故此分享,里面多是验证性的...

    Unity3D 角色控制器CharacterController

    5. **Move()** 方法:这是CharacterController的核心方法,用于控制角色的移动。它接受一个三维向量参数,代表世界空间中的移动距离。在Update()函数中调用此方法,可以实现角色的平滑移动。 6. **Simple Move()** ...

    QTableViewDemo1.zip

    V(view) 是指 QTableView 视图,要来显示数据模型,C(controllor) 控制在 Qt 中被弱化,与 View 合并到一起。 使用时需要包含#include 和#include ,创建一个QTableView对象和QStandardItemModel并使用QTableView的...

    mvc,mvp框架

    mvc、mvp及mvvm设计模式初步调查,View::对应于xml布局文件 Model:实体模型 Controllor:对应于Activity业务逻辑,数据处理和UI处理

    CP210x USB串口驱动

    - 提供配置工具,允许用户调整波特率、数据位、停止位、校验位等串口参数。 - 支持中断传输,提高实时数据处理能力。 - 兼容各种编程语言的串口通信库,如Python的pySerial库、C#的SerialPort类等。 对于开发者而言...

    基于TCP_IP协议的单片机与Internet互联的研究与实现

    嵌入式TCP/P协议栈主要是为了解决低端MCU(Micro Controllor Unit,微控制器)与Internet互联的问题,它极大地扩展了嵌入式系统的应用范围。本文在分析了嵌入式系统、嵌入式Intemet的研究背景、国内外发展动态、研究...

    cp2101驱动程序.rar

    软件介绍: VCOMM--CP210x USB to UART Bridge Controller Driver Set me500可以将电脑的端USB口虚拟为COM端口来达到扩展的目的,不需修改现有的软件及硬件就能够通过USB...解压后打开PreInstaller.exe安装。

    Generate-Controller-GC:用于生成完整控制器 Grocery CRUD 的 Codeigniter 库

    #Generate Controller GC ###Generate Controller GC 是一个 Codeigniter 库,用于为 CodeIgniter 2.x 生成完整的控制器 Grocery CRUD。 ##Description 该库允许快速轻松地生成 CRUD 控制器 Grocery。...

    earn-big-money#Dashboard#后端代码目录1

    后端源码目录以及说明项目代码代码说明bin: 执行程序controllor: 控制器目录DBController_public.js:数据库接口userSyst

    HP-iLO:iLO 4 HP ProLiant

    惠普iLO iLO 4 HP ProLiant { "in_post": 0, "log_drive_arrays": [ { "status": "OP_STATUS_DEGRADED", "encr_self_stat": "OP_STATUS_OK", "name": "Controller on System Board", "has_accel": 1, ...

    cdap:用于构建数据分析应用程序的开源框架

    介绍 CDAP是针对Hadoop生态系统的集成式开源应用程序开发平台,可为开发人员提供数据和应用程序抽象,以简化和加速应用程序开发,解决更广泛的实时和批处理用例,并在满足企业需求的同时将应用程序部署到生产环境中...

    重庆联通客户应用视频

    作为亚洲首个将IBM SVC(SAN Volume Controllor)安装在DS8000系统上的客户和大中华区电信行业第一个使用虚拟存储技术的客户,重庆联通完成了对多品牌存储平台进行管理,使得互操作性和数据管理轻而易举。

    ofswitch13:OFSwitch13-用于ns-3的OpenFlow 1.3模块

    用于ns-3的OpenFlow 1.3模块 这是OFSwitch13模块,它通过功能增强了,从而使ns-3用户可以模拟软件定义的网络(SDN)。 实际上,此模块实现了用于将ns-3模拟器互连到 (ofsoftswitch13)库的的接口。...

    个人小结-cylong1

    接下来,陈云龙在Controllor层、Model层和部分View层的代码编写中扮演了核心角色。在MVC(Model-View-Controller)架构中,Controller层是应用程序的中枢,负责处理用户输入并协调Model和View之间的交互。Model层则...

    mvp+rxjava+Retrofit.zip

    其实Android本身就采用的是MVC(Model View Controllor)模式、其中Model指的是数据逻辑和实体模型;View指的是布局文件、Controllor指的是Activity。对于很多Android初学者可能会有这样的经历,写代码的时候,不管...

Global site tag (gtag.js) - Google Analytics