一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 使用ServletInputStream在攔截器或過濾器中應用后重寫

使用ServletInputStream在攔截器或過濾器中應用后重寫

2022-03-01 00:37閆-先生 Java教程

這篇文章主要介紹了使用ServletInputStream在攔截器或過濾器中應用后重寫,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

ServletInputStream在攔截器或過濾器應用后重寫

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
ServletInputStream inputStream = super.getInputStream();
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try {
    reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset.forName("UTF-8")));
    String line = "";
    while ((line = reader.readLine()) != null) {
          sb.append(line);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (servletInputStream != null) {
       try {
           servletInputStream.close();
       } catch (IOException e) {
           e.printStackTrace();
       }
    }
    if (reader != null) {
         try {
              reader.close();
         } catch (IOException e) {
              e.printStackTrace();
         }
    }
}
//使用ServletInputStream中數據的代碼
byte[] bytes = sb.getBytes("UTF-8");
final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
return new ServletInputStream() {
       @Override
       public boolean isFinished() {
               return false;
       }
 
        @Override
        public boolean isReady() {
               return false;
        }
 
        @Override
        public void setReadListener(ReadListener readListener) {
 
        }
 
        @Override
        public int read() throws IOException {
               return bais.read();
        }
};

在攔截器種使用了request.getInputStream()或者getReader()

導致在controller中無法獲取請求參數

問題描述

在攔截器種使用了request.getInputStream()或者getReader(),然后在controller接口種使用了@requestbody ,導致controller中無法獲取入參,報錯:HttpMessageNotReadableException: Required request body is missing:

原因分析

ServletRequest中getReader()和getInputStream()只能調用一次。而又由于@RequestBody注解獲取輸出參數的方式也是根據流的方式獲取的。所以我們前面使用流獲取后,后面的@RequestBody就獲取不到對應的輸入流了。

為什么取不到輸入流了???因為流對應的是數據,數據放在內存中,有的是部分放在內存中。

read 一次標記一次當前位置(mark position),第二次read就從標記位置繼續讀(從內存中copy)數據。

所以這就是為什么讀了一次第二次是空了。 怎么讓它不為空呢?只要inputstream 中的pos 變成0就可以重寫讀取當前內存中的數據。

javaAPI中有一個方法public void reset() 這個方法就是可以重置pos為起始位置,但是不是所有的IO讀取流都可以調用該方法!ServletInputStream是不能調用reset方法,這就導致了只能調用一次getInputStream()。

如何處理

重寫HttpServletRequestWrapper把request保存下來,然后通過過濾器把保存下來的request再填充進去,這樣就可以多次讀取request了。

第一步:定義過濾器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
 
@WebFilter(urlPatterns = "/*", filterName = "channelFilter")
public class ChannelFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        ServletRequest requestWrapper = null;
        if (servletRequest instanceof HttpServletRequest) {
            requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
        }
        if (requestWrapper == null) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            System.out.println("進入了過濾器。。。。。");
            filterChain.doFilter(requestWrapper, servletResponse);
        }
    }
 
    @Override
    public void destroy() {
    }
}

第二步:重寫RequestWrapper類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
 
public class RequestWrapper extends HttpServletRequestWrapper {
    private final String body;
    public RequestWrapper(HttpServletRequest request) {
        super(request);
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        InputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException ex) {
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        body = stringBuilder.toString();
    }
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
        ServletInputStream servletInputStream = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }
 
            @Override
            public boolean isReady() {
                return false;
            }
 
            @Override
            public void setReadListener(ReadListener readListener) {
            }
 
            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return servletInputStream;
    }
 
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
    public String getBody() {
        return this.body;
    }
}

第三步:在啟動類中注冊過濾器

使用ServletInputStream在攔截器或過濾器中應用后重寫

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/u011110968/article/details/80228567

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美日韩视频在线成人 | 免费一级特黄特色大片在线观看 | 精品国产免费久久久久久 | 国产自在线观看 | 18无删减羞羞网站动漫 | 国色天香社区视频在线观看免费完整版 | 日本美女xx | 国产高清在线不卡 | 视频在线观看高清免费看 | 狠狠香蕉| 青草视频在线观看免费资源 | 幻女free性俄罗斯第一次摘花 | 亚洲视频在线观看免费视频 | 70老妇牲交毛片 | 婷婷色综合网 | 天天草人人草 | 日韩porn| 久久国产影院 | 午夜秀场在线观看 | 国产精品成人免费观看 | 国产精品馆| 99精品在线视频观看 | hezyo加勒比一区二区三区 | 果冻传媒ⅹxxxxxhd | 日本人和黑人一级纶理片 | 草莓秋葵菠萝蜜绿巨人污 | 情趣内衣情趣玩具play | 免费网站看v片在线成人国产系列 | 欧美又大又粗又长又硬 | 色屁屁www| 国产成人福利免费观看 | 日本黄色高清视频网站 | 精品视频手机在线观看免费 | 美艳教师刘艳第三部166 | 大桥未久aⅴ一区二区 | 国产精品毛片久久久久久久 | 精品人伦一区二区三区潘金莲 | 日本久久啪啪婷婷激情五月 | 国产精品毛片久久久久久久 | naruto tube18动漫| 爱情岛永久成人免费网站 |