1. 程式人生 > >SpringAOP實現攔截Controller請求引數並輸出到日誌

SpringAOP實現攔截Controller請求引數並輸出到日誌

一、實現的效果

請求:

http://localhost:8080/regist?username=king&age=12&password=123456

Controller:

@RestController
public class UserController {

    @RequestMapping("/regist")
    public Apiresult userRegister(@ModelAttribute User user) {
    //....
    return Apiresult.success("ok");
    }
    //user類包含username,age,password屬性,並重寫了tostring方法
}

控制檯

---------Path: /regist
---------ClassName: UserController
---------MethodName: userRegister
---------ParamList: {username:king,age:12,password:123456}

二、這樣做的原因

1.方便除錯,和前臺聯調可以直接看到引數
2.記錄資訊,方便回查。

三、實現程式碼

package com.kingboy.common.tools.log;

import lombok.extern.log4j.Log4j;
import org.aspectj
.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework
.stereotype.Component; import org.springframework.web.bind.annotation.RequestMapping; import java.util.Objects; import java.util.stream.Stream; /** * @author [email protected] * @date 2017/11/19 下午10:10 * @desc 方法接收的引數日誌. */ @Log4j @Aspect @Component @ConditionalOnProperty(name = "king.log.enabled", havingValue = "true") public class ParamInfoLog { @Pointcut("execution(* com.kingboy.controller..*(..))") public void controller() { } @Pointcut("execution(* com.kingboy.service..*(..))") public void service() { } @Pointcut("execution(* com.kingboy.repository..*(..))") public void repository() { } @Before("controller()") public void controller(JoinPoint point) { MethodSignature signature = (MethodSignature) point.getSignature(); Long count = Stream.of(signature.getMethod().getDeclaredAnnotations()) .filter(annotation -> annotation.annotationType() == RequestMapping.class) .count(); String requestPath = count >= 1 ? signature.getMethod().getAnnotation(RequestMapping.class).value()[0] : ""; String info = String.format("path:%s | %s", requestPath, getMethodInfo(point)); log.info(info); } @Before("service()") public void service(JoinPoint point) { log.info(String.format("%s", getMethodInfo(point))); } @Before("repository()") public void repository(JoinPoint point) { log.info(String.format("%s", getMethodInfo(point))); } private String getMethodInfo(JoinPoint point) { String className = point.getSignature().getDeclaringType().getSimpleName(); String methodName = point.getSignature().getName(); String[] parameterNames = ((MethodSignature) point.getSignature()).getParameterNames(); StringBuilder sb = null; if (Objects.nonNull(parameterNames)) { sb = new StringBuilder(); for (int i = 0; i < parameterNames.length; i++) { String value = point.getArgs()[i] != null ? point.getArgs()[i].toString() : "null"; sb.append(parameterNames[i] + ":" + value + "; "); } } sb = sb == null ? new StringBuilder() : sb; String info = String.format("class:%s | method:%s | args:%s", className, methodName, sb.toString()); return info; } }

更新時間 2018-09-06 00:50:25

根據專案實際情況進行了一定的優化,可以參考以下程式碼,日誌使用的是lombok提供的註解,更換為自己的log即可

@Slf4j
@Aspect
@Component
public class ParamLogger {

    @Pointcut("execution(* com.kimzing.provider.web..*(..))")
    public void controller() {
    }

    @Pointcut("execution(* com.kimzing.provider.service..*(..))")
    public void service() {
    }

    @Pointcut("execution(* com.kimzing.provider.mapper..*(..))")
    public void repository() {
    }

    @Before("controller()")
    public void controller(JoinPoint point) {

    }

    @Around("controller()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        String uuid = RandomUtil.uuid();

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        log.info("\n\t請求標識: {}\n\t請求IP: {}\n\t請求路徑: {}\n\t請求方式: {}\n\t方法描述: {}\n\t請求引數: {}",
                uuid, request.getRemoteAddr(), request.getRequestURL(), request.getMethod(),
                getMethodInfo(point), JSONObject.toJSONString(request.getParameterMap()));

        long startTime = System.currentTimeMillis();
        Object[] args = point.getArgs();
        Object retVal = point.proceed(args);
        long endTime = System.currentTimeMillis();

        log.info("\n\t請求標識: {} \n\t執行時間: {} ms \n\t返回值: {}", uuid, endTime - startTime, JSONObject.toJSONString(retVal));
        return retVal;
    }

    @Before("service()")
    public void service(JoinPoint point) {
        log.info("\n\tservice method: {}", getMethodInfo(point));
    }

    @Before("repository()")
    public void repository(JoinPoint point) {
        log.info("\n\trepository method: {}", getMethodInfo(point));
    }

    private String getMethodInfo(JoinPoint point) {
        ConcurrentHashMap<String, Object> info = new ConcurrentHashMap<>(3);

        info.put("class", point.getTarget().getClass().getSimpleName());
        info.put("method", point.getSignature().getName());

        String[] parameterNames = ((MethodSignature) point.getSignature()).getParameterNames();
        ConcurrentHashMap<String, String> args = null;

        if (Objects.nonNull(parameterNames)) {
            args = new ConcurrentHashMap<>(parameterNames.length);
            for (int i = 0; i < parameterNames.length; i++) {
                String value = point.getArgs()[i] != null ? point.getArgs()[i].toString() : "null";
                args.put(parameterNames[i], value);
            }
            info.put("args", args);
        }

        return JSONObject.toJSONString(info);
    }

}

相關推薦

SpringAOP實現攔截Controller請求引數輸出日誌

一、實現的效果 請求: http://localhost:8080/regist?username=king&age=12&password=123456 Controller: @RestController public cl

Android 攔截WebView請求加入或修改引數(GET)

