> 最近保全中心一期基本完成,准备在测试的时候对整体进行优化,在测试过程中,由于排查日志时的流水号没有日志打印 ,打算在日志中对所有进入系统的请求中拦截流水号,并输出到日志中。
编写拦截器
此次打算使用拦截器对外部请求系统的报文中拦截流水号 --> seqNo。首先需要编写拦截器 。
/**
* @description: 订单号拦截器便于日志输出
* @author: zhanghailang
* @date: 2020-11-18 13:24
*/
@Slf4j
public class SeqNoInterceptor extends HandlerInterceptorAdapter {
private String seqNo = "transSeq";
private String error = "/error";
private String UTF_8 = "UTF-8";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
if (StringUtils.isEmpty(request.getContentType())||
(!request.getContentType().equals("application/json") && (!request.getContentType().equals("application/json; charset=UTF-8")))) {
return true;
}
log.info(request.getServletPath());
if (error.equals(request.getServletPath())) {
return true;
}
BodyReaderWrapper aa = new BodyReaderWrapper(request);
if(!StringUtils.isEmpty(getPostBodyParams(aa.getInputStream(), UTF_8))){
Map map = JSONUtil.toBean(getPostBodyParams(aa.getInputStream(), UTF_8), Map.class);
if (!CollectionUtil.isEmpty(map)) {
Map headerMap = (Map) map.get("header");
String seqNotemp = (String) headerMap.get(seqNo);
if (!StringUtils.isEmpty(seqNotemp)) {
MDC.put("seqNo", seqNotemp);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
/**
* 获取POST请求中Body参数
*
* @param
* @return 字符串
*/
private String getPostBodyParams(ServletInputStream inputStream, String charset) throws Exception {
try {
String body = StreamUtils.copyToString(inputStream, Charset.forName(charset));
if (StringUtils.isEmpty(body)) {
return "";
}
return body;
} catch (Exception e) {
throw e;
}
}
}
logback.xml配置
配置拦截器
需要对拦截器进行配置。此处匹配路径注意使用是 /** 。
/**
* @description: 拦截器配置类
* @author: zhanghailang
* @date: 2020-11-18 13:40
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Bean
public SeqNoInterceptor getSeqNoInterceptor(){
return new SeqNoInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getSeqNoInterceptor()).addPathPatterns("/**");
}
}
配置过滤器
package com.huida.investment.Interceptor;
/**
* @description:解决流不可重复读问题
* @author: zhanghailang
* @date: 2020-12-9 18:23
*/
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
//@WebFilter(filterName="bodyReaderFilter",urlPatterns="/*")
public class BodyReaderFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// do nothing
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
ServletRequest requestWrapper=null;
if(request instanceof HttpServletRequest) {
requestWrapper=new BodyReaderWrapper((HttpServletRequest)request);
}
if(requestWrapper==null) {
chain.doFilter(request, response);
}else {
chain.doFilter(requestWrapper, response);
}
}
@Override
public void destroy() {
// do nothing
}
}
/**
* @description:过滤器注册
* @author: zhanghailang
* @date: 2020-12-9 18:24
*/
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<BodyReaderFilter> Filters() {
FilterRegistrationBean<BodyReaderFilter> registrationBean = new FilterRegistrationBean<BodyReaderFilter>();
registrationBean.setFilter(new BodyReaderFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setName("bodyReaderFilter");
return registrationBean;
}
}
保存流
关键的一点就是解决流不可重复读的问题,需要先保存流
package com.huida.investment.Interceptor;
/**
* @description:保存流
* @author: zhanghailang
* @date: 2020-12-9 18:22
*/
import org.springframework.util.StreamUtils;
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;
public class BodyReaderWrapper extends HttpServletRequestWrapper {
/**
* 用于将流保存下来
*/
private byte[] requestBody;
public BodyReaderWrapper(HttpServletRequest request) throws IOException {
super(request);
requestBody = StreamUtils.copyToByteArray(request.getInputStream());
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);
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) {
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
}
r(ReadListener readListener) {
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
}