目录
如果对@RequestMapping不是特别了解的,建议读一下这篇文章: https://blog.csdn.net/weixin_43888891/article/details/126861310
参数映射准确来说是springmvc来帮我们干的活,但是由于springboot太过火爆,简化了springmvc相关配置文件,以至于很多人会误认为是springboot的功能。其实springboot是帮我们整合了spring相关框架。记住只是简化,底层还是不变的!
在学习接收参数前,肯定要先了解一共有几种传参方式,下面一共提供了四种,供参考学习:
1)params传参,params传参的格式是http://xxx?参数名=值&参数名=值。在postman当中params当中添加参数会发现,他就是在地址栏上加的参数。

2)body表单传参,就是请求体传参
form-data的请求是在body中,为key=value格式,同时可以传文件,Content-Type为multipart/form-data,后端可以用@RequestParam接收。

3)json传参
json传参也是在body当中,只不过json是一种数据格式,后端可以用@RequestBody接收。

4)地址栏传参,直接通过/在地址上拼接参数值,这种方式不需要在地址栏上写参数名,后端只需要知道他在地址的哪个位置传的参数就可以拿到值!

这两个实体类用来当做测试类,用来接参数,后续我们会不断的使用到他:
public class Params {
private String userName;
private Integer age;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Param{" +
"userName='" + userName + '\'' +
", age=" + age +
'}';
}
}
public class User {
private String userName;
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
'}';
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
import com.gzl.cn.demo.entity.Params;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/noAnno")
public class NoAnnoController {
@GetMapping("/url")
public String getMapping(String msg) {
return msg;
}
// 可以有多个实体类参数
@GetMapping("/body")
public String getMapping(Params param,User user) {
System.out.println(param);
System.out.println(user);
return param.toString();
}
@PostMapping("/post")
public String postMapping(String msg) {
return msg;
}
@PostMapping("/post-body")
public String postMapping(Params msg) {
return msg.toString();
}
}
以下是测试的详细步骤:
(1)测试无注解params传参
测试:get请求:
http://localhost:8080/noAnno/url?msg=111
http://localhost:8080/noAnno/body?userName=张三&age=11

测试:post请求:post请求我们无法通过浏览器来访问,得需要借助postman调用
http://localhost:8080/noAnno/post?msg=111
http://localhost:8080/noAnno/post-body?userName=张三&age=22
当然也可以借用cmd框当中的curl命令来请求post
curl http://localhost:8080/noAnno/post-body -X POST -d "userName=66&age=22"

(2)测试无注解body表单传参

(3)测试无注解params传参+body表单传参 两种同时传参

总结:
params传参也可以选择body表单传参,甚至可以两种同时传,两种同时传会将body传的参数使用逗号拼接上params传的参数在后端会拿到null值,这块需要注意一下!假如是null值的情况下去get属性,或者是tostring就会空指针!如果传参的话,参数名要和controller当中定义的变量名一样才能接受到参数!任意请求方式 都是一样的!http://localhost:8089/conformity/parm/requestParm8?uid=1&uname=222&pwd=2222
就是在地址?然后加上&拼接。
不携带@RequestParm的时候,可以连key值都不传。
@GetMapping("/requestParm")
public void requestParm(Integer id){
System.out.println("get不带@RequestParam:"+id);
}
携带@RequestParm的时候,必须传值。因为@RequestParam注解的required默认是true。假如不传会报错。
@GetMapping("/requestParm1")
public void requestParm1(@RequestParam Integer id){
System.out.println("get带@RequestParam:"+id);
}
@RequestParam接收参数,不可使用使用实体来封装,如下所示,直接会报400错误。@RequstParm然后使用实体来接参数,其实是没问题的,并且不传key值也是可以的。post、get都一样。// 错误的
@PostMapping("/requestParm7")
public void requestParm7(@RequestParam User user){
System.out.println("get带@RequestParam:"+user);
}
@RequestParam参数映射:注意@RequestParam默认是以变量名作为前端传参名称,但是假如我们注解设置了名称,如下,那么参数名称以注解当中的属性为准!假如前端传msg而不是msg1就会报异常。
@GetMapping("/url")
public String getMapping(@RequestParam("msg1") String msg) {
System.out.println(msg);
System.out.println(aaa);
return msg;
}
总结:
1、传单个参数的时候可以使用@RequestParam,不带也可以,带上就意味着前端必须传这个值。
2、实体接受参数的话,不可以带,带上就会报错。不带的话是可以接受多个参数的。并且没有key限制。
@RequestParam的属性
value和name属性使用了@AliasFor,在spring当中起着一个注解属性别名传递值的作用。也就是我给value属性赋值,name属性同样也能取到值,name属性赋值,value属性也同样可以取到值。@RequestParam(value = "msg")等同于@RequestParam("msg"),因为注解当中不带属性名称默认指的就是value属性,而@RequestParam("msg")等同于@RequestParam(name = "msg")。required属性代表的是否是必填,默认是true,这个true代表的是前端必须传key值,value值可以随意,但是key值是必须的。假如不传就是400异常!defaultValue属性:设置默认值,可以避免required属性设置为true然后前端不传key值报错的问题。相当于设置defaultValue属性之后,前端传不传值都可以,传值就以前端的为准,不传值就以设置的defaultValue值为准!示例如下:@RequestParam(name = "pageNo",required = false,defaultValue = "1") Integer pageNo@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
boolean required() default true;
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
@PathVariable 用于绑定 url 中的占位符。例如:请求 url 中 /delete/{id},这个{id}就是 url 占位符。url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志。
@RequestMapping("/pathVariable2/{id}")
public void pathVariable2(@PathVariable Integer id){
System.out.println("get带@RequestParam:"+id);
}
上面代码示例使用了地址栏传参,就算不带@PathVariable也可以访问,只不过接不到值。
@PathVariable 的属性
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PathVariable {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
boolean required() default true;
}
总结:

@RequestBody一般被用来接收http请求中body中json数据。
get、post都可以使用。一般用于post。
@RequestMapping("/requestBody2")
public void requestBody2(@RequestBody Params params){
System.out.println("get带@RequestParam:"+params);
}
{"userName":"111","age":"11"},传输json数据,也可以不传key。这里有一点需要注意,mvc给我们做了参数类型转换,Params 对象当中的age是Integer类型,但是json传字符串,照样可以映射进去。Boolean、BigDecimal、Integer、String、Date这些其实都可以映射进去的。当然Date相对来说比较特殊一点。传yyyy-MM-dd格式是不会报错的。但是其他格式可能就会报错了,一般使用Date类型接参数涉及到需要咱们自己格式化,关于日期相关问题感兴趣的可以看这一篇文章:https://blog.csdn.net/weixin_43888891/article/details/126846791
@RequestBody 的属性
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
boolean required() default true;
}
@RequestHeader主要用来获取请求当中的请求头
@RestController
@RequestMapping("/requestHeader")
public class RequestHeaderController {
@PostMapping("/header")
public String getMapping(@RequestHeader("param")String param){
return param;
}
}
我们通过header进行参数传递,同样它可以设置是否必传,默认值等,请大家自行翻阅源码,就不一一罗列了。

这是直接拿到request对象,通过request可以从对象中灵活的获取参数:
@RestController
@RequestMapping("/request")
public class HttpServletRequestController {
@GetMapping("/getUrlValue")
public String getUrlValue(HttpServletRequest request) {
// 没有的时候不会报错,直接为null
String msg = request.getParameter("msg");
System.out.println(msg);
return msg;
}
@GetMapping("/getUrlValues")
public String getHttpServletRequestValue(HttpServletRequest request) {
Map<String, String[]> parameterMap = request.getParameterMap();
return JSONObject.toJSONString(request.getParameterMap());;
}
}
针对于
request.getParameter("msg");,其实就是跟@RequestParam差不多,可以获取到body当中的for-data的数据以及使用url ?拼接的参数的数据
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano
我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_