springboot打印接口调用日志的实例_第1页
springboot打印接口调用日志的实例_第2页
springboot打印接口调用日志的实例_第3页
springboot打印接口调用日志的实例_第4页
springboot打印接口调用日志的实例_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第springboot打印接口调用日志的实例目录概述方案思路封装HttpServletRequest请求把可重复读请求体通过过滤器往下传记录入参日志实现入参记录拦截器注册拦截器记录返参日志

概述

请求日志几乎是所有大型企业级项目的必要的模块,请求日志对于我们来说后期在项目运行上线一段时间用于排除异常、请求分流处理、限制流量等。

请求日志一般都会记录请求参数、请求地址、请求状态(StatusCode)、SessionId、请求方法方式(Method)、请求时间、客户端IP地址、请求返回内容、耗时等等。如果你得系统还有其他个性化的配置,也可以完成记录。

记录请求参数时,由于servlet.getInputStream的数据只能读取一次,因此需要先把数据缓存下来,构造返回流,保证之后的Controller可以正常读取到请求体的数据。

方案思路

封装HttpServletRequest请求类,改类在构造方法中将请求的输入流中的数据缓存了起来,保证之后的处理可以重复读取输入流中的数据。实现过滤器,把上步封装的请求类传下去,保证Controller可以正常读取输入流中的数据。添加拦截器,读取输入流中的数据。读取返回参数。

封装HttpServletRequest请求

packageercept;

importjavax.servlet.ReadListener;

importjavax.servlet.ServletInputStream;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletRequestWrapper;

importjava.io.*;

*@author

*@date封装HttpServletRequest请求

publicclassRequestWrapperextendsHttpServletRequestWrapper{

privatefinalStringbody;

publicRequestWrapper(HttpServletRequestrequest){

super(request);

StringBuilderstringBuilder=newStringBuilder();

BufferedReaderbufferedReader=null;

InputStreaminputStream=null;

try{

inputStream=request.getInputStream();

if(inputStream!=null){

bufferedReader=newBufferedReader(newInputStreamReader(inputStream));

char[]charBuffer=newchar[128];

intbytesBody=-1;

while((bytesBody=bufferedReader.read(charBuffer))0){

stringBuilder.append(charBuffer,0,bytesBody);

}

}else{

stringBuilder.append("");

}

}catch(IOExceptione){

}finally{

if(inputStream!=null){

try{

inputStream.close();

}catch(IOExceptione){

e.printStackTrace();

}

}

if(bufferedReader!=null){

try{

bufferedReader.close();

}catch(IOExceptione){

e.printStackTrace();

}

}

}

body=stringBuilder.toString();

}

@Override

publicServletInputStreamgetInputStream()throwsIOException{

finalByteArrayInputStreambyteArrayInputStream=newByteArrayInputStream(body.getBytes());

ServletInputStreamservletInputStream=newServletInputStream(){

@Override

publicbooleanisFinished(){

returnfalse;

}

@Override

publicbooleanisReady(){

returnfalse;

}

@Override

publicvoidsetReadListener(ReadListenerreadListener){

}

@Override

publicintread()throwsIOException{

returnbyteArrayInputStream.read();

}

};

returnservletInputStream;

}

@Override

publicBufferedReadergetReader()throwsIOException{

returnnewBufferedReader(newInputStreamReader(this.getInputStream()));

}

publicStringgetBody(){

returnthis.body;

}

}

把可重复读请求体通过过滤器往下传

防止请求流读取一次后就没有了,之后的不管是过滤器、拦截器、处理器都是读的已经缓存好的数据,实现可重复读。

packageercept;

importorg.springframework.stereotype.Component;

importjavax.servlet.*;

importjavax.servlet.annotation.WebFilter;

importjavax.servlet.http.HttpServletRequest;

importjava.io.IOException;

*@author

*@date防止请求流读取一次后就没有了

@Component

@WebFilter(urlPatterns="/**")

publicclassRecordChannelFilterimplementsFilter{

@Override

publicvoidinit(FilterConfigfilterConfig)throwsServletException{

}

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

ServletRequestrequest=null;

if(servletRequestinstanceofHttpServletRequest){

request=newRequestWrapper((HttpServletRequest)servletRequest);

}

if(request==null){

//防止流读取一次就没有了,将流传递下去

filterChain.doFilter(servletRequest,servletResponse);

}else{

filterChain.doFilter(request,servletResponse);

}

}

@Override

publicvoiddestroy(){

}

}

记录入参日志

实现入参记录拦截器

通过拦截器的方式实现用户入参记录。

packageercept;

importcom.alibaba.fastjson.JSONObject;

importorg.bouncycastle.util.encoders.Base64;

importorg.springframework.stereotype.Component;

importorg.springframework.web.servlet.HandlerInterceptor;

importio.jsonwebtoken.Claims;

importjavax.annotation.Resource;

importjavax.crypto.spec.SecretKeySpec;

importjavax.servlet.http.Cookie;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

importjava.util.ArrayList;

importjava.util.HashMap;

importjava.util.List;

importjava.util.Map;

*@author

*@date记录用户操作记录入参

@Component

