解决request.getInputStream()只能获取一次的问题,同时修改request及response

刚到公司的时候,公司可以说是什么都没有,开发人员也就我和另一个负责基础库的大神,凡事多请教和自己摸索,也学到了很多东西,是时候做个整理了,方便自己,方便他人。
刚到公司只有一个原来外包人员开发的系统,而现在公司需要废弃这个系统,新开发全新的系统,但需要对正在使用老系统的客户做平滑过渡,所以新的系统需要对老系统进行API上的兼容,同时新客户又可以通过新的API进行数据推送,比如老系统使用username、password提交用户名密码,而新的系统通过account、password提交,老系统response中为messages、code,而新的系统则为message、errorCode,这就是需求的背景。
看到需求的时候首先想到的就是在filter中进行修改,但同时需要注意的是,在filter中request.getInputStream()取出请求后,在后面就会拿不到请求数据了,即一个InputStream对象在被读取完成后,将无法被再次读取。所以必须将读取出的数据进行缓存。有了以上的考虑之后,就有了如下的代码实现。走起!

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.StreamUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * 做兼容性处理的过滤器
 * @author DiCaprito
 */
public class UpdateReqRespFilter implements Filter {
    private static final Map URL_REWRITE_MAP = new HashMap() {{
        put("/tws/app/tws/WvPallet/save", "/api/admin/sync/business/sync.htm");
    }};
    private static final Map LOGIN_REWRITE_MAP = new HashMap() {{
        put("/tws/public/mag/login", "/___/auth/login-by-password.htm");
    }};

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (isDeprecatedRequest(request)) {
            RequestWrapper requestWrapper = new RequestWrapper((HttpServletRequest) request);
            ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);
            chain.doFilter(requestWrapper, responseWrapper);
            response.getWriter().write(modifyResponse(responseWrapper.toString()));
        }
        else if (isLoginRequest(request)) {
            LoginRequestWrapper requestWrapper = new LoginRequestWrapper((HttpServletRequest) request);
            ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);
            chain.doFilter(requestWrapper, responseWrapper);
            response.getWriter().write(modifyLoginResponse(responseWrapper.toString()));
        }
        else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {
    }

    private boolean isDeprecatedRequest(ServletRequest request) {
        return URL_REWRITE_MAP.containsKey(((HttpServletRequest) request).getRequestURI());
    }

    private boolean isLoginRequest(ServletRequest request) {
        return LOGIN_REWRITE_MAP.containsKey(((HttpServletRequest) request).getRequestURI());
    }

    private String modifyResponse(String originalResult) {
        String result = originalResult;
        result = StringUtils.replace(result,"\"message\":", "\"messages\":");
        result = StringUtils.replace(result,"\"errorCode\":", "\"code\":");
        return result;
    }

    private String modifyLoginResponse(String originalResult) {
        String result = originalResult;
        result = StringUtils.replace(result, "\"data\":{", "\"data\":[{");
        int index = result.indexOf("}", result.indexOf("\"data\":[{"));
        result = result.substring(0, index) + "}]" + result.substring(index + 1);
        result = StringUtils.replace(result,"\"message\":", "\"messages\":");
        result = StringUtils.replace(result,"\"errorCode\":", "\"code\":");
        return result;
    }

    private static class RequestWrapper extends HttpServletRequestWrapper {
        public RequestWrapper(HttpServletRequest request) {
            super(request);
        }

        @Override
        public String getRequestURI() {
            String originalUri = super.getRequestURI();
            String newUri = URL_REWRITE_MAP.get(originalUri);
            return newUri != null ? newUri : originalUri;
        }
    }

    private static class LoginRequestWrapper extends HttpServletRequestWrapper {
        private byte[] requestBody = null;

        public LoginRequestWrapper(HttpServletRequest request) {
            super(request);
            //缓存请求body
            try {
                requestBody = StreamUtils.copyToByteArray(request.getInputStream());
                String result = new String(requestBody,"UTF-8");
                result = result.replace("\"username\":", "\"account\":");
                requestBody = result.getBytes("UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public String getRequestURI() {
            String originalUri = super.getRequestURI();
            String newUri = LOGIN_REWRITE_MAP.get(originalUri);
            return newUri != null ? newUri : originalUri;
        }

        @Override
        public ServletInputStream getInputStream() throws IOException {
            if(requestBody == null){
                requestBody= new byte[0];
            }
            final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);
            return new ServletInputStream() {
                @Override
                public int read() throws IOException {
                    return bais.read();
                }
            };
        }

        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(getInputStream(), "utf-8"));
        }
    }

    private static class ResponseWrapper extends HttpServletResponseWrapper {
        private CharArrayWriter output;

        public ResponseWrapper(HttpServletResponse response) {
            super(response);
            output = new CharArrayWriter();
        }

        @Override
        public PrintWriter getWriter() {
            return new PrintWriter(output);
        }

        @Override
        public String toString() {
            return output.toString();
        }
    }
}

同时记得在web.xml中配置servlet和filter,大功告成。

你可能感兴趣的:(request修改,response修改,filter,java)