SpringBoot下Request处理

背景:
1、SpringBoot下获取Request,打印日志或参数校验。
2、Request请求流不能重复读取。 java.lang.IllegalStateException: getReader() has already been called for this request 异常。
3、拦截时对于MultipartHttpServletRequest不能转换成自定义RequestWrapper

实现:
1、实现一个过滤器,对于所有请求路径。
2、对于文件请求类型multipart/不进行自定义处理
3、自定义RequestWrapper处理流,然后通过FilterChain传下去

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Objects;
import java.util.Optional;

@Order(1)//执行顺序的优先级
@Component
@WebFilter(filterName = "httpServletRequestFilter", urlPatterns = "/*") //过滤所有路径
public class RequestReplacedFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //文件上传类型不处理
        if (Objects.isNull(request) || Optional.ofNullable(request.getContentType()).orElse("").startsWith("multipart/")) {
            chain.doFilter(request, response);
            return;
        }
        //自定义RequestWrapper处理流,然后通过FilterChain传下去
        chain.doFilter( new RequestWrapper((HttpServletRequest) request), response);
    }
}

4、自定义RequestWrapper处理流,可重复读取inputStream

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

public class RequestWrapper extends HttpServletRequestWrapper {
    private final String body;

    public RequestWrapper(HttpServletRequest request) {
        super(request);
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        InputStream inputStream = null;
        try {
            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 {
                stringBuilder.append("");
            }
        } catch (IOException ex) {

        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        body = stringBuilder.toString();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
        ServletInputStream servletInputStream = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

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

            @Override
            public void setReadListener(ReadListener readListener) {
            }

            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return servletInputStream;

    }

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

    public String getBody() {
        return this.body;
    }
}

自定义拦截器,开始和结束时记录日志。

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Map;

@Component
@Slf4j
public class AccessLogInterceptor implements HandlerInterceptor {

    private static final String LOGGER_SEND_TIME = "SEND_TIME";

    /**
     * 在请求开始记录日志实体
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        request.setAttribute(LOGGER_SEND_TIME, System.currentTimeMillis());
        // 打印请求内容
        log.info("Request URL    :{}", request.getRequestURI());
        log.info("Request Method :{}", request.getMethod());
        log.info("Request IP :{}", AddressIpUtils.getIpAddress(request));
        if (request instanceof MultipartHttpServletRequest) {
            MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
            Map<String, String[]> parameterMap = multipartHttpServletRequest.getParameterMap();
            for (Map.Entry<String, String[]> stringEntry : parameterMap.entrySet()) {
                log.info("Request Param     :{}", stringEntry.getKey() + "=" + Arrays.toString(stringEntry.getValue()));
            }
            Map<String, MultipartFile> fileMap = multipartHttpServletRequest.getFileMap();
            for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
                MultipartFile file = entry.getValue();
                String fileName = file.getOriginalFilename();
                log.info("Request Param     :{}", fileName);
            }
        } else if (request instanceof RequestWrapper) {
            RequestWrapper requestWrapper = (RequestWrapper) request;
            log.info("Request Param     :{}", RequestUtil.getParameters(requestWrapper));
        }
        return true;
    }

    @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 {
        long current = System.currentTimeMillis();
        long sendTime = (long) request.getAttribute(LOGGER_SEND_TIME);
        log.info("Duration       :{}ms", current - sendTime);
        log.info("CreateTime     :{}", LocalDateTime.now());
        log.info("Http Status    :{}", response.getStatus());
    }
}

获取请求参数工具类

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class RequestUtil {

    public static String getParameters(RequestWrapper request) throws JsonProcessingException {
        if (StrUtil.isNotBlank(request.getBody())) return request.getBody();

        ObjectMapper mapper = new ObjectMapper();
        Enumeration<String> enume = request.getParameterNames();
        Map<String, Object> map = new HashMap<String, Object>();
        while (enume.hasMoreElements()) {
            String key = enume.nextElement();
            String value = request.getParameter(key);
            map.put(key, value);

        }
        return mapper.writeValueAsString(map);
    }
}
import javax.servlet.http.HttpServletRequest;

/**
 * 获取ip访问地址工具类
 */
public class AddressIpUtils {

    public static String getIpAddress(HttpServletRequest request) {
        String Xip = request.getHeader("X-Real-IP");
        String XFor = request.getHeader("X-Forwarded-For");
        if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
            //多次反向代理后会有多个ip值,第一个ip才是真实ip
            int index = XFor.indexOf(",");
            if(index != -1){
                return XFor.substring(0,index);
            }else{
                return XFor;
            }
        }
        XFor = Xip;
        if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
            return XFor;
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getRemoteAddr();
        }
        return XFor;
    }
}

拦截器注册

@Configuration
public class WebAppConfiguration implements WebMvcConfigurer {
    @Autowired
    AccessLogInterceptor accessLogInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(accessLogInterceptor).addPathPatterns("/**");
   }
}

你可能感兴趣的:(spring,boot,后端,java)