继上一篇文章 springboot 切点@Pointcut 过滤某个目录的类 我又使用拦截器来记录日志信息。
spring拦截器 一般有两种
- 继承HandlerInterceptorAdapter
- 实现HandlerInterceptor
一般用作日志记录和登录校验使用。
主要有三种方法
- preHandle:拦截于请求刚进入时,进行判断,需要boolean返回值,如果返回true将继续执行,如果返回false,将不进行执行。一般用于登录校验。
- postHandle:拦截于方法成功返回后,视图渲染前,可以对modelAndView进行操作。
- afterCompletion:拦截于方法成功返回后,视图渲染前,可以进行成功返回的日志记录。
问题
1.开发时 主要遇到一个问题 获取body参数体数据时,进入controller接口时报错400
原因是 post请求时的body参数是通过流获取,而流里面的内容 读取后 数据就没了 所以当进入controller接口时 报错400
看到 前辈 文章,解决办法: 先读取流,再次将流写到request中。
2.继承HandlerInterceptorAdapter和实现HandlerInterceptor 这两种方法 在本项目中 只有继承HandlerInterceptorAdapter符合要求,不知道项目自身原因还是什么,实现HandlerInterceptor这种方式 注入feign失败,于是乎 使用继承HandlerInterceptorAdapter这种方式来解决的。
代码
拦截器编写
public class TestInterceptor extends HandlerInterceptorAdapter {
private final Logger logger = LogManager.getLogger(TestInterceptor.class);
@Autowired
private SystemAuditFeignClient systemAuditFeignClient;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
try {
SystemAudit systemAudit = new SystemAudit();
//获取请求参数
JSONObject jsonObject = new JSONObject();
BodyReaderHttpServletRequestWrapper requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
String body = requestWrapper.getBodyString(request);//获取@RequestBody的参数体
if(isJson(body)){
JSONObject bodyData = JSON.parseObject(body);
if(bodyData!=null&&bodyData.size()>0){
jsonObject.put("body", bodyData);
}
}else{
JSONArray bodyData = JSONArray.parseArray(body);
if(bodyData!=null&&bodyData.size()>0){
jsonObject.put("body", bodyData);
}
}
JSONObject requestData = getRequestData(request);
if(requestData!=null&&requestData.size()>0){
jsonObject.put("params", requestData);
}
System.out.println("拦截器获取到body内容:"+body);
systemAudit.setNote(jsonObject.toJSONString());
//增加|删除|修改|查询 请求方式
String httpMethod = request.getMethod();
if ("GET".equalsIgnoreCase(httpMethod)) {
systemAudit.setOperation("查询");
} else if ("POST".equalsIgnoreCase(httpMethod)) {
systemAudit.setOperation("增加");
} else if ("PUT".equalsIgnoreCase(httpMethod)) {
systemAudit.setOperation("修改");
} else if ("DELETE".equalsIgnoreCase(httpMethod)) {
systemAudit.setOperation("删除");
}
//动态参数
String remoteHost = request.getRemoteHost();
logger.info("remoteHost" + remoteHost);
systemAudit.setSourceIp(remoteHost);
logger.info("日志信息"+systemAudit.getNote());
this.systemAuditFeignClient.insert(systemAudit);
} catch (Exception e) {
logger.error("日志添加发生异常", e);
}
}
//获取 @RequestParam 的参数内容
public JSONObject getRequestData(HttpServletRequest request) {
Map resultMap=new HashMap();
Map<String, String[]> map = request.getParameterMap();
//遍历
for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry element = (Map.Entry) iter.next();
//key值
Object strKey = element.getKey();
//value,数组形式
String[] value = (String[]) element.getValue();
StringBuffer stringBuffer=new StringBuffer();
for (int i = 0; i < value.length; i++) {
stringBuffer.append(value[i]);
}
if(!isJson(stringBuffer.toString())) {
resultMap.put(strKey.toString(), stringBuffer.toString());
}else{
resultMap.put(strKey.toString(), JSON.parseObject(stringBuffer.toString()));
}
}
String json = JSON.toJSONString(resultMap);
JSONObject jsonObject = JSON.parseObject(json);
return jsonObject;
}
public boolean isJson(String content){
try {
JSONObject jsonStr= JSONObject.parseObject(content);
return true;
} catch (Exception e) {
return false;
}
}
}
自定义过滤器,先在过滤器中获取流,然后在写进去
@Component
public class RequserAgainFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
ServletRequest requestWrapper = null;
if(request instanceof HttpServletRequest) {
requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);
}
if(requestWrapper == null) {
System.out.println("servletRequest");
filterChain.doFilter(request, response);
} else {
System.out.println("requestWrapper");
filterChain.doFilter(requestWrapper, response);
}
}
}
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
String sessionStream = getBodyString(request);
body = sessionStream.getBytes(Charset.forName("UTF-8"));
}
/**
* 获取请求Body
* @param request
* @return
*/
public String getBodyString(final ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = cloneInputStream(request.getInputStream());//将获取到的请求参数重新塞入request里面去
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();
}
finally {
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
/**
* Description: 复制输入流</br>
*
* @param inputStream
* @return</br>
*/
public InputStream cloneInputStream(ServletInputStream inputStream) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
try {
while ((len = inputStream.read(buffer)) > -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
byteArrayOutputStream.flush();
}
catch (IOException e) {
e.printStackTrace();
}
InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
return byteArrayInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() 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) {
}
};
}
}
注册自定义拦截器
@Configuration
public class WebAppConfigurer implements WebMvcConfigurer{
@Bean
public TestInterceptor testInterceptor() {
return new TestInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration interceptor = registry.addInterceptor(testInterceptor());
//添加拦截路径
interceptor.addPathPatterns("/**").excludePathPatterns("/api/test1/**","/api/test/testInsert");
}
}
此时 打印的日志信息 如下:
- get 请求 参数是基本数据类型
- post请求 参数是json串 @RequestParam
- post请求 参数体
此时,大功告成!不足之处,还请多多指教!