今天遇到一個需求,H5內部呼叫登入請求,然後手機端給他拼接使用者的ID及其他訊息 這個WebView提供了方法shouldInterceptRequest 下面程式碼,只是簡單demo,請求方式是get mWebView.setWebViewClient(new WebViewClien

自定義Spring的Aop切面類攔截業務請求獲取到請求引數名和引數值

/**  * @author 劉俊重  * @Description 稽核校驗  * 所有的service業務方法都會先走這個方法,  * 先判斷本操作需不需要稽核,如果需要稽核則插入稽核隊列表,  * 不需要稽核則直接插入相關業務表  * @date 2017年7月5日  */ @Component @As

spring boot 攔截實現攔截前端請求返回json至前端頁面

攔截器主體 import com.alibaba.fastjson.JSONObject; import com.ufclub.vis.constant.StatusConstant; import com.ufclub.vis.entity.BaseResult; imp

FileReader實現讀取文件內容輸出到屏幕上

null tac otf style ace 讀取 編碼 use unicode編碼 FileReader與FileInputStream都是從文件讀數據,而前者一次讀一個字符,後者一次讀一個字節(在Unicode編碼環境下1個字符=2個字節) package com.j

關於Retrofit2+Okhttp3實現統一新增請求引數和重定向

Android開發中難免會遇到一些比較“不友好”的服務端介面。比如以前遇到的json資料中,某個欄位偶爾為Object,偶爾為List… 最近遇到的一個問題就是:所有請求介面都要增加一個token引數… 並且token引數有可能過期,比如請求某一條介面,如果token失效則在該請求

springMvc實現攔截特定請求判斷用戶是否登錄

攔截 定義 就會 操作 結束 詳細 htm object 哪裏 dUI與一 對於一個新聞站點來說除了評論功能其他請求都不用攔截 所以試著給springmvc框架增加一個用戶登錄的攔截功能 0基礎需要明白 登錄攔截是怎麽實現的 由誰實現攔截 在哪裏配置 用戶的登錄狀態保存在哪

實現後臺動態請求引數:getParam

/** * 得到request物件 */ public HttpServletRequest getRequest() { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHo

Java實現攔截HTTP請求的幾種方式

在Java的服務端開發當中,攔截器是很常見的業務場景,這裡對Java開發當中幾種常見的攔截器的實現方式進行記錄和分析。案例說明基於Spring Boot環境。一:實現javax.servlet.Filter介面(使用過濾器方式攔截請求)import org.springfra

spring aop攔截Controller引數校驗

       在專案中,我們會對入參做校驗,這些引數的校驗邏輯我們會寫很多次.能不能將這些引數的校驗邏輯提出來呢?答案是可以.Spring 有自己的validate工具方法,我個人感覺不是太好遠,想自己定製更加契合自己專案的校驗機制.經過哆哆嗦嗦的研究,有點結果,現在貼出來

Spring Boot 攔截請求引數MD5簽名校驗

攔截器定義 /** * 攔截器 請求引數簽名校驗 * Created by jiyang on 14:47 2017/12/14 */ @Component @Slf4j public class ParameterInterceptor implements Han

如何啟用設定org.slf4j.Logger列印輸出日誌

org.slf4j.Logger列印並輸出日誌 在resouces目錄下面新建logback.xml(此為Logback推薦目錄) 內容配置如下 logback 分為兩種設定: 1. 輸出到控制

mybatis攔截器的使用(輸出日誌或sql語句)

2016-08-28 14:48:02  [ http-apr-8888-exec-8:70630 ] - [ INFO ]  ---------------------------------------------- 2016-08-28 14:48:02  [ http-apr-8888-exec-8

linux java程序後臺啟動,輸出日誌到指定檔案中

linux 中讓java程序以後臺形式執行,並輸出日誌到指定檔案中。 舉例: 現在linux /home/pro/application/monitor下有一個jar包叫zop-monitor-web

使用 aop攔截 springMVC的controller獲取請求引數及返回結果

有人說使用aop攔截不到springMVC的controller,一般出現此種情況大多是由於配置錯誤造成,不廢話直接進入主題: 1、applicationContext.xml 配置掃描 除@controller外的bean <context:component

AOP之獲取Controller請求(Request)、返回(Response)引數、報錯資訊實現日誌記錄

需求:為系統中所有的提交,修改,刪除等等操作(除查詢以外的所有操作)做日誌記錄,記錄的內容包括:請求引數,返回引數,如果報錯就儲存報錯資訊。日誌要新增一個日誌型別。 方案:最好的選擇就是用註解標記切點,用AOP實現此需求。 一、準備 版本: J

實現從命令列引數輸入兩個字串型別的數值,計算輸出兩個數值的和。 [必做題]

import java.io.UnsupportedEncodingException; import java.util.Scanner; public class ZiFuChuanHe { public static void main(String[] args) throws

使用攔截器獲取請求引數資訊寫入日誌

前言 使用攔截器獲取請求的引數,ip地址等等資訊,然後寫入日誌更加方便後期異常的維護。 2.程式碼例項 public class RequestParamInfoIntorceptor extends HandlerInterceptorAdapter

SpringAOP攔截Controller,Service實現日誌管理(自定義註解的方式)

         首先我們為什麼需要做日誌管理,在現實的上線中我們經常會遇到系統出現異常或者問題。這個時候就馬上開啟CRT或者SSH連上伺服器拿日子來分析。受網路的各種限制。於是我們就想為什麼不能直接在管理後臺檢視報錯的資訊呢。於是日誌管理就出現了。          其次

SpringAOP攔截Controller,Service實現日誌管理(自定義註解的方式)(轉載)

http://langgufu.iteye.com/blog/2235556   首先我們為什麼需要做日誌管理,在現實的上線中我們經常會遇到系統出現異常或者問題。這個時候就馬上開啟CRT或者SSH連上伺服器拿日子來分析。受網路的各種限制。於是我們就想為什麼不能直接在