前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试不是无情物,参数注解知多少?

面试不是无情物,参数注解知多少?

作者头像
程序员爱酸奶
发布2020-05-22 15:46:01
5580
发布2020-05-22 15:46:01
举报
文章被收录于专栏:程序员爱酸奶程序员爱酸奶

前言

前两天面试的,面试官问我用在参数上的注解有哪些?我想了一下说有RequestParam,每个参数都需要RequestParam修饰,可以设置required 等于false,表示该字段非必传。面试官:还有呢?我:只知道这么多了,RequestParam 注解用的比较多,其他的没怎么用?面试官:好了,今天的面试就到这,后续有消息会通知你。挂掉电话 我:???

结束掉面试后,好好的看了下用在参数上的注解。用在参数上的注解,主要是controller 层,用来接收请求中的参数。常用的有三种 @RequestParm @RequestBody @PathVariable

下面我们一个个看下

@RequestParam

@RequestParam 注解接收请求的参数是从request.getParameterMap()中取的。我们来先看下这个例子:

@RequestMapping(value = "/hello",method = {RequestMethod.GET,RequestMethod.POST})
    public String play(@RequestParam(value = "name",required = false) String name, HttpServletRequest request){
        Map<String, String[]> map=request.getParameterMap();
        for(Map.Entry<String, String[]> entry:map.entrySet()){
            System.out.println(entry.getKey());
            System.out.println(Arrays.toString(entry.getValue()));
        }
        return name+",你好!";
    }

@RequestMapping 表示请求的相对路径,value 是相对路径的值,method 用来限制请求的类型,我这里设置的是可以get 和post 请求。 HttpServletRequest 这个参数是方便我们得到请求的request 里面的信息。

而RequestParam 注解就是用来接收 参数name 的。我们看下RequestParam 的源码:


@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 "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

name和value 用来接收参数名,二者选其一就可以。required 默认为true 表示参数必须传,改成false 表示参数非必传。

我们现在运行看下结果

说明@RequestParam 注解是从request.parames()方法中获取到参数。

@RequestParam 可以接收post 和get 的参数。且parms 和body 中都添加的参数,会同时生效。

总结:1、@RequestParam 注解,作用在单个参数上,并且参数不能是一个对象。因为我们看到request.getParameterMap() 接收的map 的类型为Map。2、@RequestParam 注解,多个参数可以使用多个注解,可以设置参数是否必传。3、@RequestParam 注解获取参数是从request 中的parms 获取的。支持get 和post

@RequestBody

@RequestBody 注解是从请求体重获取参数。一个请求只有一个请求体,但是可以有多个参数,这就是为什么只能有一个@RequestBody 注解,但是可以有多个@RequestParam 注解。因为get请求没有请求体。所以@RequestBody 一般用来接收post 请求的参数,且用来接收前端传的json 字符串的。我们还是上面的例子,稍作调整

@RequestMapping(value = "/hello1",method = {RequestMethod.GET,RequestMethod.POST})
    public String play1(@RequestBody String name,String sex, HttpServletRequest request){
        Map<String, String[]> map=request.getParameterMap();
        for(Map.Entry<String, String[]> entry:map.entrySet()){
            System.out.println(entry.getKey()+":"+Arrays.toString(entry.getValue()));
        }
        return name+",你好! \n你的性别是:"+sex;
    }

发现name的值是name=小明&sex=男。这说明@RequestBody 注解只能使用一个,且获取到所有的参数,我们最好不要用单一的参数接收。我们再稍作修改。通过map 来接收请求体。

@RequestMapping(value = "/hello1",method = {RequestMethod.GET,RequestMethod.POST})
    public String play1(@RequestBody Map<String,Object> parms, HttpServletRequest request){
        Map<String, String[]> map=request.getParameterMap();
        for(Map.Entry<String, String[]> entry:map.entrySet()){
            System.out.println(entry.getKey()+":"+Arrays.toString(entry.getValue()));
        }
        return parms.get("name")+",你好! \n你的性别是:"+parms.get("sex");
    }

而控制台什么都没打印。

说明@RequestBody并不是从parms 中获取参数的,而是从从requestbody 中获取参数,并且是获取json 格式的参数。这时我们使用Content-Type=application/json。如果我们使用Content-Type 等于application/x-www-form-urlencoded或者multipart/form-data 则会报错。因为不是这两者是key-value 模式的。

为什么会这样呢?因为@RequestBody 不仅能接收一个对象,还能接收一组对象。但是其他两种却不行。如下我们调整一下代码:

@RequestMapping(value = "/hello2",method = {RequestMethod.POST})
    public String play2(@RequestBody List<Map<String,Object>> parms){
        StringBuilder stringBuilder=new StringBuilder();
        for(Map<String,Object> map:parms){
            stringBuilder.append(map.get("name")+",你好! \n你的性别是:"+map.get("sex")+"\n");
        }
        return stringBuilder.toString();
    }

可以看到@RequestBody 还是有自己的优势的,不仅如此,RequestBody不但可以接收map,还可以接收我们自定义的bean。如下:我们先创建一个user 实体

public class User {
    private String name;
    private String sex;
    private int age;
    //getter和setter 方法
}

然后写一个接口

@RequestMapping(value = "/hello3",method = {RequestMethod.GET,RequestMethod.POST})
    public String play3(@RequestBody List<User> users){
        StringBuilder stringBuilder=new StringBuilder();
        for(User user:users){
            stringBuilder.append(user.getName()+",你好! \n你的性别是:"+user.getSex()+"\n");
        }
        return stringBuilder.toString();
    }

看到可以达到一样的效果,还省去了我们转换。

总结:1、@RequestBody 注解 接收请求体中参数,接收post请求,不能接收get 请求。且只能有一个RequestBody 注解。2、@RequestBody 注解多用来接收json 传参。可以是map,对象,list.

@PathVariable

@PathVariable 注解是接收请求路径中的占位符的值。如下:

@RequestMapping(value = "/hello4/{name}/{sex}",method = {RequestMethod.GET,RequestMethod.POST})
    public String play4(@PathVariable String name,@PathVariable String sex) {
        return name+",你好! \n你的性别是:"+sex;
    }

其他的作用和RequestParam 是一样的。他只能接收单个参数,url 中有几个占位符,就有几个@Pathvariable 注解。

无注解接收参数

还有一种情况,放在最后,我们在接口的时候请求参数没有任何注解,也可以接收到请求的参数。看下面去掉@RequestParam 注解

 @RequestMapping(value = "/hello5",method = {RequestMethod.GET,RequestMethod.POST})
    public String play5(String name,String sex, HttpServletRequest request){
        Map<String, String[]> map=request.getParameterMap();
        for(Map.Entry<String, String[]> entry:map.entrySet()){
            System.out.println(entry.getKey()+":"+Arrays.toString(entry.getValue()));
        }
        return name+",你好! \n你的性别是:"+sex;
    }

并且还支持参数非必传。

我们再试试不用@RequestBody 注解

@RequestMapping(value = "/hello6",method = {RequestMethod.GET,RequestMethod.POST})
    public String play6( User user){
        return user.getName()+",你好! \n你的性别是:"+user.getSex();
    }

发现并没有获取到值。造成上述的原因:其实是默认是使用@RequestParam 注解,且 ruquires=false。所以当我们使用注解的时候,单个的参数也可以直接获取到。

后记

总算差不多了,现在面试官有本事再问我这个问题试试,看我不怼回去。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员爱酸奶 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • @RequestParam
  • @RequestBody
  • @PathVariable
  • 无注解接收参数
  • 后记
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档