Spring MVC 3.2 @ResponseBody interceptor

后端 未结 4 2130
北荒
北荒 2021-02-05 22:28

In our application we are using JSON for request and response. The controller methods are annotated with @RequestBody(). The object being returned e.g. TransferResponse. I would

4条回答
  •  一生所求
    2021-02-05 22:47

    I finally have a working (but not elegant) solution for this case. I think that can have a better solution, but i can't find that.

    At first, i was created a Request and Response wrapper that encapsulates the payload, making my request Input Stream and response Output Stream reutilizable and overridable. I need to use this in my Filter to manipulate both the request and the response payloads.

    import java.io.BufferedReader;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletInputStream;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;
    
    import org.springframework.context.ApplicationContext;
    
    import br.com.vivo.core.controller.impl.utils.ApplicationContextUtils;
    
    import com.fasterxml.jackson.core.JsonFactory;
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    
    @WebFilter(urlPatterns = { "/*" })
    public class HeadBodyFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
    
            ApplicationContext applicationContext = ApplicationContextUtils.getApplicationContext();
    
            ObjectMapper objectMapper = (ObjectMapper) applicationContext.getBean("jacksonObjectMapper");
            JsonFactory jsonFactory = objectMapper.getFactory();
    
            ByteResponseWrapper byteResponseWrapper = new ByteResponseWrapper((HttpServletResponse) response);
            ByteRequestWrapper byteRequestWrapper = new ByteRequestWrapper((HttpServletRequest) request);
    
    
            String jsonRequestString = new String(byteRequestWrapper.getBytes());
            JsonParser requestParser = jsonFactory.createParser(jsonRequestString);
            JsonNode rootRequestNode = objectMapper.readTree(requestParser);
    
    
            if(rootRequestNode != null && rootRequestNode.has("body")) {
                JsonNode requestBody = rootRequestNode.get("body");
                writeJsonIntoRequest(byteRequestWrapper, requestBody, objectMapper);
            }
    
    
            chain.doFilter(byteRequestWrapper, byteResponseWrapper);
    
            String jsonResponseString = new String(byteResponseWrapper.getBytes(), response.getCharacterEncoding());
    
    
    
            JsonParser responseParser = jsonFactory.createParser(jsonResponseString);
            JsonNode rootResponseNode = objectMapper.readTree(responseParser);
    
            Object head = "Whoo hoo!";
    
            ObjectNode responseObjectWrapper = objectMapper.createObjectNode();
            responseObjectWrapper.put("head", objectMapper.valueToTree(head));
            responseObjectWrapper.put("body", rootResponseNode);
    
            writeJsonIntoResponse(response, responseObjectWrapper, objectMapper);
    
        }
    
    
        private void writeJsonIntoRequest(ByteRequestWrapper request,
                JsonNode requestBody, ObjectMapper objectMapper) throws IOException {
    
            String json = objectMapper.writeValueAsString(requestBody);
            request.replaceRequestPayload(json.getBytes());
    
        }
    
        @Override
        public void destroy() {
    
        }
    
    
    
        /**
         * Escreve o json no response
         * 
         * @param response
         * @param rootNode
         * @throws IOException
         */
        private void writeJsonIntoResponse(final ServletResponse response, final JsonNode responseBody, final ObjectMapper objectMapper) throws IOException {
    
            String json = objectMapper.writeValueAsString(responseBody);
    
            // escreve o json
            response.getOutputStream().write((json + "\r\n").getBytes(response.getCharacterEncoding()));
        }
    
    
    
        static class ByteResponseWrapper extends HttpServletResponseWrapper {
    
            private PrintWriter writer;
            private ByteOutputStream output;
    
            public byte[] getBytes() {
                writer.flush();
                return output.getBytes();
            }
    
            public ByteResponseWrapper(HttpServletResponse response) {
                super(response);
                output = new ByteOutputStream();
                writer = new PrintWriter(output);
            }
    
            @Override
            public PrintWriter getWriter() {
                return writer;
            }
    
            @Override
            public ServletOutputStream getOutputStream() throws IOException {
                return output;
            }
        }
    
    
    
        static class ByteRequestWrapper extends HttpServletRequestWrapper {
    
            byte[] requestBytes = null;
            private ByteInputStream byteInputStream;
    
    
            public ByteRequestWrapper(HttpServletRequest request) throws IOException {
                super(request);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
                InputStream inputStream = request.getInputStream();
    
                byte[] buffer = new byte[4096];
                int read = 0;
                while ( (read = inputStream.read(buffer)) != -1 ) {
                    baos.write(buffer, 0, read);
                }
    
                replaceRequestPayload(baos.toByteArray());
            }
    
            public byte[] getBytes() {
                return requestBytes;
            }
    
            @Override
            public BufferedReader getReader() throws IOException {
                return new BufferedReader(new InputStreamReader(getInputStream()));
            }
    
            @Override
            public ServletInputStream getInputStream() throws IOException {
                return byteInputStream;
            }
    
            public void replaceRequestPayload(byte[] newPayload) {
                requestBytes = newPayload;
                byteInputStream = new ByteInputStream(new ByteArrayInputStream(requestBytes));
            }
        }
    
        static class ByteOutputStream extends ServletOutputStream {
    
            private ByteArrayOutputStream bos = new ByteArrayOutputStream();
    
            @Override
            public void write(int b) throws IOException {
                bos.write(b);
            }
    
            public byte[] getBytes() {
                return bos.toByteArray();
            }
        }
    
        static class ByteInputStream extends ServletInputStream {
    
            private InputStream inputStream;
    
            public ByteInputStream(final InputStream inputStream) {
                this.inputStream = inputStream;
            }
    
            @Override
            public int read() throws IOException {
                return inputStream.read();
            }
    
        }
    
    }
    

提交回复
热议问题