@RequestParam详解

@RequestParam

主要用于将请求参数区域的数据映射到控制层方法的参数上
在这里插入图片描述

首先我们需要知道@RequestParam注解主要有哪些参数

  1. value:请求中传入参数的名称,如果不设置后台接口的value值,则会默认为该变量名。比如上图中第一个参数如果不设置value=“page”,则前端传入的参数名必须为pageNum,否则在后台接口中pageNum将接收不到对应的数据

  2. required:该参数是否为必传项。默认是true,表示请求中一定要传入对应的参数,否则会报404错误,如果设置为false时,当请求中没有此参数,将会默认为null,而对于基本数据类型的变量,则必须有值,这时会抛出空指针异常。如果允许空值,则接口中变量需要使用包装类来声明。

  3. defaultValue:参数的默认值,如果请求中没有同名的参数时,该变量默认为此值。注意默认值可以使用SpEL表达式,如"#{systemProperties[‘java.vm.version’]}"

如果在请求中传入多个同名参数,比如:url?userName=zhl&userName=holley时怎么办?

其实此时传入的数据格式是:“zhl,holley”,即多个数据之间使用逗号分隔开,在后台接口中可以使用数组或者list类型的变量来接收:

public String requestparam8(@RequestParam(value="userName") String []  userNames) 
或者
public String requestparam8(@RequestParam(value="list") List<String> list) 

@PathVariable绑定uri模板变量值:通过@PathVariable可以绑定占位符参数到方法参数中,例如:

在这里插入图片描述
如果请求为"url/info/16",则spring会自动将16绑定到通过@PathVariable注解的同名变量uid上

@CookieValue绑定Cookie数据值

@CookieValue用于将请求的Cookie数据映射到功能处理方法的参数上。

public String test(@CookieValue(value="JSESSIONID", defaultValue="") String sessionId) 

如上配置将自动将JSESSIONID值入参到sessionId参数上,defaultValue表示Cookie中没有JSESSIONID时默认为空。

public String test2(@CookieValue(value="JSESSIONID", defaultValue="") Cookie sessionId)   

传入参数类型也可以是javax.servlet.http.Cookie类型

测试代码在CookieValueTypeController中。@CookieValue也拥有和@RequestParam相同的三个参数,含义一样。

@RequestHeader绑定请求头数据

@RequestHeader用于将请求的头信息区数据映射到功能处理方法的参数上。

@RequestMapping(value="/header")  
public String test(  @RequestHeader("User-Agent") String userAgent,  @RequestHeader(value="Accept") String[] accepts)

如上配置将自动将请求头“User-Agent”值入参到userAgent参数上,并将“Accept”请求头值入参到accepts参数上。测试代码在HeaderValueTypeController中。

@RequestHeader也拥有和@RequestParam相同的三个参数,含义一样。

@ModelAttribute绑定请求参数到命令对象

@ModelAttribute一个具有如下三个作用:

①绑定请求参数到命令对象:放在功能处理方法的入参上时,用于将多个请求参数绑定到一个命令对象,从而简化绑定流程,而且自动暴露为模型数据用于视图页面展示时使用;

②暴露表单引用对象为模型数据:放在处理器的一般方法(非功能处理方法)上时,是为表单准备要展示的表单引用对象,如注册时需要选择的所在城市等,而且在执行功能处理方法(@RequestMapping注解的方法)之前,自动添加到模型对象中,用于视图页面展示时使用;

③暴露@RequestMapping方法返回值为模型数据:放在功能处理方法的返回值上时,是暴露功能处理方法的返回值为模型数据,用于视图页面展示时使用。

一、绑定请求参数到命令对象

如用户登录,我们需要捕获用户登录的请求参数(用户名、密码)并封装为用户对象,此时我们可以使用@ModelAttribute绑定多个请求参数到我们的命令对象。

public String test1(@ModelAttribute("user") UserModel user) 

它的作用是将该绑定的命令对象以“user”为名称添加到模型对象中供视图页面展示使用。我们此时可以在视图页面使用${user.username}来获取绑定的命令对象的属性。

绑定请求参数到命令对象支持对象图导航式的绑定,如请求参数包含“?username=zhang&password=123&workInfo.city=bj”自动绑定到user中的workInfo属性的city属性中。

