SpringBoot2.x之在攔截器獲取http請求的json數據公共參數的驗證


HTTP請求中的是字符串數據

//字符串讀取
void charReader(HttpServletRequest request) {
    BufferedReader br = request.getReader();
    String str, wholeStr = "";
    while((str = br.readLine()) != null){
       wholeStr += str;
    }
    System.out.println(wholeStr);
}
//二進制讀取
void binaryReader(HttpServletRequest request) {
     int len = request.getContentLength();
     ServletInputStream iii = request.getInputStream();
     byte[] buffer = new byte[len];
     iii.read(buffer, 0, len);
}

注意:
request.getInputStream(); request.getReader(); 和request.getParameter("key");
這三個函數中任何一個函數執行一次后(可正常讀取body數據),之后再執行就無效了,比如在Controller里面就不能再調用了。

解決方法: 包裝HttpServletRequest對象,緩存body數據,再次讀取的時候將緩存的值寫出

 

新建RequestWrapper

import lombok.extern.slf4j.Slf4j;
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;

/**
 * @description 包裝HttpServletRequest,目的是讓其輸入流可重復讀
 **/
@Slf4j
public class RequestWrapper extends HttpServletRequestWrapper {
    /**
     * 存儲body數據的容器
     */
    private final byte[] body;

    public RequestWrapper(HttpServletRequest request) throws IOException {
        super(request);

        // 將body數據存儲起來
        String bodyStr = getBodyString(request);
        body = bodyStr.getBytes(Charset.defaultCharset());
    }

    /**
     * 獲取請求Body
     *
     * @param request request
     * @return String
     */
    public String getBodyString(final ServletRequest request) {
        try {
            return inputStream2String(request.getInputStream());
        } catch (IOException e) {
            log.error("", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 獲取請求Body
     *
     * @return String
     */
    public String getBodyString() {
        final InputStream inputStream = new ByteArrayInputStream(body);

        return inputStream2String(inputStream);
    }

    /**
     * 將inputStream里的數據讀取出來並轉換成字符串
     *
     * @param inputStream inputStream
     * @return String
     */
    private String inputStream2String(InputStream inputStream) {
        StringBuilder sb = new StringBuilder();
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.defaultCharset()));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            log.error("", e);
            throw new RuntimeException(e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
        }

        return sb.toString();
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {

        final ByteArrayInputStream inputStream = new ByteArrayInputStream(body);

        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return inputStream.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
            }
        };
    }
}

 

新建RequestWrapperFilter

import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @description RequestWrapperFilter
 **/
@Slf4j
@WebFilter(filterName = "requestWrapperFilter", urlPatterns = "/*")
public class RequestWrapperFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("RequestWrapperFilter初始化...");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ServletRequest requestWrapper = new RequestWrapper((HttpServletRequest) request);
        chain.doFilter(requestWrapper, response);
    }

    @Override
    public void destroy() {
        log.info("RequestWrapperFilter 銷毀...");
    }
}

springboot啟動類增加@ServletComponentScan注解

在攔截器就可以獲取請求參數了

新建一個攔截器ApiInterceptor

@Slf4j
public class ApiInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        Gson gson = new GsonBuilder().serializeNulls().enableComplexMapKeySerialization().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
        String requestUrl = request.getServletPath();
        String requestJson = new RequestWrapper(request).getBodyString();
        Map parameterMap = gson.fromJson(requestJson, Map.class);
        log.info(" 請求地址為: " + requestUrl + " 請求參數為: " + requestJson);

        try {
            if (parameterMap.get("appId") == null || parameterMap.get("appId").toString() == "") {
                responseJson(response, gson.toJson(WrapMapper.wrap(Wrapper.ERROR_CODE, "appId 參數錯誤或不存在")));
                return false;
            }
            return true;
        } catch (Exception e) {
            log.error(e.toString());
            return false;
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

    }

    private void responseJson(HttpServletResponse response, String json) throws Exception {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/json; charset=utf-8");
        try {
            log.info(json);
            writer = response.getWriter();
            writer.print(json);
        } catch (IOException e) {
            log.error(e.toString());
        } finally {
            if (writer != null)
                writer.close();
        }
    }
}

 

WebMvcConfig增加攔截器配置

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Bean
    public ApiInterceptor getApiInterceptor() {
        System.out.println("注入了 ApiInterceptor");
        return new ApiInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 多個攔截器組成一個攔截器鏈
        // addPathPatterns 用於添加攔截規則
        // excludePathPatterns 排除攔截
        String[] excludePaths = {
                "/login"
        };
        registry.addInterceptor(getApiInterceptor()).addPathPatterns("/**").excludePathPatterns(Arrays.asList(excludePaths));
    }
}

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM