java打印请求参数日志

之前写过一篇博客,是通过拦截器的方式对所有http请求进行日志打印,但是这有一个严重的问题,那就是body数据只能从流里取出来一次,虽然通过复制的方式解决了这个问题,却又引入新的问题。
项目进行流读取及流复制的操作是一件非常消耗CPU资源的一件事,当并发数不高的时候服务会很正常,但是并发数高起来之后就需要更多的CPU核数来支持服务运行。正因为上述考虑,随后将日志从拦截器中改为了aop,这样就不存在多次读取流的问题,本质上切面拿的是controller层方法入参,跟servlet就无关了。
具体代码如下:

@Component
@Aspect
@Slf4j
public class LogCollectionAop {

    @Resource(name = "headKafkaTemplate")
    private KafkaTemplate<String, String> headKafkaTemplate;
    @Value("${spring.kafka.header-topic}")
    private String headerTopic;

    @Pointcut("execution(* com.sohu.mp.appletbackend.controller.*.*(..))")
    public void log(){}

    @Before("log()")
    //只有@Around注解才能配合使用ProceedingJoinPoint,其他方法用JoinPoint。少了proceed()方法
    public void doBefore(JoinPoint pjp) throws Throwable {
        ServletRequestAttributes servletAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        assert servletAttributes != null;
        HttpServletRequest request = servletAttributes.getRequest();
        getHeaderLog(request,pjp);
    }

    private void getHeaderLog(HttpServletRequest request, JoinPoint pjp){
        //取参数,打印参数
        if (request.getMethod().equals("GET")){
        //get请求如果也用下边的方式取参数,会没有参数名称,所以还是从servlet中取
            getParam = request.getQueryString();;
        }
        if (request.getMethod().equals("POST")){
        //这么取,取出来的是方法的入参,不仅仅是body里的参数,body只是其中一项
            Object[] arguments = pjp.getArgs();
            StringBuilder sb = new StringBuilder();
            Arrays.stream(arguments).forEach(sb::append);
            body = StringUtils.trimAllWhitespace(sb.toString());
        }
    }
}

当然也能取出来参数名,但是取出来的是你命名的变量名,而不是@RequestParam(value="")中的value。不需要通过反射取参数名,通过下边这种方式即可。

			Object[] args = pjp.getArgs();
            MethodSignature methodSignature = (MethodSignature)pjp.getSignature();
            //获取参数名
            Parameter[] ps = methodSignature.getMethod().getParameters();
            String[] parameterNames = new String[ps.length];
            for (int i=0;i<ps.length;i++){
                parameterNames[i] = ps[i].getName();
            }
            // 通过map封装参数和参数值
            HashMap<String, String> paramMap = new HashMap();
            for (int i = 0; i < parameterNames.length; i++) {
                paramMap.put(parameterNames[i], StringUtils.trimAllWhitespace(String.valueOf(args[i])));
            }

拦截器打印参数

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过在过滤器中获取请求参数和响应结果并打印日志的方式来实现。 在过滤器中,可以通过HttpServletRequest对象获取请求参数,例如: ```java String queryString = request.getQueryString(); // 获取请求参数 ``` 而获取响应结果则需要在HttpServletResponse对象的输出流中进行捕获,例如: ```java // 获取响应输出流 PrintWriter writer = response.getWriter(); // 创建一个新的输出流 PrintWriter newWriter = new PrintWriter(new OutputStreamWriter(writer, "UTF-8"), true); // 将新输出流设置给HttpServletResponse对象 response.setCharacterEncoding("UTF-8"); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(result); // result为响应结果 // 捕获输出流中的内容 String responseResult = new String(writer.toString().getBytes("UTF-8")); ``` 在获取到请求参数和响应结果后,可以通过日志框架(如log4j、slf4j等)将其打印出来,例如: ```java import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RequestLoggingFilter implements Filter { private static final Logger logger = LoggerFactory.getLogger(RequestLoggingFilter.class); @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; String queryString = httpRequest.getQueryString(); // 获取请求参数 logger.info("Request URL: {}?{}", httpRequest.getRequestURL(), queryString); HttpServletResponse httpResponse = (HttpServletResponse) response; // 获取响应输出流 PrintWriter writer = httpResponse.getWriter(); // 创建一个新的输出流 PrintWriter newWriter = new PrintWriter(new OutputStreamWriter(writer, "UTF-8"), true); // 将新输出流设置给HttpServletResponse对象 httpResponse.setCharacterEncoding("UTF-8"); httpResponse.setContentType("application/json;charset=UTF-8"); // 捕获输出流中的内容 String responseResult = new String(writer.toString().getBytes("UTF-8")); logger.info("Response: {}", responseResult); // 继续执行过滤器链 chain.doFilter(request, response); } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } } ``` 以上就是在过滤器中实现请求参数和响应结果日志打印的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值