好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

在拦截器中读取request参数,解决在controller中无法二次读取的问题

拦截器中读取request参数,在controller中无法二次读取

新建类

?

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

79

80

81

82

83

84

85

86

package com.ouyeelbuy.mc测试数据mon.base;

import javax.servlet.ReadListener;

import javax.servlet.ServletInputStream;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

import java.io.*;

 

/**

  * @author robin.zhang

  * @date $

  * @description 解决在request的数据流只能读取一次的问题

  */

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;

     }

}

添加过滤器

?

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

package com.ouyeelbuy.mc测试数据mon.filter;

import com.ouyeelbuy.mc测试数据mon.base.RequestWrapper;

import org.springframework.stereotype.Component;

import javax.servlet.*;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;

 

/**

  * @author robin.zhang

  * @date $

  * @description 解决request数据流只能读取一次的问题

  */

@Component

public class RequestFilter 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 {

             filterChain.doFilter(requestWrapper, servletResponse);

         }

     }

 

     @Override

     public void destroy() {

     }

}

然后注册这个过滤器到spring容器中,问题解决!

使用拦截器时,controller中不能再次获取body中的参数

报错信息: 从报错信息可以看出,io流已经关闭。这是由于拦截器读取了body中的参数信息,导致controller不能再次读取。

I/O error while reading input message; nested exception is java.io.IOException: Stream closed

解决办法

在拦截器读取到body信息后,再次将内容写入

1、获取body信息

?

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

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

import javax.servlet.ReadListener;

import javax.servlet.ServletInputStream;

import javax.servlet.ServletRequest;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

import java.io.*;

import java.nio.charset.Charset;

 

/**

  * 保存流

  */

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {

     private final byte [] body;

     public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) {

         super (request);

         String sessionStream = getBodyString(request);

         body = sessionStream.getBytes(Charset.forName( "UTF-8" ));

     }

 

     /**

      * 获取请求Body

      *

      * @param request

      * @return

      */

     public String getBodyString( final ServletRequest request) {

         StringBuilder sb = new StringBuilder();

         InputStream inputStream = null ;

         BufferedReader reader = null ;

         try {

             inputStream = cloneInputStream(request.getInputStream());

             reader = new BufferedReader( new InputStreamReader(inputStream, Charset.forName( "UTF-8" )));

             String line = "" ;

             while ((line = reader.readLine()) != null ) {

                 sb.append(line);

             }

         } catch (IOException e) {

             e.printStackTrace();

         } finally {

             if (inputStream != null ) {

                 try {

                     inputStream.close();

                 } catch (IOException e) {

                     e.printStackTrace();

                 }

             }

             if (reader != null ) {

                 try {

                     reader.close();

                 } catch (IOException e) {

                     e.printStackTrace();

                 }

             }

         }

         return sb.toString();

     }

 

     /**

      * Description: 复制输入流</br>

      *

      * @param inputStream

      * @return</br>

      */

     public InputStream cloneInputStream(ServletInputStream inputStream) {

         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

         byte [] buffer = new byte [ 1024 ];

         int len;

         try {

             while ((len = inputStream.read(buffer)) > - 1 ) {

                 byteArrayOutputStream.write(buffer, 0 , len);

             }

             byteArrayOutputStream.flush();

         } catch (IOException e) {

             e.printStackTrace();

         }

         InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

         return byteArrayInputStream;

     }

 

     @Override

     public BufferedReader getReader() throws IOException {

         return new BufferedReader( new InputStreamReader(getInputStream()));

     }

 

     @Override

     public ServletInputStream getInputStream() throws IOException {

         final ByteArrayInputStream bais = new ByteArrayInputStream(body);

         return new ServletInputStream() {

 

             @Override

             public int read() throws IOException {

                 return bais.read();

             }

 

             @Override

             public boolean isFinished() {

                 return false ;

             }

 

             @Override

             public boolean isReady() {

                 return false ;

             }

 

             @Override

             public void setReadListener(ReadListener readListener) {

             }

         };

     }

}

2、重新写入

?

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

import org.springframework.core.annotation.Order;

import javax.servlet.*;

import javax.servlet.annotation.WebFilter;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;

// 表示执行过滤顺序,值越小,越先执行

@Order ( 1 )

// 配置需要过滤的地址

@WebFilter (filterName = "bodyReaderFilter" , urlPatterns = "/*" )

public class BodyReaderFilter implements Filter {

 

     @Override

     public void init(FilterConfig filterConfig) throws ServletException {

//        System.out.println("--------------过滤器初始化------------");

     }

 

     @Override

     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

//        System.out.println("--------------执行过滤操作------------");

 

         // 防止流读取一次后就没有了, 所以需要将流继续写出去

         HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

         ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest);

         filterChain.doFilter(requestWrapper, servletResponse);

     }

 

     @Override

     public void destroy() {

//        System.out.println("--------------过滤器销毁------------");

     }

}

3、注册过滤器

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.web.servlet.ServletComponentScan;

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

import org.springframework.cloud.openfeign.EnableFeignClients;

 

@SpringBootApplication

@EnableFeignClients

@EnableDiscoveryClient

// 注册过滤器注解

@ServletComponentScan

public class WebPlatformApplication {

     public static void main(String[] args) {

         SpringApplication.run(WebPlatformApplication. class );

     }

}

添加完成后,运行正常!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/bai120552717/article/details/98062171

查看更多关于在拦截器中读取request参数,解决在controller中无法二次读取的问题的详细内容...

  阅读:29次