publicclassOperationLogInterceptorimplementsHandlerInterceptor{

/**

*Jwtsecert串,需要与加密token的秘钥一致

*/

publicstaticfinalStringJWT_SECERT="23142d7a9s7d66970ad07d8sa";

/**

*需要记录的接口URL

*/

privatestaticListStringpathList=newArrayList();

static{

pathList.add("/mdms/model");

}

@Resource

privateFunctionDOMapperfunctionDOMapper;//菜单动能sql

@Resource

privateUserOperationHistoryDOMapperhistoryDOMapper;//操作日志记录表

@Override

publicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler){

StringservletPath=""+request.getServletPath();

Stringmethod=request.getMethod();

pathList.forEach(path-{

if(servletPath.contains(path)){

Cookie[]cookies=request.getCookies();

if(cookies!=null){

for(Cookiecookie:cookies){

//获取token在请求中

if(cookie.getName().equals("_qjt_ac_")){

Stringtoken=cookie.getValue();

/**解密token**/

byte[]encodeKey=Base64.decode(JWT_SECERT);

Claimsclaims=null;

try{

SecretKeySpeckeySpec=newSecretKeySpec(encodeKey,0,encodeKey.length,"AES");

claims=Jwts.parser().setSigningKey(keySpec).parseClaimsJws(token).getBody();

}catch(Exceptione){

return;

}

//用户账号

Stringaccount=claims.getSubject();

//查询URL在功能表中的功能

functionDOMapper.selectOne(servletPath,method);

//获取入参

RequestWrapperrequestWrapper=null;

if(requestinstanceofHttpServletRequest){

requestWrapper=newRequestWrapper(request);

}

MapString,Objectmap=newHashMap();

map.put("parameter",JSONObject.parse(requestWrapper.getBody()));

historyDOMapper.insert(map);//将操作信息入库

}

}

}

}

});

returntrue;

}

}

注册拦截器

packagecom.example.demo.config;

importercept.OperationLogInterceptor;

importorg.springframework.context.annotation.Bean;

importorg.springframework.web.servlet.HandlerInterceptor;

importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;

importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;

*@author

*@date注册拦截器

publicclassWebConfigimplementsWebMvcConfigurer{

@Bean

publicHandlerInterceptorgetOperationLogInterceptor(){

returnnewOperationLogInterceptor();

}

@Override

publicvoidaddInterceptors(InterceptorRegistryregistry){

registry.addInterceptor(getOperationLogInterceptor()).addPathPatterns("/**").excludePathPatterns();

}

}

记录返参日志

packageercept;

importcom.alibaba.fastjson.JSONObject;

importorg.bouncycastle.util.encoders.Base64;

importorg.springframework.core.MethodParameter;

importorg.springframework.http.HttpHeaders;

importorg.springframework.http.MediaType;

importorg.springframework.http.converter.HttpMessageConverter;

importorg.springframework.http.server.ServerHttpRequest;

importorg.springframework.http.server.ServerHttpResponse;

importorg.springframework.util.CollectionUtils;

importorg.springframework.web.bind.annotation.ControllerAdvice;

importorg.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

importjavax.annotation.Resource;

importjavax.crypto.spec.SecretKeySpec;

importjavax.servlet.http.HttpServletRequest;

importjavax.xml.ws.Response;

importjava.util.*;

*@author

*@date记录用户操作日志返参

@ControllerAdvice(basePackages="项目包")

publicclassGetResponseBodyimplementsResponseBodyAdviceObject{

/**

*Jwtsecert串,需要与加密token的秘钥一致

*/

publicstaticfinalStringJWT_SECERT="23142d7a9s7d66970ad07d8sa";

/**

*需要记录的接口URL

*/

privatestaticListStringpathList=newArrayList();

static{

pathList.add("/mdms/model");

}

@Resource

privateFunctionDOMapperfunctionDOMapper;//菜单动能sql

@Resource

privateUserOperationHistoryDOMapperhistoryDOMapper;//操作日志记录表

@Override

publicbooleansupports(MethodParametermethodParameter,ClassextendsHttpMessageConverteraClass){

returnfalse;

}

@Override

publicObjectbeforeBodyWrite(Objectbody,MethodParametermethodParameter,MediaTypemediaType,ClassextendsHttpMessageConverteraClass,ServerHttpRequestserverHttpRequest,ServerHttpResponseserverHttpResponse){

Stringpath=serverHttpRequest.getURI().getPath();

StringmethodValue=serverHttpRequest.getMethodValue();

pathList.forEach(serverPath-{

if(path.contains(serverPath)){

HashMapString,StringcookieMap=newHashMap();

HttpHeadersheaders=serverHttpRequest.getHeaders();

ListStringcookieList=headers.get("cookie");

if(CollectionUtils.isEmpty(cookieList)){

return;

}

StringreplaceAll=cookieList.get(0).replaceAll(";","").replaceAll(";","");

String[]split=replaceAll.split(";");

for(Stringcookie:split){

String[]param=cookie.split("=");

cookieMap.put(param[0],param[1]);

}

Stringtoken=cookieMap.get("_qjt_ac_");

byte[]encodeKey=Base64.decode(JWT_SECERT);

Claimsclaims=null;

try{

SecretKeySpeckeySpec=newSecretKeySpec(encodeKey,0,encodeKey.length,"AES");

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论