


Wie implementiert man die Vorgangsprotokollierung elegant in einem Java SpringBoot-Projekt?
1. Was ist AOP?
AOP (Aspektorientierte Programmierung) Apropos AOP: Fast jeder, der das Spring-Framework studiert hat, weiß, dass es eine der drei Kernideen von Spring ist (IOC: Inversion of Control, DI: Dependency Injection, AOP: Aspect Oriented). Programmierung). Es kann Logik oder Verantwortlichkeiten (z. B. Transaktionsverarbeitung, Protokollverwaltung, Berechtigungskontrolle usw.) kapseln, die nicht mit dem Geschäft zusammenhängen, aber üblicherweise von den Geschäftsmodulen aufgerufen werden, um die Duplizierung von Code im System zu reduzieren und zu reduzieren die Kopplung zwischen Modulen und trägt zur zukünftigen Skalierbarkeit und Wartbarkeit bei.
2. Was hat AOP gemacht?
Einfach ausgedrückt macht AOP hauptsächlich drei Dinge:
1 Wo eingeschnitten werden soll, das heißt, in welchem Geschäftscode Nicht-Geschäftscode wie die Protokollierung ausgeführt wird.
2. Wann einzuschneiden ist, vor oder nach der Ausführung des Geschäftscodes.
3. Was nach dem Einschalten zu tun ist, z. B. Berechtigungsüberprüfung, Protokollierung usw.
kann mit einem Bild verstanden werden:
Erklärung eines Kernbegriffs auf dem Bild:
Punktschnitt: Schnittpunkt, entscheiden Sie, wo in den Geschäftscode geschnitten werden soll Mitte (d. h. in die Schnittfläche eingewebt). Pointcuts sind in Ausführungsmodus und Anmerkungsmodus unterteilt. Ausführungsmodus: Sie können Pfadausdrücke verwenden, um anzugeben, welche Klassen in Aspekte eingebunden werden. Annotationsmodus: Sie können angeben, welcher annotationsmodifizierte Code in Aspekte eingebunden wird.
Hinweis: Verarbeitung, einschließlich Verarbeitungszeitpunkt und Verarbeitungsinhalt. Das Verarbeiten von Inhalten bedeutet, etwas zu tun, beispielsweise Berechtigungen zu überprüfen und Protokolle aufzuzeichnen. Der Verarbeitungszeitpunkt bezieht sich auf den Zeitpunkt der Ausführung des Verarbeitungsinhalts, der in Vorverarbeitung (dh vor der Ausführung des Geschäftscodes), Nachverarbeitung (nach der Ausführung des Geschäftscodes) usw. unterteilt wird.
Aspekt: Aspekt, nämlich Pointcut und Advice.
Joint Point: Joint Point ist ein Punkt der Programmausführung. Beispielsweise die Ausführung einer Methode oder die Behandlung einer Ausnahme. In Spring AOP stellt ein Join-Punkt immer eine Methodenausführung dar.
Weaving: Weaving ist der Prozess der Inhaltsverarbeitung in der Zielobjektmethode durch dynamischen Proxy.
3. Implementierungsschritte
(1) Passen Sie eine Annotation @Log an (2) Erstellen Sie eine Aspektklasse, legen Sie den Schnittpunkt fest, um die mit @Log annotierte Methode abzufangen, fangen Sie die übergebenen Parameter ab und führen Sie die Protokollierung durch. (3) Ändern @ Protokoll ist auf der Schnittstelle markiert
Die spezifischen Implementierungsschritte sind wie folgt:
1. AOP-Abhängigkeit hinzufügen
Der Code lautet wie folgt (Beispiel):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2. Passen Sie eine Protokollanmerkung an
Im Allgemeinen werden Annotationen für Protokolle verwendet. Geben Sie Pointcut-Ausdrücke ein. Wir erstellen zunächst eine Protokollanmerkung. Wenn der Spring-Container die Methode mit dieser Annotation scannt, wird sie erweitert.
Der Code lautet wie folgt (Beispiel):
@Target({ ElementType.PARAMETER, ElementType.METHOD }) // 注解放置的目标位置,PARAMETER: 可用在参数上 METHOD:可用在方法级别上 @Retention(RetentionPolicy.RUNTIME) // 指明修饰的注解的生存周期 RUNTIME:运行级别保留 @Documented public @interface Log { /** * 模块 */ String title() default ""; /** * 功能 */ public BusinessType businessType() default BusinessType.OTHER; /** * 是否保存请求的参数 */ public boolean isSaveRequestData() default true; /** * 是否保存响应的参数 */ public boolean isSaveResponseData() default true; }
3. Aspektdeklaration
Deklarieren Sie eine Aspektklasse und übergeben Sie sie zur Verwaltung an den Spring-Container.
Der Code lautet wie folgt (Beispiel):
@Aspect @Component @Slf4j public class LogAspect { @Autowired private IXlOperLogService operLogService; /** * 处理完请求后执行 * @param joinPoint 切点 */ @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") public void doAfterReturnibng(JoinPoint joinPoint, Log controllerLog, Object jsonResult) { handleLog(joinPoint, controllerLog, null, jsonResult); } protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) { try { // 获取当前的用户 JwtUser loginUser = SecurityUtils.getLoginUser(); // 日志记录 XlOperLog operLog = new XlOperLog(); operLog.setStatus(0); // 请求的IP地址 String iP = ServletUtil.getClientIP(ServletUtils.getRequest()); if ("0:0:0:0:0:0:0:1".equals(iP)) { iP = "127.0.0.1"; } operLog.setOperIp(iP); operLog.setOperUrl(ServletUtils.getRequest().getRequestURI()); if (loginUser != null) { operLog.setOperName(loginUser.getUsername()); } if (e != null) { operLog.setStatus(1); operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); } // 设置方法名称 String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); operLog.setMethod(className + "." + methodName + "()"); operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); operLog.setOperTime(new Date()); // 处理设置注解上的参数 getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); // 保存数据库 operLogService.save(operLog); } catch (Exception exp) { log.error("异常信息:{}", exp.getMessage()); exp.printStackTrace(); } } /** * 获取注解中对方法的描述信息 用于Controller层注解 * @param log 日志 * @param operLog 操作日志 * @throws Exception */ public void getControllerMethodDescription(JoinPoint joinPoint, Log log, XlOperLog operLog, Object jsonResult) throws Exception { // 设置操作业务类型 operLog.setBusinessType(log.businessType().ordinal()); // 设置标题 operLog.setTitle(log.title()); // 是否需要保存request,参数和值 if (log.isSaveRequestData()) { // 设置参数的信息 setRequestValue(joinPoint, operLog); } // 是否需要保存response,参数和值 if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) { operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000)); } } /** * 获取请求的参数,放到log中 * @param operLog 操作日志 * @throws Exception 异常 */ private void setRequestValue(JoinPoint joinPoint, XlOperLog operLog) throws Exception { String requsetMethod = operLog.getRequestMethod(); if (HttpMethod.PUT.name().equals(requsetMethod) || HttpMethod.POST.name().equals(requsetMethod)) { String parsams = argsArrayToString(joinPoint.getArgs()); operLog.setOperParam(StringUtils.substring(parsams,0,2000)); } else { Map<?,?> paramsMap = (Map<?,?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); operLog.setOperParam(StringUtils.substring(paramsMap.toString(),0,2000)); } } /** * 参数拼装 */ private String argsArrayToString(Object[] paramsArray) { String params = ""; if (paramsArray != null && paramsArray.length > 0) { for (Object object : paramsArray) { // 不为空 并且是不需要过滤的 对象 if (StringUtils.isNotNull(object) && !isFilterObject(object)) { Object jsonObj = JSON.toJSON(object); params += jsonObj.toString() + " "; } } } return params.trim(); } /** * 判断是否需要过滤的对象。 * @param object 对象信息。 * @return 如果是需要过滤的对象,则返回true;否则返回false。 */ @SuppressWarnings("rawtypes") public boolean isFilterObject(final Object object) { Class<?> clazz = object.getClass(); if (clazz.isArray()) { return clazz.getComponentType().isAssignableFrom(MultipartFile.class); } else if (Collection.class.isAssignableFrom(clazz)) { Collection collection = (Collection) object; for (Object value : collection) { return value instanceof MultipartFile; } } else if (Map.class.isAssignableFrom(clazz)) { Map map = (Map) object; for (Object value : map.entrySet()) { Map.Entry entry = (Map.Entry) value; return entry.getValue() instanceof MultipartFile; } } return object instanceof MultipartFile || object instanceof HttpServletRequest || object instanceof HttpServletResponse || object instanceof BindingResult; } }
4. Markieren Sie ihn auf der Schnittstelle.
Markieren Sie die benutzerdefinierte Anmerkung auf der Schnittstelle, die zum Aufzeichnen des Betriebsprotokolls benötigt wird. Der Code lautet wie folgt (Beispiel):
@Log(title = "代码生成", businessType = BusinessType.GENCODE) @ApiOperation(value = "批量生成代码") @GetMapping("/download/batch") public void batchGenCode(HttpServletResponse response, String tables) throws IOException { String[] tableNames = Convert.toStrArray(tables); byte[] data = genTableService.downloadCode(tableNames); genCode(response, data); }
5. Implementierungseffekt
Protokolle werden aufgezeichnet, wenn relevante Vorgänge ausgeführt werden, und einige grundlegende Informationen werden aufgezeichnet und in der Datentabelle gespeichert.
Das obige ist der detaillierte Inhalt vonWie implementiert man die Vorgangsprotokollierung elegant in einem Java SpringBoot-Projekt?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



Leitfaden zur perfekten Zahl in Java. Hier besprechen wir die Definition, Wie prüft man die perfekte Zahl in Java?, Beispiele mit Code-Implementierung.

Leitfaden zum Zufallszahlengenerator in Java. Hier besprechen wir Funktionen in Java anhand von Beispielen und zwei verschiedene Generatoren anhand ihrer Beispiele.

Leitfaden für Weka in Java. Hier besprechen wir die Einführung, die Verwendung von Weka Java, die Art der Plattform und die Vorteile anhand von Beispielen.

Leitfaden zur Smith-Zahl in Java. Hier besprechen wir die Definition: Wie überprüft man die Smith-Nummer in Java? Beispiel mit Code-Implementierung.

In diesem Artikel haben wir die am häufigsten gestellten Fragen zu Java Spring-Interviews mit ihren detaillierten Antworten zusammengestellt. Damit Sie das Interview knacken können.

Java 8 führt die Stream -API ein und bietet eine leistungsstarke und ausdrucksstarke Möglichkeit, Datensammlungen zu verarbeiten. Eine häufige Frage bei der Verwendung von Stream lautet jedoch: Wie kann man von einem Foreach -Betrieb brechen oder zurückkehren? Herkömmliche Schleifen ermöglichen eine frühzeitige Unterbrechung oder Rückkehr, aber die Stream's foreach -Methode unterstützt diese Methode nicht direkt. In diesem Artikel werden die Gründe erläutert und alternative Methoden zur Implementierung vorzeitiger Beendigung in Strahlverarbeitungssystemen erforscht. Weitere Lektüre: Java Stream API -Verbesserungen Stream foreach verstehen Die Foreach -Methode ist ein Terminalbetrieb, der einen Vorgang für jedes Element im Stream ausführt. Seine Designabsicht ist

Anleitung zum TimeStamp to Date in Java. Hier diskutieren wir auch die Einführung und wie man Zeitstempel in Java in ein Datum konvertiert, zusammen mit Beispielen.

Java ist eine beliebte Programmiersprache, die sowohl von Anfängern als auch von erfahrenen Entwicklern erlernt werden kann. Dieses Tutorial beginnt mit grundlegenden Konzepten und geht dann weiter zu fortgeschrittenen Themen. Nach der Installation des Java Development Kit können Sie das Programmieren üben, indem Sie ein einfaches „Hello, World!“-Programm erstellen. Nachdem Sie den Code verstanden haben, verwenden Sie die Eingabeaufforderung, um das Programm zu kompilieren und auszuführen. Auf der Konsole wird „Hello, World!“ ausgegeben. Mit dem Erlernen von Java beginnt Ihre Programmierreise, und wenn Sie Ihre Kenntnisse vertiefen, können Sie komplexere Anwendungen erstellen.
