欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

springboot打印接口調(diào)用日志的實例

 更新時間:2022年09月30日 08:35:04   作者:融極  
這篇文章主要介紹了springboot打印接口調(diào)用日志的實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

概述

請求日志幾乎是所有大型企業(yè)級項目的必要的模塊,請求日志對于我們來說后期在項目運行上線一段時間用于排除異常、請求分流處理、限制流量等。

請求日志一般都會記錄請求參數(shù)、請求地址、請求狀態(tài)(Status Code)、SessionId、請求方法方式(Method)、請求時間、客戶端IP地址、請求返回內(nèi)容、耗時等等。如果你得系統(tǒng)還有其他個性化的配置,也可以完成記錄。

記錄請求參數(shù)時,由于servlet.getInputStream的數(shù)據(jù)只能讀取一次,因此需要先把數(shù)據(jù)緩存下來,構(gòu)造返回流,保證之后的Controller可以正常讀取到請求體的數(shù)據(jù)。

方案思路

  • 封裝HttpServletRequest請求類,改類在構(gòu)造方法中將請求的輸入流中的數(shù)據(jù)緩存了起來,保證之后的處理可以重復(fù)讀取輸入流中的數(shù)據(jù)。
  • 實現(xiàn)過濾器,把上步封裝的請求類傳下去,保證Controller可以正常讀取輸入流中的數(shù)據(jù)。
  • 添加攔截器,讀取輸入流中的數(shù)據(jù)。
  • 讀取返回參數(shù)。

封裝HttpServletRequest請求

package com.example.demo.intercept;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
/**
?* @author?
?* @date 封裝HttpServletRequest請求
?*/
public class RequestWrapper extends HttpServletRequestWrapper {
? ? private final String body;
? ? public RequestWrapper(HttpServletRequest request) {
? ? ? ? super(request);
? ? ? ? StringBuilder stringBuilder = new StringBuilder();
? ? ? ? BufferedReader bufferedReader = null;
? ? ? ? InputStream inputStream = null;
? ? ? ? try {
? ? ? ? ? ? inputStream = request.getInputStream();
? ? ? ? ? ? if (inputStream != null) {
? ? ? ? ? ? ? ? bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
? ? ? ? ? ? ? ? char[] charBuffer = new char[128];
? ? ? ? ? ? ? ? int bytesBody = -1;
? ? ? ? ? ? ? ? while ((bytesBody = bufferedReader.read(charBuffer)) > 0) {
? ? ? ? ? ? ? ? ? ? stringBuilder.append(charBuffer, 0, bytesBody);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? stringBuilder.append("");
? ? ? ? ? ? }
? ? ? ? } catch (IOException e) {
? ? ? ? } finally {
? ? ? ? ? ? if (inputStream != null) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? inputStream.close();
? ? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (bufferedReader != null) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? bufferedReader.close();
? ? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? body = stringBuilder.toString();
? ? }
? ? @Override
? ? public ServletInputStream getInputStream() throws IOException {
? ? ? ? final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
? ? ? ? ServletInputStream servletInputStream = new ServletInputStream() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean isFinished() {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean isReady() {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void setReadListener(ReadListener readListener) {
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public int read() throws IOException {
? ? ? ? ? ? ? ? return byteArrayInputStream.read();
? ? ? ? ? ? }
? ? ? ? };
? ? ? ? return servletInputStream;
? ? }
? ? @Override
? ? public BufferedReader getReader() throws IOException {
? ? ? ? return new BufferedReader(new InputStreamReader(this.getInputStream()));
? ? }
? ? public String getBody() {
? ? ? ? return this.body;
? ? }
}

把可重復(fù)讀請求體通過過濾器往下傳

防止請求流讀取一次后就沒有了,之后的不管是過濾器、攔截器、處理器都是讀的已經(jīng)緩存好的數(shù)據(jù),實現(xiàn)可重復(fù)讀。

package com.example.demo.intercept;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
?* @author?
?* @date 防止請求流讀取一次后就沒有了
?*/
@Component
@WebFilter(urlPatterns = "/**")
public class RecordChannelFilter implements Filter {
? ? @Override
? ? public void init(FilterConfig filterConfig) throws ServletException {
? ? }
? ? @Override
? ? public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
? ? ? ? ServletRequest request = null;
? ? ? ? if (servletRequest instanceof HttpServletRequest) {
? ? ? ? ? ? request = new RequestWrapper((HttpServletRequest) servletRequest);
? ? ? ? }
? ? ? ? if (request ==null){
? ? ? ? ? ? //防止流讀取一次就沒有了,將流傳遞下去
? ? ? ? ? ? filterChain.doFilter(servletRequest,servletResponse);
? ? ? ? }else {
? ? ? ? ? ? filterChain.doFilter(request,servletResponse);
? ? ? ? }
? ? }
? ? @Override
? ? public void destroy() {
? ? }
}

記錄入?yún)⑷罩?/h2>

實現(xiàn)入?yún)⒂涗洈r截器

通過攔截器的方式實現(xiàn)用戶入?yún)⒂涗洝?/p>

