zoukankan      html  css  js  c++  java
  • web应用程序中解决Request和Response只能获取一次的问题

    由于Request和Response是用流的方式传递数据,所以只能读取一次。tomcat中已有SavedRequest类,没有SavedResponse类,我们创建两个容器类来装载Request/Response->写一个过滤器Filter拦截请求将Info装载入容器中。

    RequestWrapper:

     
     
    import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
    import com.longshine.luxicrmboot.commons.utils.ApplicationUtils;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.io.IOUtils;
    import org.springframework.util.StreamUtils;
    import org.springframework.web.util.HtmlUtils;
     
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import java.io.*;
    import java.nio.charset.StandardCharsets;
    import java.util.Objects;
     
     
    /**
     * Request包装类
     * <p>
     * 1.预防xss攻击
     * 2.拓展requestbody无限获取(HttpServletRequestWrapper只能获取一次)
     * </p>
     *
     * @author Caratacus
     */
    @Slf4j
    public class RequestWrapper extends HttpServletRequestWrapper {
     
        /**
         * 存储requestBody byte[]
         */
        private final byte[] body;
     
        public RequestWrapper(HttpServletRequest request) {
            super(request);
            byte[] body = new byte[0];
            try {
                body = StreamUtils.copyToByteArray(request.getInputStream());
            } catch (IOException e) {
                log.error("Error: Get RequestBody byte[] fail," + e);
            }
            this.body = body;
        }
     
        @Override
        public BufferedReader getReader() {
            ServletInputStream inputStream = getInputStream();
            return Objects.isNull(inputStream) ? null : new BufferedReader(new InputStreamReader(inputStream));
        }
     
        @Override
        public ServletInputStream getInputStream() {
            if (ObjectUtils.isEmpty(body)) {
                return null;
            }
            final ByteArrayInputStream bais = new ByteArrayInputStream(body);
            return new ServletInputStream() {
     
                @Override
                public boolean isFinished() {
                    return false;
                }
     
                @Override
                public boolean isReady() {
                    return false;
                }
     
                @Override
                @SuppressWarnings("EmptyMethod")
                public void setReadListener(ReadListener readListener) {
     
                }
     
                @Override
                public int read() {
                    return bais.read();
                }
            };
        }
     
        @Override
        public String[] getParameterValues(String name) {
            String[] values = super.getParameterValues(name);
            if (values == null) {
                return null;
            }
            int count = values.length;
            String[] encodedValues = new String[count];
            for (int i = 0; i < count; i++) {
                encodedValues[i] = htmlEscape(values[i]);
            }
            return encodedValues;
        }
     
        @Override
        public String getParameter(String name) {
            String value = super.getParameter(name);
            if (value == null) {
                return null;
            }
            return htmlEscape(value);
        }
     
        @Override
        public Object getAttribute(String name) {
            Object value = super.getAttribute(name);
            if (value instanceof String) {
                htmlEscape((String) value);
            }
            return value;
        }
     
        @Override
        public String getHeader(String name) {
            String value = super.getHeader(name);
            if (value == null) {
                return null;
            }
            return htmlEscape(value);
        }
     
        @Override
        public String getQueryString() {
            String value = super.getQueryString();
            if (value == null) {
                return null;
            }
            return htmlEscape(value);
        }
     
        /**
         * 使用spring HtmlUtils 转义html标签达到预防xss攻击效果
         *
         * @param str
         * @see org.springframework.web.util.HtmlUtils#htmlEscape
         */
        protected String htmlEscape(String str) {
            return HtmlUtils.htmlEscape(str);
        }
     
    }

    ResponseWrapper:

     
    import com.alibaba.fastjson.JSON;
    import com.google.common.base.Throwables;
    import com.longshine.luxicrmboot.commons.msg.AjaxResult;
    import com.longshine.luxicrmboot.commons.msg.ErrorCode;
    import io.swagger.annotations.ApiResponses;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.util.MimeTypeUtils;
     
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.nio.charset.StandardCharsets;
    import java.util.Objects;
     
    /**
     * response包装类
     *
     * @author Caratacus
     */
    @Slf4j
    public class ResponseWrapper extends HttpServletResponseWrapper {
     
        private ErrorCode errorcode;
     
        public ResponseWrapper(HttpServletResponse response) {
            super(response);
        }
     
        public ResponseWrapper(HttpServletResponse response, ErrorCode errorcode) {
            super(response);
            setErrorCode(errorcode);
        }
     
        /**
         * 获取ErrorCode
         *
         * @return
         */
        public ErrorCode getErrorCode() {
            return errorcode;
        }
     
        /**
         * 设置ErrorCode
         *
         * @param errorCode
         */
        public void setErrorCode(ErrorCode errorCode) {
            if (Objects.nonNull(errorCode)) {
                this.errorcode = errorCode;
                super.setStatus(this.errorcode.getHttpCode());
            }
        }
     
        /**
         * 向外输出错误信息
         *
         * @param e
         * @throws IOException
         */
        public void writerErrorMsg(Exception e) {
            if (Objects.isNull(errorcode)) {
                log.warn("Warn: ErrorCodeEnum cannot be null, Skip the implementation of the method.");
                return;
            }
            printWriterApiResponses(AjaxResult.failure(this.getErrorCode(), e));
        }
     
        /**
         * 设置ApiErrorMsg
         */
        public void writerErrorMsg() {
            writerErrorMsg(null);
        }
     
        /**
         * 向外输出AjaxResult
         *
         * @param ajaxResult
         */
        public void printWriterApiResponses(AjaxResult ajaxResult) {
            writeValueAsJson(ajaxResult);
        }
     
        /**
         * 向外输出json对象
         *
         * @param obj
         */
        public void writeValueAsJson(Object obj) {
            if (super.isCommitted()) {
                log.warn("Warn: Response isCommitted, Skip the implementation of the method.");
                return;
            }
            super.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE);
            super.setCharacterEncoding(StandardCharsets.UTF_8.name());
            try (PrintWriter writer = super.getWriter()) {
                writer.print(JSON.toJSONString(obj));
                writer.flush();
            } catch (IOException e) {
                log.warn("Error: Response printJson faild, stackTrace: {}", Throwables.getStackTraceAsString(e));
            }
        }
     
    }

    过滤器:

     
    import com.longshine.luxicrmboot.commons.wrapper.RequestWrapper;
    import org.springframework.stereotype.Component;
     
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
     
    /**
     * 记住Request/Response 过滤器
     * 解决Request/Response不能重复使用问题
     *
     * @author Caratacus
     */
    @Component
    @WebFilter(filterName = "crownFilter", urlPatterns = "/*")
    public class MemoryReqResFilter implements Filter {
     
        @Override
        @SuppressWarnings("EmptyMethod")
        public void destroy() {
        }
     
        @Override
        public void doFilter(ServletRequest request, ServletResponse res,
                             FilterChain chain) throws ServletException, IOException {
            HttpServletRequest req = (HttpServletRequest) request;
            chain.doFilter(new RequestWrapper(req), res);
        }
     
        @Override
        @SuppressWarnings("EmptyMethod")
        public void init(FilterConfig config) {
        }
     
    }
  • 相关阅读:
    make menuconfig出现乱码
    内存中的变量和值
    is&==
    python小整数池
    生成器
    GIL
    grub rescue问题修复
    期末考试
    期末要求
    选课练习
  • 原文地址:https://www.cnblogs.com/nizuimeiabc1/p/13060040.html
Copyright © 2011-2022 走看看