springboot 打印日志時(shí)碰到的問題

在springboot 項(xiàng)目上傳文件時(shí)出現(xiàn)了以下錯(cuò)誤


Required request part 'file' is not present

我是通過在Filter中使用HttpServletRequestWrapper 的形式打印請(qǐng)求和返回日志的,經(jīng)過排查發(fā)現(xiàn)去枷,使用HttpServletRequestWrapper 打印請(qǐng)求參數(shù)時(shí)怖辆,發(fā)現(xiàn)當(dāng)HttpServletRequest請(qǐng)求的Content-Type 為application/json時(shí)能夠正常解析是复,但是當(dāng)用表單提交的形式時(shí),springboot 找不到表單提交的參數(shù)竖螃,返回參數(shù)缺失相關(guān)的異常淑廊。
根據(jù)源碼查詢發(fā)現(xiàn),在RequestParamMethodArgumentResolver類中 resolveName方法 中調(diào)用了request.getParameterValues(name)特咆,結(jié)果返回為null

    protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
        HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);

        if (servletRequest != null) {
            Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest);
            if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {
                return mpArg;
            }
        }

        Object arg = null;
        MultipartRequest multipartRequest = request.getNativeRequest(MultipartRequest.class);
        if (multipartRequest != null) {
            List<MultipartFile> files = multipartRequest.getFiles(name);
            if (!files.isEmpty()) {
                arg = (files.size() == 1 ? files.get(0) : files);
            }
        }
        if (arg == null) {
            String[] paramValues = request.getParameterValues(name);
            if (paramValues != null) {
                arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
            }
        }
        return arg;
    }

HTML中的form表單有一個(gè)關(guān)鍵屬性 enctype=application/x-www-form-urlencoded 或multipart/form-data季惩。
enctype=application/x- www-form-urlencoded是默認(rèn)的編碼方式,這種編碼方式很簡(jiǎn)單腻格,編碼后的結(jié)果通常是field1=value2&field2=value2&… 的形式画拾,如 name=aaaa&Submit=Submit。這種編碼的具體規(guī)則可以在 rfc2231 里查到荒叶, 通常使用的表單也 是采用這種方式編碼的碾阁,Servlet 的 API 提供了對(duì)這種 編碼方式解碼的支持,只需要調(diào)用 ServletRequest 類中的getParameter()方法就可 以得到用戶表單中的字段和數(shù)據(jù)些楣。
而我們知道 request.getParameter()脂凶,request.getInputStream(),request.getReader()這三種方法是有沖突的愁茁,因?yàn)榱髦荒茏x取一次蚕钦。所以在我們通過表單提交的數(shù)據(jù)找不到。

我們根據(jù)HttpServletRequest 的Content-Type類型進(jìn)行判斷HttpServletRequestWrapper 進(jìn)行哪種處理鹅很。
更改后的 RequestWrapper如下


@Slf4j
public class RequestWrapper extends HttpServletRequestWrapper {


    private byte[] body;

    /**
     * Constructs a request object wrapping the given request.
     *
     * @param request The request to wrap
     * @throws IllegalArgumentException if the request is null
     */
   public RequestWrapper(HttpServletRequest request) {
        super(request);
        try {
        if(HttpMethod.POST.matches(request.getMethod())){
            log.error(request.getContentType()+"---------------");

                if(request.getContentType().contains("application/x-www-form-urlencoded")){
                    // 通過getParameter的形式解析
                    body=  JacksonUtil.objectToJson(request.getParameterMap()).getBytes();
                }else if(request.getContentType().contains("multipart/form-data")){
                    body="文件類型嘶居,不解析".getBytes();
                }else {
                    body = IOUtils.toByteArray(request.getInputStream());
                }

        }else { // get 請(qǐng)求通過getParameterMap 的方式獲取
            body=  JacksonUtil.objectToJson(request.getParameterMap()).getBytes();
        }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new SignWrapperInputStream(body);
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }


    public byte[] getBody() {
        return body;
    }

    public void setBody(byte[] body) {
        this.body = body;
    }

    private class SignWrapperInputStream extends ServletInputStream {

        private ByteArrayInputStream buffer;

        public SignWrapperInputStream(byte[] body) {
            body = (body == null) ? new byte[0] : body;
            this.buffer = new ByteArrayInputStream(body);
        }

        @Override
        public int read() throws IOException {
            return buffer.read();
        }

        @Override
        public boolean isFinished() {
            return buffer.available() == 0;
        }

        @Override
        public boolean isReady() {
            return true;
        }

        @Override
        public void setReadListener(ReadListener listener) {
            throw new RuntimeException("Not implemented");

        }
    }
}

這樣就可以進(jìn)行json、表單促煮、還有文件相關(guān)的日志打印了邮屁。按照道理來說 multipart/form-data類型應(yīng)該也是通過 request.getInputStream()或者request.getReader()獲取的,不知道為什么也是不能通過HttpServletRequestWrapper解析菠齿,有知道的小伙伴請(qǐng)留言告訴我一下佑吝,不勝感激。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绳匀,一起剝皮案震驚了整個(gè)濱河市芋忿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌疾棵,老刑警劉巖戈钢,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異是尔,居然都是意外死亡殉了,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門嗜历,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宣渗,“玉大人抖所,你說我怎么就攤上這事『鄞眩” “怎么了田轧?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鞍恢。 經(jīng)常有香客問我傻粘,道長(zhǎng),這世上最難降的妖魔是什么帮掉? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任弦悉,我火速辦了婚禮,結(jié)果婚禮上蟆炊,老公的妹妹穿的比我還像新娘稽莉。我一直安慰自己,他們只是感情好涩搓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布污秆。 她就那樣靜靜地躺著,像睡著了一般昧甘。 火紅的嫁衣襯著肌膚如雪良拼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天充边,我揣著相機(jī)與錄音庸推,去河邊找鬼。 笑死浇冰,一個(gè)胖子當(dāng)著我的面吹牛贬媒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肘习,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼掖蛤,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了井厌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤致讥,失蹤者是張志新(化名)和其女友劉穎仅仆,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體垢袱,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡墓拜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了请契。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咳榜。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡夏醉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涌韩,到底是詐尸還是另有隱情畔柔,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布臣樱,位于F島的核電站靶擦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏雇毫。R本人自食惡果不足惜玄捕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望棚放。 院中可真熱鬧枚粘,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至柬姚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間庄涡,已是汗流浹背量承。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留穴店,地道東北人撕捍。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像泣洞,于是被迫代替她去往敵國(guó)和親忧风。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353