Springboot如何利用拦截器拦截请求信息收集到日志详解

网友投稿 1367 2022-12-19

Springboot如何利用-拦截请求信息收集到日志详解

Springboot如何利用-拦截请求信息收集到日志详解

目录1、需求2、问题2、获取1)导入依赖为了获取客户端类型、操作系统类型、ip、port2)封装获取body字符串的工具类3)-类4)继承 HttpServletRequestWrapper类5)过滤器类6)-过滤器配置类总结

1、需求

最近在工作中遇到的一个需求,将请求中的客户端类型、操作系统类型、ip、port、请求方式、URI以及请求参数值收oyzsQNh集到日志中,网上找资料说用-拦截所有请求然后收集信息,于是就开始了操作:

2、问题

试了之后发现当请求方式为POST,前端发送数据json时只能用request.getReader()流获取,自信满满从流中获取之后发现请求之后报错:

getInputStream() has already been called for this request...

于是网上找答案,发现是ServletRequest的getReader()和getInputStream()两个方法只能被调用一次,而且不能两个都调用。那么如果Filter中调用了一次,在Controller里面就不能再调用了。

然后又开始找解决方法,说既然ServletInputStream不支持重新读写,就把流读出来后用容器存储起来,后面就可以多次利用了。

于是继承 HttpServletRequestWrapper类(http请求包装器,其基于装饰者模式实现了HttpServletRequest界面)并实现想要重新定义的方法以达到包装原生HttpServletRequest对象。还需要在过滤器里将原生的HttpServletRequest对象替换成我们的RequestWrapper对象。

测试发现POST请求参数值可以在-类中获取到了,本以为大功告成,又发现GET请求不好使了,开始报错Stream closed,一顿操作发现需要在过滤器进行判断,如果是POST请求走自己的继承的HttpServletRequestWrapper类请求,否则走普通的请求。终于成功!突然舒服了。

2、获取

1)导入依赖为了获取客户端类型、操作系统类型、ip、port

eu.bitwalker

UserAgentUtils

1.21

2)封装获取body字符串的工具类

package com.btrc.access.util;

import javax.servlet.http.HttpServletRequest;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.nio.charset.Charset;

public class RequestUtil {

public static String getBodyString(HttpServletRequest request) {

StringBuilder sb = new StringBuilder();

try (

InputStream inputStream = request.getInputStream();

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")))

) {

String line;

while ((line = reader.readLine()) != null) {

sb.append(line);

}

} catch (IOException e) {

e.printStackTrace();

}

return sb.toString();

}

}

3)-类

package com.btrc.access.filter;

import com.btrc.access.util.RequestUtil;

import eu.bitwalker.useragentutils.UserAgent;

import org.apache.commons.lang.StringUtils;

import org.springframework.http.HttpMethod;

import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

/**

* 请求-:拦截请求目的是将请求的信息收集到日志

*/

public class RequestInterceptor implements HandlerInterceptor {

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

UserAgent userAgent = UserAgent.parseUserAhttp://gentString(request.getHeader("user-agent"));

//客户端类型

String clientType = userAgent.getOperatingSystem().getDeviceType().getName();

//客户端操作系统类型

String osType = userAgent.getOperatingSystem().getName();

//客户端ip

String clientIp = request.getRemoteAddr();

//客户端port

int clientPort = request.getRemotePort();

//请求方式

String requestMethod = request.getMethod();

//客户端请求URI

String requestURI = request.getRequestURI();

//客户端请求参数值

String requestParam;

//如果请求是POST获取body字符串,否则GET的话用request.getQueryString()获取参数值

if(StringUtils.equalsIgnoreCase(HttpMethod.POST.name(), requestMethod)){

requestParam = RequestUtil.getBodyString(request);

}else{

requestParam = request.getQueryString();

}

//客户端整体请求信息

StringBuilder clientInfo = new StringBuilder();

clientInfo.append("客户端信息:[类型:").append(clientType)

.append(", 操作系统类型:").append(osType)

.append(", ip:").append(clientIp)

.append(", port:").append(clientPort)

.append(", 请求方式:").append(requestMethod)

.append(", URI:").append(requestURI)

.append(", 请求参数值:").append(requestParam.replaceAll("\\s*", ""))

.append("]"oyzsQNh);

//***这里的clientInfo就是所有信息了,请根据自己的日志框架进行收集***

System.out.println(clientInfo);

//返回ture才会继续执行,否则一直拦截住

return true;

}

}

4)继承 HttpServletRequestWrapper类

package com.btrc.access.filter;

import com.btrc.access.util.RequestUtil;

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.Charset;

public class AccessRequestWrapper extends HttpServletRequestWrapper {

private final byte[] body;

public AccessRequestWrapper(HttpServletRequest request) {

super(request);

body = RequestUtil.getBodyString(request).getBytes(Charset.forName("UTF-8"));

}

@Override

public BufferedReader getReader() throws IOException {

return new BufferedReader(new InputStreamReader(getInputStream()));

}

@Override

public ServletInputStream getInpuoyzsQNhtStream() throws IOException {

final ByteArrayInputStream bais = new ByteArrayInputStream(body);

return new ServletInputStream() {

@Override

public int read() throws IOException {

return bais.read();

}

@Override

public boolean isFinished() {

return false;

}

@Override

public boolean isReady() {

return false;

}

@Override

public void setReadListener(ReadListener readListener) {

}

};

}

}

5)过滤器类

package com.btrc.access.filter;

import org.apache.commons.lang.StringUtils;

import org.springframework.http.HttpMethod;

import javax.servlet.*;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

public class AccessFilter implements Filter {

@Override

public void init(FilterConfig filterConfig) throws ServletException {

}

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) servletRequest;

//如果是POST走自己的继承的HttpServletRequestWrapper类请求,否则走正常的请求

if(StringUtils.equalsIgnoreCase(HttpMethod.POST.name(), request.getMethod())){

//一定要在判断中new对象,否则还会出现Stream closed问题

filterChain.doFilter(new AccessRequestWrapper(request),servletResponse);

}else{

filterChain.doFilter(servletRequest,servletResponse);

}

}

@Override

public void destroy() {

}

}

6)-过滤器配置类

package com.btrc.access.config;

import com.btrc.access.filter.AccessFilter;

import com.btrc.access.filter.RequestInterceptor;

import org.springframework.boot.web.servlet.FilterRegistrationBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.Filter;

/**

* -过滤器配置类

*/

@Configuration

public class WebMvcConfig implements WebMvcConfigurer {

@Bean

public FilterRegistrationBean httpServletRequestReplacedFilter() {

FilterRegistrationBean registration = new FilterRegistrationBean();

registration.setFilter(new AccessFilter());

// /* 是全部的请求拦截,和Interceptor的拦截地址/**区别开

registration.addUrlPatterns("/*");

registration.setName("accessRequestFilter");

registration.setOrder(1);

return registration;

}

@Override

public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(new RequestInterceptor()).addPathPatterns("/**");

}

}

总结

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:构建Maven多模块项目的方法
下一篇:使用Springboot实现word在线编辑保存
相关文章

 发表评论

暂时没有评论,来抢沙发吧~