最近在做一塊將所有接口的返回值body值接口地址ip地址等都打印字日誌中。這樣查找錯誤比較方便,
解決當前問題用aop切面來工作。下面是代碼:
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Aspect
@Component
public class WebLogAspect {
//配置文件配置logging.printFlag (1打印日誌0不打印日誌)
@Value("${logging.printFlag}")
private int printFlag;
private static Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
// 定義切點Pointcut所有@RequestMappping註解的方法
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public void excudeService() {
}
@Around("excudeService()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
HttpServletRequest request = sra.getRequest();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String url = request.getRequestURL().toString();
String method = request.getMethod();
String uri = request.getRequestURI();
String queryString = request.getQueryString();
Object[] args = pjp.getArgs();
String params = "";
//獲取請求參數集合並進行遍歷拼接
if(args.length>0){
if("POST".equals(method)){
Object object = args[0];
Map map = getKeyAndValue(object);
params = JSON.toJSONString(map);
}else if("GET".equals(method)){
params = queryString;
}
}
if(printFlag == 1){
Map<String, String> Headermap = new HashMap<String, String>();
Enumeration headerNames = request.getHeaderNames();
//獲取Header
while (headerNames.hasMoreElements()) {
String key = (String) headerNames.nextElement();
String value = request.getHeader(key);
Headermap.put(key, value);
}
Set<String> keys = Headermap.keySet(); //此行可省略,直接將map.keySet()寫在for-each循環的條件中
logger.warn("\n"+"Header獲取時間:"+df.format(new Date()));
for(String key:keys){
logger.warn("Header鍵: "+key+"\t"+"Header值:"+Headermap.get(key));
}
logger.info("\n"+"客戶端操作IP:"+"\t"+request.getRemoteAddr());//遠程IP,即客戶端IP
logger.warn("\n"+"客戶端操作端口:"+"\t"+String.valueOf(request.getRemotePort()));//遠程端口,即客戶端端口
logger.warn("\n"+"操作地址時間:"+"\t"+df.format(new Date()));
logger.info("\n"+"請求地址:"+"\t"+url);
logger.info("\n"+"請求類型:"+"\t"+method);
logger.info("\n"+"請求參數:"+"\t"+params);
//轉發request,解決io流讀取一次的問題,RequestWrapper類會在另一篇博文寫到
RequestWrapper requestWrapper = new RequestWrapper(request);
String body = requestWrapper.getBody();
logger.warn("\n"+"Body值時間:"+"\t"+df.format(new Date()));
logger.info("\n"+"Body值:"+"\t"+body);
}
// result的值就是被攔截方法的返回值
Object result = pjp.proceed();
if(printFlag == 1){
Object json = JSONObject.toJSON(result);
if(result != null){
JSONObject parseObject = JSONObject.parseObject(json.toString());
logger.info("\n"+"請求返回時間:"+"\t"+df.format(new Date()));
logger.info("\n"+"請求返回值:" + JSONObject.toJSONString(parseObject,SerializerFeature.PrettyFormat));
}
}
return result;
}
public static Map<String, Object> getKeyAndValue(Object obj) {
Map<String, Object> map = new HashMap<>();
// 得到類對象
Class userCla = (Class) obj.getClass();
/* 得到類中的所有屬性集合 */
Field[] fs = userCla.getDeclaredFields();
for (int i = 0; i < fs.length; i++) {
Field f = fs[i];
f.setAccessible(true); // 設置些屬性是可以訪問的
Object val = new Object();
try {
val = f.get(obj);
// 得到此屬性的值
map.put(f.getName(), val);// 設置鍵值
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}
pom.xml配置
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>