1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        每日一例 | 手寫RequestParameter注解,實現(xiàn)有參方法調(diào)用

        共 7714字,需瀏覽 16分鐘

         ·

        2021-06-02 02:36

        前言

        昨天實現(xiàn)了requestMapping和controller注解,解決了請求地址與接口方法之間的映射問題,可以根據(jù)前端請求地址調(diào)用對應(yīng)的接口方法。但是還不能解決有參方法的調(diào)用,今天我們就來啃下這個硬碴,解決這個最后一公里。

        開肝

        定義RequestParameter注解

        springboot的注解是RequestParam,我們今天實現(xiàn)的需求就是參考RequestParam,但是我沒有時間去研究springboot的源碼(至少今天沒有時間),就先按照自己的想法來實現(xiàn)了。和前面注解不一樣的一點是,這個注解的target指定的是ElementType.PARAMETER,因為這個注解是加在方法的參數(shù)上的。

        @Target(ElementType.PARAMETER)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface RequestParameter {
            String value();
        }

        加到方法的參數(shù)上是這樣的:

        @RequestMapping("/sayHello")
            public String test(@RequestParameter("name") String name) {
                return "hello," + name;
            }

        是不是看著還挺像像樣的。

        業(yè)務(wù)端使用

        目前業(yè)務(wù)處理還是在doDispatcher方法,所以今天依然是動這個方法。

        先說下思路,思路也很簡單,就是服務(wù)器收到前端請求后,根據(jù)requestMapping(請求地址)拿到對應(yīng)的方法,從方法中拿到參數(shù)注解RequestParameter(這個注解的作用就是標(biāo)記參數(shù)名,讓我們可以根據(jù)參數(shù)名拿到參數(shù)),然后根據(jù)注解的value拿到參數(shù)名,然后根據(jù)參數(shù)名從requestAttributeMap拿到請求參數(shù)的值,組裝方法入?yún)⒘斜怼?/p>

        /**
             * 請求分發(fā)處理
             * @throws Exception
             */

            public void doDispatcher() throws Exception{
                RequestHear requestHear = request.getRequestHear();
                Map<String, Object> requestAttributeMap = request.getRequestAttributeMap();
                logger.info("請求頭信息:{}", requestHear);
                logger.info("請求信息:{}", requestAttributeMap);
                if (Objects.isNull(requestHear) || Objects.isNull(requestAttributeMap)) {
                    return;
                }
                String requestMapping = requestHear.getRequestMapping();
                if (requestMappingMap.containsKey(requestMapping)) {
                    Method method = requestMappingMap.get(requestMapping);
                    logger.debug("method:{}", method);
                    Class<?> declaringClass = method.getDeclaringClass();
                    Annotation[][] parameterAnnotations = method.getParameterAnnotations();
                    Object[] parameters = new Object[parameterAnnotations.length];
                    for (int i = 0; i < parameterAnnotations.length; i++) {
                        RequestParameter annotation = (RequestParameter)parameterAnnotations[i][0];
                        parameters[i] = requestAttributeMap.get(annotation.value());
                    }
                    Object o = declaringClass.newInstance();
                    Object invoke = method.invoke(o, parameters);
                    logger.info("invoke:{}", invoke);
                    response.write(String.format("hello syskeCat, dateTime:%d\n result = %s", System.currentTimeMillis(), invoke));
                } else {
                    response.write(404, String.format("resources not found :%d", System.currentTimeMillis()));
                }
                socket.close();
            }

        我單獨把修改部分拿出來,簡單解釋下。

        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
                    Object[] parameters = new Object[parameterAnnotations.length];
                    for (int i = 0; i < parameterAnnotations.length; i++) {
                        RequestParameter annotation = (RequestParameter)parameterAnnotations[i][0];
                        parameters[i] = requestAttributeMap.get(annotation.value());
                    }
                    Object o = declaringClass.newInstance();
                    Object invoke = method.invoke(o, parameters);

        method.getParameterAnnotations的作用是獲取方法的所有參數(shù)注解,返回結(jié)果是一個二維數(shù)組,因為一個方法可以有多個參數(shù),每個參數(shù)都可以有多個注解,所以肯定是一個二維數(shù)組。parameterAnnotations[0][0]就是第一個參數(shù)的第一個注解,parameterAnnotations[1][0]就是第二個參數(shù)的第一個注解,其他以此類推。這張圖更清楚地說明了這一點:

        因為獲取到的注解是Annotation,并非是我們的定義的注解,所以需要進行強制轉(zhuǎn)換成我們的自定義注解RequestParameter。

        然后通過注解的value()方法從注解中拿到參數(shù)名,根據(jù)參數(shù)名從參數(shù)map中拿到請求的值,組裝成參數(shù)集合,然后反射調(diào)用。

        請求參數(shù)處理這邊我們也做了一些調(diào)整,主要是為了獲取請求參數(shù)參數(shù):

         Map<String, Object> attributeMap = Maps.newHashMap();
                if (requestMapping.contains("?")) {
                    int endIndex = requestMapping.lastIndexOf('?');
                    String requestParameterStr = requestMapping.substring(endIndex + 1);
                    requestMapping = requestMapping.substring(0, endIndex);
                    String[] split = requestParameterStr.split("&");
                    for (String s : split) {
                        String[] split1 = s.split("=");
                        attributeMap.put(StringUtil.trim(split1[0]), StringUtil.trim(split1[1]));
                    }

                }

        主要就是在增加了請求參數(shù)的處理,把sayHello?name=yunzhongzhi&age=12處理成requestMapping和請求參數(shù)map。這塊后期還需要優(yōu)化,要把get請求和post請求分開,分別處理,所以目前我們的服務(wù)器只支持get請求。

        測試

        完成以上調(diào)整,我們的方法就已經(jīng)支持有參調(diào)用了,我們來測試下吧!

        效果還不錯,目標(biāo)完美達成。

        總結(jié)

        感覺有思路的話,寫東西還是比較快的,這些需求都是今天早上實現(xiàn)的,中間被Annotation卡住了,一直無法獲取到參數(shù)名,后來發(fā)現(xiàn)只要強轉(zhuǎn)一下就行了。千里之行,始于足下,感興趣的小伙伴肝起來。

        下面是項目的開源倉庫,有興趣的小伙伴可以去看看,如果有想法的小伙伴,我真心推薦你自己動個手,自己寫一下,真的感覺不錯:

        https://github.com/Syske/syske-boot
        - END -


        瀏覽 54
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产婬妇高潮久久久久久免费AV | 91国内产香蕉 | 天天夜夜干 | 人妖与人妖做受视频 | 美女插逼视频 | 三级片无码麻豆视频 | 全免费一级毛片免费看无码播放 | 国产九九九视频 | 无码免费一区二区 | 日日日大香蕉 |