@RequestMapping(value="/model2/{username}")  
public String test2(@ModelAttribute("model") DataBinderTestModel model) {   

DataBinderTestModel相关模型请从第三章拷贝过来,请求参数到命令对象的绑定规则详见【4.16.1、数据绑定】一节,URI模板变量也能自动绑定到命令对象中,当你请求的URL中包含“bool=yes&schooInfo.specialty=computer&hobbyList[0]=program&hobbyList[1]=music&map[key1]=value1&map[key2]=value2&state=blocked”会自动绑定到命令对象上。

当URI模板变量和请求参数同名时,URI模板变量具有高优先权。

二、暴露表单引用对象为模型数据

@ModelAttribute("cityList")  
public List<String> cityList() {  return Arrays.asList("北京", "山东");  
} 

如上代码会在执行功能处理方法之前执行,并将其自动添加到模型对象中,在功能处理方法中调用Model 入参的containsAttribute(“cityList”)将会返回true。

@ModelAttribute("user")  //①  
public UserModel getUser(@RequestParam(value="username", defaultValue="") String username) {  
//TODO 去数据库根据用户名查找用户对象  
UserModel user = new UserModel();  
user.setRealname("zhang");  return user;  
}

如你要修改用户资料时一般需要根据用户的编号/用户名查找用户来进行编辑,此时可以通过如上代码查找要编辑的用户。

也可以进行一些默认值的处理。

@RequestMapping(value="/model1") //②  
public String test1(@ModelAttribute("user") UserModel user, Model model)  

此处我们看到①和②有同名的命令对象,那Spring Web MVC内部如何处理的呢:

(1、首先执行@ModelAttribute注解的方法,准备视图展示时所需要的模型数据;@ModelAttribute注解方法形式参数规则和@RequestMapping规则一样,如可以有@RequestParam等;

(2、执行@RequestMapping注解方法,进行模型绑定时首先查找模型数据中是否含有同名对象,如果有直接使用,如果没有通过反射创建一个,因此②处的user将使用①处返回的命令对象。即②处的user等于①处的user。

三、暴露@RequestMapping方法返回值为模型数据

public @ModelAttribute("user2") UserModel test3(@ModelAttribute("user2") UserModel user) 

大家可以看到返回值类型是命令对象类型,而且通过@ModelAttribute(“user2”)注解,此时会暴露返回值到模型数据(名字为user2)中供视图展示使用。那哪个视图应该展示呢?此时Spring Web MVC会根据RequestToViewNameTranslator进行逻辑视图名的翻译.

此时又有问题了,@RequestMapping注解方法的入参user暴露到模型数据中的名字也是user2,其实我们能猜到:

(3、@ModelAttribute注解的返回值会覆盖@RequestMapping注解方法中的@ModelAttribute注解的同名命令对象。

四、匿名绑定命令参数

public String test4(@ModelAttribute UserModel user, Model model)public String test5(UserModel user, Model model)   

此时我们没有为命令对象提供暴露到模型数据中的名字,此时的名字是什么呢?Spring Web MVC自动将简单类名(首字母小写)作为名字暴露,如“cn.javass.chapter6.model.UserModel”暴露的名字为“userModel”。

public @ModelAttribute List<String> test6()public @ModelAttribute List<UserModel> test7()   

对于集合类型(Collection接口的实现者们,包括数组),生成的模型对象属性名为“简单类名(首字母小写)”+“List”,如List生成的模型对象属性名为“stringList”,List生成的模型对象属性名为“userModelList”。

其他情况一律都是使用简单类名(首字母小写)作为模型对象属性名,如Map<String, UserModel>类型的模型对象属性名为“map”。

@SessionAttributes绑定命令对象到session

有时候我们需要在多次请求之间保持数据,一般情况需要我们明确的调用HttpSession的API来存取会话数据,如多步骤提交的表单。Spring Web MVC提供了@SessionAttributes进行请求间透明的存取会话数据。

//1、在控制器类头上添加@SessionAttributes注解  
@SessionAttributes(value = {"user"})    //①  
public class SessionAttributeController   //2、@ModelAttribute注解的方法进行表单引用对象的创建  
@ModelAttribute("user")    //②  
public UserModel initUser()   //3、@RequestMapping注解方法的@ModelAttribute注解的参数进行命令对象的绑定  
@RequestMapping("/session1")   //③  
public String session1(@ModelAttribute("user") UserModel user)  //4、通过SessionStatus的setComplete()方法清除@SessionAttributes指定的会话数据  
@RequestMapping("/session2")   //③  
public String session(@ModelAttribute("user") UserModel user, SessionStatus status) {  if(true) { //④  status.setComplete();  }  return "success";  
}

@SessionAttributes(value = {“user”})含义:

@SessionAttributes(value = {“user”}) 标识将模型数据中的名字为“user” 的对象存储到会话中(默认HttpSession),此处value指定将模型数据中的哪些数据(名字进行匹配)存储到会话中,此外还有一个types属性表示模型数据中的哪些类型的对象存储到会话范围内,如果同时指定value和types属性则那些名字和类型都匹配的对象才能存储到会话范围内。

包含@SessionAttributes的执行流程如下所示:

① 首先根据@SessionAttributes注解信息查找会话内的对象放入到模型数据中;

② 执行@ModelAttribute注解的方法:如果模型数据中包含同名的数据,则不执行@ModelAttribute注解方法进行准备表单引用数据,而是使用①步骤中的会话数据;如果模型数据中不包含同名的数据,执行@ModelAttribute注解的方法并将返回值添加到模型数据中;

③ 执行@RequestMapping方法,绑定@ModelAttribute注解的参数:查找模型数据中是否有@ModelAttribute注解的同名对象,如果有直接使用,否则通过反射创建一个;并将请求参数绑定到该命令对象;

此处需要注意:如果使用@SessionAttributes注解控制器类之后,③步骤一定是从模型对象中取得同名的命令对象,如果模型数据中不存在将抛出HttpSessionRequiredException Expected session attribute ‘user’(Spring3.1)

或HttpSessionRequiredException Session attribute ‘user’ required - not found in session(Spring3.0)异常。

④ 如果会话可以销毁了,如多步骤提交表单的最后一步,此时可以调用SessionStatus对象的setComplete()标识当前会话的@SessionAttributes指定的数据可以清理了,此时当@RequestMapping功能处理方法执行完毕会进行清理会话数据。

我们通过Spring Web MVC的源代码验证一下吧,此处我们分析的是Spring3.1的RequestMappingHandlerAdapter,读者可以自行验证Spring3.0的AnnotationMethodHandlerAdapter,流程一样:

(1、RequestMappingHandlerAdapter.invokeHandlerMethod

//1、RequestMappingHandlerAdapter首先调用ModelFactory的initModel方法准备模型数据:  
modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);  
//2、调用@RequestMapping注解的功能处理方法  
requestMappingMethod.invokeAndHandle(webRequest, mavContainer);  
//3、更新/合并模型数据  
modelFactory.updateModel(webRequest, mavContainer);   

(2、ModelFactory.initModel

Map<String, ?> attributesInSession = this.sessionAttributesHandler.retrieveAttributes(request);  
//1.1、将与@SessionAttributes注解相关的会话对象放入模型数据中  
mavContainer.mergeAttributes(attributesInSession);  
//1.2、调用@ModelAttribute方法添加表单引用对象  
invokeModelAttributeMethods(request, mavContainer);  
//1.3、验证模型数据中是否包含@SessionAttributes注解相关的会话对象,不包含抛出异常  
for (String name : findSessionAttributeArguments(handlerMethod)) {  if (!mavContainer.containsAttribute(name)) {  //1.4、此处防止在@ModelAttribute注解方法又添加了会话对象  //如在@ModelAttribute注解方法调用session.setAttribute("user", new UserModel());  Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);  if (value == null) {  throw new HttpSessionRequiredException("Expected session attribute '" + name + "'");  }  mavContainer.addAttribute(name, value);  
}

(3、ModelFactory.invokeModelAttributeMethods

for (InvocableHandlerMethod attrMethod : this.attributeMethods) {  String modelName = attrMethod.getMethodAnnotation(ModelAttribute.class).value();   //1.2.1、如果模型数据中包含同名数据则不再添加  if (mavContainer.containsAttribute(modelName)) {  continue;  }  //1.2.2、调用@ModelAttribute注解方法并将返回值添加到模型数据中,此处省略实现代码  
}

(4、requestMappingMethod.invokeAndHandle 调用功能处理方法,此处省略

(5、ModelFactory.updateMode 更新模型数据

//3.1、如果会话被标识为完成,此时从会话中清除@SessionAttributes注解相关的会话对象  
if (mavContainer.getSessionStatus().isComplete()){   this.sessionAttributesHandler.cleanupAttributes(request);  
}  
//3.2、如果会话没有完成,将模型数据中的@SessionAttributes注解相关的对象添加到会话中  
else {  this.sessionAttributesHandler.storeAttributes(request, mavContainer.getModel());  
}  
//省略部分代码

到此@SessionAtrribute介绍完毕,测试代码在cn.javass.chapter6.web.controller.paramtype.SessionAttributeController中。

另外cn.javass.chapter6.web.controller.paramtype.WizardFormController是一个类似于【AbstractWizardFormController】多步骤提交表单需要考虑会话超时问题,这种方式可能对用户不太友好,我们可以采取隐藏表单(即当前步骤将其他步骤的表单隐藏)或表单数据存数据库(每步骤更新下数据库数据)等方案解决。

@Value绑定SpEL表示式

@Value用于将一个SpEL表达式结果映射到到功能处理方法的参数上。

public String test(@Value("#{systemProperties['java.vm.version']}") String jvmVersion)  

到此数据绑定我们就介绍完了,对于没有介绍的方法参数和注解(包括自定义注解)在后续章节进行介绍。接下来我们学习下数据类型转换吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/556991.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java new关键字和newInstance()方法的区别

1、类的加载方式不同 在执行Class.forName(“a.class.Name”)时&#xff0c;JVM会在classapth中去找对应的类并加载&#xff0c;这时JVM会执行该类的静态代码段。在使用newInstance()方法的时候&#xff0c;必须保证这个类已经加载并且已经连接了&#xff0c;而这可以通过Clas…

springboot 的 RedisTemplate 的 execute 和 executePipelined 功能的区别redis

1.executespring 如下是 springboot 官网原文:springboot Redis provides support for transactions through the multi, exec, and discard commands. These operations are available on RedisTemplate, however RedisTemplate is not guaranteed to execute all operatio…

Error running ‘Tomcat‘: Unable to open debugger port (127.0.0.1:2148): java.net.SocketExceptio

在Web项目运行的时候&#xff0c;IDEA可能会报Error running ‘Tomcat’: Unable to open debugger port (127.0.0.1:2148): java.net.SocketException “socket closed”错误&#xff0c;启动不了Tomcat&#xff0c;在这种时候&#xff0c;网上的解决办法大多都是修改端口的这…

# hive打不开,提示节点过少,进入安全模式~~

hive打不开,提示节点过少&#xff0c;进入安全模式~~ 前段时候给电及除尘&#xff0c;因为经常拆着玩&#xff0c;越熟练越容易大意&#xff0c;一下子把电源排线扯坏了。挼了挼&#xff0c;想凑和着用吧&#xff0c;没想到不知怎么的就会关机&#xff0c;太频繁了。一怒之下取…

Java 枚举(enum) 详解7种常见的用法

JDK1.5引入了新的类型——枚举。在 Java 中它虽然算个“小”功能&#xff0c;却给我的开发带来了“大”方便。 用法一&#xff1a;常量 在JDK1.5 之前&#xff0c;我们定义常量都是&#xff1a; public static fianl… 。现在好了&#xff0c;有了枚举&#xff0c;可以把相关…

sqoop导入hive时间格式问题解决方案

sqoop导入hive时间格式问题解决方案 从mysql导入数据时,发现时间格式有问题,要么是时间后面多一位零,要么要使用时间戳,还能不能好好玩耍了?! 于是,我就逛论坛&#xff0c;找大神&#xff0c;最终无果&#xff0c;也许这个问题过于简单吧&#xff0c;居然没有大牛讨论。想了好…

Java枚举类型(enum)详解

文章目录理解枚举类型枚举的定义枚举实现原理枚举的常见方法Enum抽象类常见方法编译器生成的Values方法与ValueOf方法枚举与Class对象枚举的进阶用法向enum类添加方法与自定义构造函数关于覆盖enum类方法enum类中定义抽象方法enum类与接口枚举与switch枚举与单例模式EnumMapEnu…

hive中导入text文件遇到的坑

今天帮一同学导入一个excel数据&#xff0c;我把excel保存为txt格式&#xff0c;然后建表导入&#xff0c;失败&#xff01;分隔符格式不匹配&#xff0c;无法导入&#xff01;&#xff01;&#xff01;&#xff01;怎么看两边都是\t&#xff0c;怎么不匹配呢&#xff1f; 做为…

开窗函数的意义与用法

开窗函数——排序函数 开窗函数与其他函数的区别是,它不是关联其他表查询,而是在一张表内根据我们的想法自定义的规则分组后对我们组内的数据进行检索和计算。我们自定义的规则所分的组&#xff0c;就如同整张表的一个个小窗口&#xff0c;因此我们开出一个个小窗口并对这些小…

mysql/sqlyog导入txt文件的方法

今天尝试着用sqlyog向mysql中导入数据&#xff0c;用了以下几种&#xff1a; 一、sql载入 格式&#xff1a; LOAD DATA LOCAL INFILE 文件路径 INTO TABLE 表名 FIELDS TERMINATED BY 字段分隔符 LINES TERMINATED BY 行分隔符;直接进去了 代码&#xff1a; LOAD DATA LOCA…

XSS知识总结

XSS基础 跨站脚本&#xff08;英语&#xff1a;Cross-site scripting&#xff0c;通常简称为&#xff1a;XSS&#xff09;是一种网站应用程序的安全漏洞攻击&#xff0c;是代码注入的一种。它允许恶意用户将代码注入到网页上&#xff0c;其他用户在观看网页时就会受到影响。这…

2020有效的邮箱号大全_2020年公众号免费裂变涨粉的3个有效方法,让我一天涨粉6000...

文章来源我的公众号&#xff1a;运营小小喵&#xff08;专注分享新媒体运营干货、写作技巧&#xff09;虽然公众号一直被唱衰&#xff0c;但至今依然还有很多人坚持在做。但现在做公众号最大的问题&#xff0c;除了流量大幅下降&#xff0c;打开率越来越低&#xff0c;更重要的…

Error during job, obtaining debugging information...

今天在插入数据的时候出现错误:Error during job, obtaining debugging information… Ended Job job_1575898012755_0005 with errors Error during job, obtaining debugging information... Examining task ID: task_1575898012755_0005_m_000000 (and more) from job job…

java实现 XSS攻击防护

首先说一下什么是XSS攻击 XSS攻击全称跨站脚本攻击&#xff0c;是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆&#xff0c; 故将跨站脚本攻击缩写为XSS&#xff0c;XSS是一种在web应用中的计算机安全漏洞&#xff0c;它允许恶意web 用户将代码植入到提供给其它用…

动态分区添加的新字段无法插入数据

我们在使用动态分区的进程中&#xff0c;有时候需要新增字段&#xff0c;新增之后&#xff0c;发现该字段一直为空&#xff0c;无论怎么插入数据&#xff0c;该字段值始终不变。过去的做法就是把表删了&#xff0c;重建带新字段的新表&#xff0c;问题就解决了&#xff0c;今天…

Java实现XSS防御

XSS概述 跨站脚本攻击(Cross Site Scripting)&#xff0c;缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码&#xff0c;当用户浏览该页之时&#xff0c;嵌入其中Web里面的Script代码会被执行&#xff0c;从而达到恶意攻击用户的目的。 Servlet的方式 1、继承HttpServle…

classmethod 继承_让人眼花缭乱的类继承

Python语言的一个优势是简洁易用。是否简洁易用仅仅是Python语言本身的一个话题&#xff0c;但“好消息”是如果你想创造那种一大堆继承、混乱的内部关系的代码&#xff0c;也是可以的&#xff01;今天烦人的代码来自于验证某些math-y数学分析代码。一开始&#xff0c;他们是发…

SQL优化之浅见

SQL优化之浅见一、查询优化二、导入大量数据时的优化三、INSERT优化四、字段注释五、说明用了段mysql/Oracle/hive等数据库,对SQL语言以Mysql为例&#xff0c;总结一下对sql优化方面的见解&#xff0c;欢迎大家补充。 一、查询优化 1.在关联查询中&#xff0c;关联键的数据类…

JAVA SSM框架+Redis 实现单点登录

1&#xff1a;什么是单点登录&#xff1f; 答&#xff1a;单点登录的英文名叫做&#xff1a;Single Sign On&#xff08;简称SSO&#xff09; 一般我们的模块都是在同一个系统下&#xff0c;同一个tomcat&#xff08;如图&#xff0c;以商城为例&#xff09; 后来为了维护和…

2017云栖大会门票转让_「揭秘GP」云栖大会 | Greenplum 6.0 内核优化解读和7.0展望...

9月25日&#xff0c;云栖大会在杭州阿里巴巴云栖小镇正式拉开序幕&#xff0c;三天会议期间&#xff0c;共吸引了200多位世界级科学家、400多家科技合作伙伴参与&#xff0c;科技展区面积超过3万平方米&#xff0c;共发布了1000多项顶尖技术。云栖大会现场在此次云栖大会上&…