package com.example.demo.intercept;
import com.alibaba.fastjson.JSONObject;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import io.jsonwebtoken.Claims;
import javax.annotation.Resource;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
?* @author?
?* @date 記錄用戶操作記錄入?yún)?
?*/
@Component
public class OperationLogInterceptor implements HandlerInterceptor {
? ? /**
? ? ?* Jwt secert串,需要與加密token的秘鑰一致
? ? ?*/
? ? public static final String JWT_SECERT = "23142d7a9s7d66970ad07d8sa";
? ? /**
? ? ?* 需要記錄的接口URL
? ? ?*/
? ? private static List<String> pathList = new ArrayList<>();
? ? static {
? ? ? ? pathList.add("/mdms/model");
? ? }
? ? @Resource
? ? private FunctionDOMapper functionDOMapper;//菜單動能sql
? ? @Resource
? ? private UserOperationHistoryDOMapper historyDOMapper;//操作日志記錄表
? ? @Override
? ? public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
? ? ? ? String servletPath = "" + request.getServletPath();
? ? ? ? String method = request.getMethod();
? ? ? ? pathList.forEach(path -> {
? ? ? ? ? ? if (servletPath.contains(path)){
? ? ? ? ? ? ? ? Cookie[] cookies = request.getCookies();
? ? ? ? ? ? ? ? if (cookies != null) {
? ? ? ? ? ? ? ? ? ? for (Cookie cookie : cookies) {
? ? ? ? ? ? ? ? ? ? ? ? //獲取token在請求中
? ? ? ? ? ? ? ? ? ? ? ? if (cookie.getName().equals("_qjt_ac_")) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? String token = cookie.getValue();
? ? ? ? ? ? ? ? ? ? ? ? ? ? /**解密token**/
? ? ? ? ? ? ? ? ? ? ? ? ? ? byte[] encodeKey = Base64.decode(JWT_SECERT);
? ? ? ? ? ? ? ? ? ? ? ? ? ? Claims claims = null;
? ? ? ? ? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? SecretKeySpec keySpec = new SecretKeySpec(encodeKey, 0, encodeKey.length, "AES");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? claims = Jwts.parser().setSigningKey(keySpec).parseClaimsJws(token).getBody();
? ? ? ? ? ? ? ? ? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? //用戶賬號
? ? ? ? ? ? ? ? ? ? ? ? ? ? String account = claims.getSubject();
? ? ? ? ? ? ? ? ? ? ? ? ? ? //查詢URL在功能表中的功能
? ? ? ? ? ? ? ? ? ? ? ? ? ? functionDOMapper.selectOne(servletPath, method);
? ? ? ? ? ? ? ? ? ? ? ? ? ? //獲取入?yún)?
? ? ? ? ? ? ? ? ? ? ? ? ? ? RequestWrapper requestWrapper = null;
? ? ? ? ? ? ? ? ? ? ? ? ? ? if (request instanceof HttpServletRequest) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? requestWrapper = new RequestWrapper(request);
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? Map<String,Object> map = new HashMap<>();
? ? ? ? ? ? ? ? ? ? ? ? ? ? map.put("parameter", JSONObject.parse(requestWrapper.getBody()));
? ? ? ? ? ? ? ? ? ? ? ? ? ? historyDOMapper.insert(map);//將操作信息入庫
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }?
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? return true;
? ? }
}

注冊攔截器

package com.example.demo.config;
import com.example.demo.intercept.OperationLogInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
?* @author?
?* @date 注冊攔截器
?*/
public class WebConfig implements WebMvcConfigurer {
? ? @Bean
? ? public HandlerInterceptor getOperationLogInterceptor() {
? ? ? ? return new OperationLogInterceptor();
? ? }
? ? @Override
? ? public void addInterceptors(InterceptorRegistry registry){
? ? ? ? registry.addInterceptor(getOperationLogInterceptor()).addPathPatterns("/**").excludePathPatterns();
? ? }
}

記錄返參日志

package com.example.demo.intercept;
import com.alibaba.fastjson.JSONObject;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.annotation.Resource;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.Response;
import java.util.*;
/**
?* @author?
?* @date 記錄用戶操作日志返參
?*/
@ControllerAdvice(basePackages = "項目包")
public class GetResponseBody implements ResponseBodyAdvice<Object> {
? ? /**
? ? ?* Jwt secert串,需要與加密token的秘鑰一致
? ? ?*/
? ? public static final String JWT_SECERT = "23142d7a9s7d66970ad07d8sa";
? ? /**
? ? ?* 需要記錄的接口URL
? ? ?*/
? ? private static List<String> pathList = new ArrayList<>();
? ? static {
? ? ? ? pathList.add("/mdms/model");
? ? }
? ? @Resource
? ? private FunctionDOMapper functionDOMapper;//菜單動能sql
? ? @Resource
? ? private UserOperationHistoryDOMapper historyDOMapper;//操作日志記錄表
? ? @Override
? ? public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
? ? ? ? return false;
? ? }
? ? @Override
? ? public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
? ? ? ? String path = serverHttpRequest.getURI().getPath();
? ? ? ? String methodValue = serverHttpRequest.getMethodValue();
? ? ? ? pathList.forEach(serverPath -> {
? ? ? ? ? ? if (path.contains(serverPath)) {
? ? ? ? ? ? ? ? HashMap<String, String> cookieMap = new HashMap<>();
? ? ? ? ? ? ? ? HttpHeaders headers = serverHttpRequest.getHeaders();
? ? ? ? ? ? ? ? List<String> cookieList = headers.get("cookie");
? ? ? ? ? ? ? ? if (CollectionUtils.isEmpty(cookieList)) {
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? String replaceAll = cookieList.get(0).replaceAll(";", "").replaceAll(";", "");
? ? ? ? ? ? ? ? String[] split = replaceAll.split(";");
? ? ? ? ? ? ? ? for (String cookie : split) {
? ? ? ? ? ? ? ? ? ? String[] param = cookie.split("=");
? ? ? ? ? ? ? ? ? ? cookieMap.put(param[0], param[1]);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? String token = cookieMap.get("_qjt_ac_");
? ? ? ? ? ? ? ? byte[] encodeKey = Base64.decode(JWT_SECERT);
? ? ? ? ? ? ? ? Claims claims = null;
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? SecretKeySpec keySpec = new SecretKeySpec(encodeKey, 0, encodeKey.length, "AES");
? ? ? ? ? ? ? ? ? ? claims = Jwts.parser().setSigningKey(keySpec).parseClaimsJws(token).getBody();
? ? ? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? //用戶賬號
? ? ? ? ? ? ? ? String account = claims.getSubject();
? ? ? ? ? ? ? ? //查詢URL在功能表中的功能
? ? ? ? ? ? ? ? functionDOMapper.selectOne(servletPath, method);
? ? ? ? ? ? ? ? //獲取返參
? ? ? ? ? ? ? ? List<Object> list = historyDOMapper.select("功能表參數(shù)", account);
? ? ? ? ? ? ? ? list.sort((Object1,Object2)->Object2.getTime().compareTo(Object1.getTime()));//將查詢到的操作記錄按時間降序排列
? ? ? ? ? ? ? ? Object history = list.get(0);
? ? ? ? ? ? ? ? if (body instanceof Response) {
? ? ? ? ? ? ? ? ? ? Response response = (Response) body;
? ? ? ? ? ? ? ? ? ? JSONObject jsonObject = JSONObject.parseObject(history.getParam());
? ? ? ? ? ? ? ? ? ? jsonObject.put("message",response.getMessage());
? ? ? ? ? ? ? ? ? ? jsonObject.put("body",response.getData());
? ? ? ? ? ? ? ? ? ? history.setParam(jsonObject.toString());
? ? ? ? ? ? ? ? ? ? history.setDes(response.getMessage());
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? historyDOMapper.updateByPrimaryKeySelective(history);//將操作信息更新
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? return body;
? ? }
}

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。 

相關(guān)文章

  • SpringMVC結(jié)合天氣api實現(xiàn)天氣查詢

    SpringMVC結(jié)合天氣api實現(xiàn)天氣查詢

    這篇文章主要為大家詳細(xì)介紹了SpringMVC結(jié)合天氣api實現(xiàn)天氣查詢,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Java實現(xiàn)經(jīng)典游戲打磚塊游戲的示例代碼

    Java實現(xiàn)經(jīng)典游戲打磚塊游戲的示例代碼

    這篇文章主要介紹了如何利用Java實現(xiàn)經(jīng)典的游戲—打磚塊。玩家操作一根螢?zāi)簧纤降摹鞍糇印?,讓一顆不斷彈來彈去的“球”在撞擊作為過關(guān)目標(biāo)消去的“磚塊”的途中不會落到螢?zāi)坏紫?。感興趣的小伙伴可以了解一下
    2022-02-02
  • Json 自定義使用函數(shù)的簡單實例

    Json 自定義使用函數(shù)的簡單實例

    下面小編就為大家?guī)硪黄狫son 自定義使用函數(shù)的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • java == 引發(fā)的線上異常詳解

    java == 引發(fā)的線上異常詳解

    這篇文章主要介紹了java == 引發(fā)的線上異常,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2021-09-09
  • Java 反射調(diào)用靜態(tài)方法的簡單實例

    Java 反射調(diào)用靜態(tài)方法的簡單實例

    下面小編就為大家?guī)硪黄狫ava 反射調(diào)用靜態(tài)方法的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • 淺談java中為什么實體類需要實現(xiàn)序列化

    淺談java中為什么實體類需要實現(xiàn)序列化

    下面小編就為大家?guī)硪黄獪\談java中為什么實體類需要實現(xiàn)序列化。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • Google Guava 緩存工具使用詳解

    Google Guava 緩存工具使用詳解

    這篇文章主要介紹了Guava自加載緩存LoadingCache使用指南,通過這些內(nèi)容介紹,了解了LoadingCache的基本原理和用法,包括如何創(chuàng)建和配置緩存,以及如何結(jié)合Java?8的特性來優(yōu)化代碼,需要的朋友可以參考下
    2023-12-12
  • Java數(shù)據(jù)結(jié)構(gòu)之線段樹詳解

    Java數(shù)據(jù)結(jié)構(gòu)之線段樹詳解

    線段樹是一種二叉搜索樹,與區(qū)間樹相似,它將一個區(qū)間劃分成一些單元區(qū)間,每個單元區(qū)間對應(yīng)線段樹中的一個葉結(jié)點。本文將介紹線段樹的Java實現(xiàn)代碼,需要的可以參考一下
    2022-01-01
  • 一文帶你掌握java8中的reduce操作

    一文帶你掌握java8中的reduce操作

    reduce?操作是一種通用的歸約操作,它可以實現(xiàn)從?Stream?中生成一個值,其生成的值不是隨意的,而是根據(jù)指定的計算模型,下面我們就來深入了解下java8中的reduce操作吧
    2023-12-12
  • idea中如何集成http請求

    idea中如何集成http請求

    這篇文章主要介紹了idea中如何集成http請求問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10

最新評論