Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在筛选器中获取请求_Java_Spring_Web Services_Servlet Filters - Fatal编程技术网

Java 如何在筛选器中获取请求

Java 如何在筛选器中获取请求,java,spring,web-services,servlet-filters,Java,Spring,Web Services,Servlet Filters,我想在RESTWeb服务项目中记录请求主体的所有请求和消息。 我使用Spring和json消息转换器。 但是我面临java.lang.IllegalStateException:这个请求已经调用了getReader()。 我怎样才能解决这个问题?或 还有别的办法吗 web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/

我想在RESTWeb服务项目中记录请求主体的所有请求和消息。 我使用Spring和json消息转换器。 但是我面临java.lang.IllegalStateException:这个请求已经调用了getReader()。 我怎样才能解决这个问题?或 还有别的办法吗

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/root-context.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>LogFilter</filter-name>
        <filter-class>com.cmpolaris.system.LogFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LogFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
我面临这个例外

INFO : com.cmpolaris.system.LogFilter - IP 192.168.1.95, Time Wed Sep 03 13:23:31 MMT 2014
    INFO : com.cmpolaris.system.LogFilter - Request Message
    INFO : com.cmpolaris.system.LogFilter - {"userId":"KTT","pwd":"ktdt","devID":"","userGroup":"SaleMan"}
    Sep 3, 2014 1:23:31 PM org.apache.catalina.core.StandardWrapperValve invoke
    SEVERE: Servlet.service() for servlet [appServlet] in context with path [/cmpolaris] threw exception [Request processing failed; nested exception is java.lang.IllegalStateExcepti
    on: getReader() has already been called for this request] with root cause
    java.lang.IllegalStateException: getReader() has already been called for this request
        at org.apache.catalina.connector.Request.getInputStream(Request.java:1052)
        at org.apache.catalina.connector.RequestFacade.getInputStream(RequestFacade.java:368)
        at org.springframework.http.server.ServletServerHttpRequest.getBody(ServletServerHttpRequest.java:131)
        at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(MappingJackson2HttpMessageConverter.java:178)
        at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.read(MappingJackson2HttpMessageConverter.java:173)
        at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.
    java:143)
        at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:180)
        at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:95)
        at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77)
        at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:123)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at com.cmpolaris.system.LogFilter.doFilter(LogFilter.java:32)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)

你知道请求转储程序过滤器吗?
根据使用tomcat的堆栈跟踪,请参阅了解用法。

将请求对象包装到另一个类,然后再转发到链过滤器。 这样,就可以避免使用流问题

例如,您可以使用此类:

在您的第一个过滤器中,首先将其包装:

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        // use wrapper to read multiple times the content
        AuthenticationRequestWrapper request = new AuthenticationRequestWrapper((HttpServletRequest) req);
        HttpServletResponse response = (HttpServletResponse) resp;
        chain.doFilter(request,response);
}

使用的子类之一,并将
includePayload
属性设置为
true
(默认值为
false

假设您希望使用使用Commons日志记录来记录消息,请将添加到web.xml并为
includePayload
属性包含init参数

<filter>
    <filter-name>LogFilter</filter-name>
    <filter-class>org.springframework.web.filter.CommonsRequestLoggingFilter</filter-class>
    <init-param>
        <param-name>includePayload</param-name>
        <param-value>true</param-value>
    </init-param>    
</filter>
<filter-mapping>
    <filter-name>LogFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

对数滤波器
org.springframework.web.filter.commonRequestLoggingFilter
包括付款
真的
对数滤波器
/*
要包含有关客户端(用户、会话ID、客户端)的更多信息,请将
includeClientInfo
属性设置为
true

只有在调试日志记录打开时才会记录消息,因此请确保
commonRequestLoggingFilter
的日志级别至少为
debug


过滤器将把请求包装在一个包装器中,这样您就可以多次读取请求。

看看请求包装器&BTW with getRemoteAddr-您不能相信它是客户端的IPR,您想用过滤器做什么?您正在过滤器中调用getReader(),而您的servlet尝试在之后的某个地方调用getInputStream()(通常在呈现某些内容时)。因此出现了例外。是的,我只是在测试。。。我想得到请求体,即使这个请求是400个错误的请求。我发现如何获取请求正文的消息。他们说的是getReader()和getInputStream()。但是我不行。请求包装器在这里可以正常工作。不确定是否有更好的方法可用于springSpring,Spring已经提供了这样做的过滤器。请看一下的子类。不需要自己写。
public class AuthenticationRequestWrapper extends HttpServletRequestWrapper {

    private final String payload;

    public AuthenticationRequestWrapper (HttpServletRequest request) throws AuthenticationException {
        super(request);

        // read the original payload into the payload variable
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        try {
            // read the payload into the StringBuilder
            InputStream 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 {
                // make an empty string since there is no payload
                stringBuilder.append("");
            }
        } catch (IOException ex) {
            log.error("Error reading the request payload", ex);
            throw new AuthenticationException("Error reading the request payload", ex);
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException iox) {
                    // ignore
                }
            }
        }
        payload = stringBuilder.toString();
    }

    @Override
    public ServletInputStream getInputStream () throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(payload.getBytes());
        ServletInputStream inputStream = new ServletInputStream() {
            public int read () 
                throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return inputStream;
    }
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        // use wrapper to read multiple times the content
        AuthenticationRequestWrapper request = new AuthenticationRequestWrapper((HttpServletRequest) req);
        HttpServletResponse response = (HttpServletResponse) resp;
        chain.doFilter(request,response);
}
<filter>
    <filter-name>LogFilter</filter-name>
    <filter-class>org.springframework.web.filter.CommonsRequestLoggingFilter</filter-class>
    <init-param>
        <param-name>includePayload</param-name>
        <param-value>true</param-value>
    </init-param>    
</filter>
<filter-mapping>
    <filter-name>LogFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>