filter过滤器,解决request获取前端参数中,参数以json流的形式传输的问题

29 篇文章 0 订阅

1、复制流的工具

import jodd.io.StreamUtil;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Created by Administrator on 2018/1/12 0012.
 */
public class MAPIHttpServletRequestWrapper extends HttpServletRequestWrapper {
    private final byte[] body;

    /**
     * Constructs a request object wrapping the given request.
     *
     * @param request
     * @throws IllegalArgumentException if the request is null
     */
    public MAPIHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = StreamUtil.readBytes(request.getInputStream());
    }

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

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            /**
             * Returns true if data can be read without blocking else returns
             * false.
             *
             * @return <code>true</code> if data can be obtained without blocking,
             * otherwise returns <code>false</code>.
             * @since Servlet 3.1
             */
            @Override
            public boolean isReady() {
                return false;
            }

            /**
             * Instructs the <code>ServletInputStream</code> to invoke the provided
             * {@link ReadListener} when it is possible to read
             *
             * @param readListener the {@link ReadListener} that should be notified
             *                     when it's possible to read.
             * @throws IllegalStateException if one of the following conditions is true
             *                               <ul>
             *                               <li>the associated request is neither upgraded nor the async started
             *                               <li>setReadListener is called more than once within the scope of the same request.
             *                               </ul>
             * @throws NullPointerException  if readListener is null
             * @since Servlet 3.1
             */
            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }
}
2、拦截器

import com.alibaba.fastjson.JSON;
import com.atc.beans.logger.LogParamVO;
import com.atc.beans.system.UserInfo;
import com.atc.framework.common.logger.LoggerService;
import com.atc.framework.common.utils.httprequest.MAPIHttpServletRequestWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * Created by Administrator on 2018/1/12 0012.
 */
public class ParamFilter implements Filter {
    private static final Logger LOGGER = LoggerFactory.getLogger(ParamFilter.class);

    @Autowired
    private LoggerService loggerService;

    /**
     * @param filterConfig
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    /**
     * @param request
     * @param response
     * @param chain
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ServletRequest servletRequest = loggerService.writeLog(request);
        chain.doFilter(servletRequest,response);
    }

    @Override
    public void destroy() {

    }

}

3、拦截器中需要执行的方法

import com.alibaba.fastjson.JSON;
import com.atc.beans.logger.LogParamVO;
import com.atc.beans.system.UserInfo;
import com.atc.framework.common.utils.httprequest.MAPIHttpServletRequestWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * Created by Administrator on 2018/1/12 0012.
 */
@Service
public class LoggerServiceImpl implements LoggerService {
    private static final Logger LOGGER = LoggerFactory.getLogger(LoggerServiceImpl.class);
    @Override
    public ServletRequest writeLog(ServletRequest request) throws IOException {
        ServletRequest requestWrapper = null;
        if (request instanceof HttpServletRequest) {
            requestWrapper = new MAPIHttpServletRequestWrapper((HttpServletRequest) request);
        }

        String requestURL = ((HttpServletRequest) requestWrapper).getRequestURL().toString();

        //获取json
        String contentType = requestWrapper.getContentType();
        String paramJson = "";
        if ("application/json; charset=UTF-8".equals(contentType)) {
            paramJson = this.getJsonParam((HttpServletRequest) requestWrapper);
        } else {
            paramJson = JSON.toJSONString(requestWrapper.getParameterMap());
        }
        LogParamVO logParamVO = new LogParamVO(yhxm, ip, requestURL, browser, paramJson);

        LOGGER.info("【Filter过滤用户操作日志】{}", JSON.toJSONString(logParamVO));

        if (requestWrapper == null) {
           return request;
        } else {
            return  requestWrapper;
        }
    }

    /**
     * 获取Json数据
     *
     * @param request
     * @return
     */
    private String getJsonParam(HttpServletRequest request) {
        String jsonParam = "";
        ServletInputStream inputStream = null;
        try {
            int contentLength = request.getContentLength();
            if (!(contentLength < 0)) {
                byte[] buffer = new byte[contentLength];
                inputStream = request.getInputStream();
                for (int i = 0; i < contentLength; ) {
                    int len = inputStream.read(buffer, i, contentLength);
                    if (len == -1) {
                        break;
                    }
                    i += len;
                }
                jsonParam = new String(buffer, "utf-8");
            }
        } catch (IOException e) {
            LOGGER.error("参数转换成json异常g{}", e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    LOGGER.error("参数转换成json异常s{}", e);
                }
            }
        }
        return jsonParam;
    }


}



网关过滤器通常用于处理HTTP请求和响应,在网关层面进行拦截、处理和转发。在使用网关过滤器获取请求体(body)参数时,需要注意请求体的类型和内容大小。通常,如果请求体是JSON格式,可以通过解析JSON获取参数;如果请求体是表单数据,则可以按照表单的格式解析获取参数。 以JavaSpring Cloud Gateway为例,可以使用`GatewayFilter`接口实现自定义的过滤逻辑来读取和修改请求体。以下是一个简单的示例: ```java import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; @Component public class BodyFilter extends AbstractGatewayFilterFactory<BodyFilter.Config> { public BodyFilter() { super(Config.class); } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest(); // 检查请求体是否可读 if (request.getMethodValue().equalsIgnoreCase("POST") && request.getHeaders().getContentType().equals(MediaType.APPLICATION_JSON)) { Mono<String> modifiedBody = request.getBody() .map(data -> { // 将数据转换为字符串 String requestBody = new String(data.array()); // 解析JSON字符串并获取参数 // 示例:假设我们要获取一个名为"param"的参数 // String paramValue = ...; // 修改参数后重新设置请求体 // requestBody = requestBody.replace("旧值", "新值"); return requestBody; }) .defaultIfEmpty("") .map(body -> exchange.getRequest().mutate().body(BodyInserters.fromValue(body)).build()); // 使用修改后的请求体创建新的ServerHttpRequest ServerHttpRequest mutableReq = modifiedBody.map(body -> exchange.getRequest().mutate().body(BodyInserters.fromValue(body)).build()).block(); return chain.filter(exchange.mutate().request(mutableReq).build()); } return chain.filter(exchange); }; } public static class Config { // 配置字段 } } ``` 在这个示例过滤器只处理了POST请求,并且只处理了内容类型为`application/json`的请求体。如果请求体是JSON格式,它会被转换为字符串,然后可以进行进一步的解析和修改。注意,由于`ServerHttpRequest.BodyContent`是一个只读的,所以这里使用了`map`来转换和重新封装请求体。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值