Showing
9 changed files
with
368 additions
and
7 deletions
1 | 1 | package org.thingsboard.server.config.yunteng; |
2 | 2 | |
3 | +import com.datastax.oss.driver.api.core.uuid.Uuids; | |
3 | 4 | import lombok.RequiredArgsConstructor; |
5 | +import lombok.extern.slf4j.Slf4j; | |
6 | +import org.apache.http.HttpHeaders; | |
4 | 7 | import org.springframework.http.HttpStatus; |
5 | 8 | import org.springframework.security.access.AccessDeniedException; |
6 | -import org.springframework.security.authentication.AccountExpiredException; | |
9 | +import org.springframework.security.core.Authentication; | |
10 | +import org.springframework.security.core.context.SecurityContextHolder; | |
7 | 11 | import org.springframework.web.bind.MethodArgumentNotValidException; |
8 | 12 | import org.springframework.web.bind.annotation.ControllerAdvice; |
9 | 13 | import org.springframework.web.bind.annotation.ExceptionHandler; |
14 | +import org.thingsboard.server.common.data.EntityType; | |
15 | +import org.thingsboard.server.common.data.asset.Asset; | |
16 | +import org.thingsboard.server.common.data.audit.ActionType; | |
17 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | |
18 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | |
19 | +import org.thingsboard.server.common.data.id.EntityId; | |
10 | 20 | import org.thingsboard.server.common.data.yunteng.core.exception.*; |
11 | 21 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
22 | +import org.thingsboard.server.common.data.yunteng.dto.SysLogOperateDTO; | |
23 | +import org.thingsboard.server.dao.audit.AuditLogService; | |
12 | 24 | import org.thingsboard.server.exception.yunteng.YunTengErrorResponseHandler; |
25 | +import org.thingsboard.server.service.security.model.SecurityUser; | |
26 | +import org.thingsboard.server.utils.yunteng.LogUtils; | |
13 | 27 | |
14 | 28 | import javax.servlet.http.HttpServletRequest; |
15 | 29 | import javax.servlet.http.HttpServletResponse; |
16 | 30 | import java.util.Objects; |
31 | +import java.util.UUID; | |
17 | 32 | |
18 | 33 | @ControllerAdvice(basePackages = "org.thingsboard.server.controller.yunteng") |
19 | 34 | @RequiredArgsConstructor |
35 | +@Slf4j | |
20 | 36 | public class ControllerExceptionHandler { |
21 | 37 | |
38 | + private final AuditLogService auditLogService; | |
22 | 39 | private final YunTengErrorResponseHandler errorResponseHandler; |
23 | 40 | |
24 | 41 | @ExceptionHandler(YunTengException.class) |
25 | - public void handleYunTengException(YunTengException ex, HttpServletResponse response) { | |
42 | + public void handleYunTengException(YunTengException ex,HttpServletRequest request, HttpServletResponse response) { | |
43 | + produceLog( request, ex); | |
26 | 44 | errorResponseHandler.handle(ex, response); |
27 | 45 | } |
28 | 46 | |
29 | 47 | @ExceptionHandler(MethodArgumentNotValidException.class) |
30 | 48 | public void handleMethodArgumentNotValidException( |
31 | - MethodArgumentNotValidException ex, HttpServletResponse response) { | |
49 | + MethodArgumentNotValidException ex,HttpServletRequest request, HttpServletResponse response) { | |
50 | + produceLog( request, ex); | |
32 | 51 | errorResponseHandler.handle( |
33 | 52 | new YunTengException( |
34 | 53 | ErrorMessage.INVALID_PARAMETER.setMessage( |
... | ... | @@ -40,6 +59,7 @@ public class ControllerExceptionHandler { |
40 | 59 | @ExceptionHandler(YtDataValidationException.class) |
41 | 60 | public void handleDataValidationException( |
42 | 61 | YtDataValidationException ex, HttpServletRequest request, HttpServletResponse response) { |
62 | + produceLog( request, ex); | |
43 | 63 | YunTengException YunTengException = |
44 | 64 | new YunTengException( |
45 | 65 | ErrorMessage.BAD_PARAMETER.setMessage(ex.getMessage()), HttpStatus.BAD_REQUEST); |
... | ... | @@ -54,7 +74,8 @@ public class ControllerExceptionHandler { |
54 | 74 | } |
55 | 75 | |
56 | 76 | @ExceptionHandler(AccessDeniedException.class) |
57 | - public void handleAccessDeniedException(AccessDeniedException ex, HttpServletResponse response) { | |
77 | + public void handleAccessDeniedException(AccessDeniedException ex,HttpServletRequest request, HttpServletResponse response) { | |
78 | + produceLog( request, ex); | |
58 | 79 | errorResponseHandler.handle( |
59 | 80 | new YunTengException( |
60 | 81 | ErrorMessage.ACCESS_DENIED.setMessage(ex.getMessage()), HttpStatus.FORBIDDEN), |
... | ... | @@ -63,7 +84,8 @@ public class ControllerExceptionHandler { |
63 | 84 | |
64 | 85 | @ExceptionHandler(NoneTenantAssetException.class) |
65 | 86 | public void handleNoneTenantAssetException( |
66 | - NoneTenantAssetException ex, HttpServletResponse response) { | |
87 | + NoneTenantAssetException ex, HttpServletRequest request, HttpServletResponse response) { | |
88 | + produceLog( request, ex); | |
67 | 89 | errorResponseHandler.handle( |
68 | 90 | new YunTengException( |
69 | 91 | ErrorMessage.NONE_TENANT_ASSET.setMessage(ex.getMessage()), HttpStatus.NOT_FOUND), |
... | ... | @@ -77,4 +99,58 @@ public class ControllerExceptionHandler { |
77 | 99 | ErrorMessage.SEND_DESTINATION_NOT_FOUND, HttpStatus.PRECONDITION_FAILED), |
78 | 100 | response); |
79 | 101 | } |
102 | + | |
103 | + | |
104 | + | |
105 | + protected SecurityUser getCurrentUser() throws ThingsboardException { | |
106 | + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | |
107 | + if (authentication != null && authentication.getPrincipal() instanceof SecurityUser) { | |
108 | + return (SecurityUser) authentication.getPrincipal(); | |
109 | + } else { | |
110 | + throw new ThingsboardException("You aren't authorized to perform this operation!", ThingsboardErrorCode.AUTHENTICATION); | |
111 | + } | |
112 | + } | |
113 | + | |
114 | + /** | |
115 | + * 生产日志并缓存到队列中 | |
116 | + * | |
117 | + * @param request 响应头 | |
118 | + * @param e 异常信息 | |
119 | + */ | |
120 | + void produceLog(HttpServletRequest request, Exception e) { | |
121 | + | |
122 | + try { | |
123 | + SecurityUser currentUser = getCurrentUser(); | |
124 | + | |
125 | + Asset entity = new Asset(); | |
126 | + entity.setName(e.getMessage()); | |
127 | + | |
128 | + //请求相关信息 | |
129 | + SysLogOperateDTO additionalInfo = new SysLogOperateDTO(); | |
130 | + additionalInfo.setApi(request.getRequestURI()); | |
131 | + additionalInfo.setClientIp(LogUtils.clientIP(request)); | |
132 | + additionalInfo.setServerIp(LogUtils.serverIP()); | |
133 | + additionalInfo.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); | |
134 | + additionalInfo.setMethod(request.getMethod()); | |
135 | + | |
136 | + | |
137 | + EntityId operateId = new EntityId() { | |
138 | + @Override | |
139 | + public UUID getId() { | |
140 | + return Uuids.timeBased(); | |
141 | + } | |
142 | + | |
143 | + @Override | |
144 | + public EntityType getEntityType() { | |
145 | + return EntityType.RUNNING_EXCEPTION; | |
146 | + } | |
147 | + }; | |
148 | + | |
149 | + | |
150 | + auditLogService.logEntityAction(currentUser.getTenantId(),currentUser.getCustomerId(),currentUser.getId(), currentUser.getName(), operateId,entity, ActionType.LOG_EXCEPTION,e,additionalInfo); | |
151 | + } catch (ThingsboardException ex) { | |
152 | + log.error("异常日志记录异常【{}】",ex); | |
153 | + } | |
154 | + | |
155 | + } | |
80 | 156 | } | ... | ... |
... | ... | @@ -19,6 +19,7 @@ import org.thingsboard.server.common.data.yunteng.dto.SceneLinkageDTO; |
19 | 19 | import org.thingsboard.server.common.data.yunteng.dto.TriggerDTO; |
20 | 20 | import org.thingsboard.server.common.data.yunteng.utils.tools.YtPageData; |
21 | 21 | import org.thingsboard.server.controller.BaseController; |
22 | +import org.thingsboard.server.controller.yunteng.aspect.annotation.AutoLog; | |
22 | 23 | import org.thingsboard.server.dao.yunteng.service.SceneLinkageService; |
23 | 24 | |
24 | 25 | import java.net.URI; |
... | ... | @@ -71,6 +72,7 @@ public class YtSceneLinkageController extends BaseController { |
71 | 72 | |
72 | 73 | @ApiOperation("查询(分页列表)") |
73 | 74 | @GetMapping(params = {PAGE_SIZE, PAGE}) |
75 | + @AutoLog("场景联动分页") | |
74 | 76 | public YtPageData<SceneLinkageDTO> page( |
75 | 77 | @RequestParam(PAGE_SIZE) int pageSize, |
76 | 78 | @RequestParam(PAGE) int page, | ... | ... |
application/src/main/java/org/thingsboard/server/controller/yunteng/aspect/OperateLogAspect.java
0 → 100644
1 | +package org.thingsboard.server.controller.yunteng.aspect; | |
2 | + | |
3 | + | |
4 | +import com.datastax.oss.driver.api.core.uuid.Uuids; | |
5 | +import lombok.extern.slf4j.Slf4j; | |
6 | +import org.apache.http.HttpHeaders; | |
7 | +import org.aspectj.lang.JoinPoint; | |
8 | +import org.aspectj.lang.ProceedingJoinPoint; | |
9 | +import org.aspectj.lang.annotation.AfterThrowing; | |
10 | +import org.aspectj.lang.annotation.Around; | |
11 | +import org.aspectj.lang.annotation.Aspect; | |
12 | +import org.aspectj.lang.annotation.Pointcut; | |
13 | +import org.aspectj.lang.reflect.MethodSignature; | |
14 | +import org.springframework.core.annotation.Order; | |
15 | +import org.springframework.security.core.Authentication; | |
16 | +import org.springframework.security.core.context.SecurityContextHolder; | |
17 | +import org.springframework.stereotype.Component; | |
18 | +import org.springframework.web.context.request.RequestAttributes; | |
19 | +import org.springframework.web.context.request.RequestContextHolder; | |
20 | +import org.springframework.web.context.request.ServletRequestAttributes; | |
21 | +import org.thingsboard.server.common.data.EntityType; | |
22 | +import org.thingsboard.server.common.data.asset.Asset; | |
23 | +import org.thingsboard.server.common.data.audit.ActionStatus; | |
24 | +import org.thingsboard.server.common.data.audit.ActionType; | |
25 | +import org.thingsboard.server.common.data.audit.AuditLog; | |
26 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | |
27 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | |
28 | +import org.thingsboard.server.common.data.id.EntityId; | |
29 | +import org.thingsboard.server.common.data.yunteng.dto.SysLogOperateDTO; | |
30 | +import org.thingsboard.server.controller.yunteng.aspect.annotation.AutoLog; | |
31 | +import org.thingsboard.server.dao.audit.AuditLogService; | |
32 | +import org.thingsboard.server.service.security.model.SecurityUser; | |
33 | +import org.thingsboard.server.utils.yunteng.LogUtils; | |
34 | + | |
35 | +import javax.servlet.http.HttpServletRequest; | |
36 | +import java.lang.reflect.Method; | |
37 | +import java.util.UUID; | |
38 | + | |
39 | +/** | |
40 | + * | |
41 | + */ | |
42 | +@Aspect | |
43 | +@Order() | |
44 | +@Component | |
45 | +@Slf4j | |
46 | +public class OperateLogAspect { | |
47 | + private final AuditLogService auditLogService; | |
48 | + | |
49 | + public OperateLogAspect(AuditLogService auditLogService) { | |
50 | + this.auditLogService = auditLogService; | |
51 | + } | |
52 | + | |
53 | + | |
54 | + /** | |
55 | + * AOP监听的切入点 | |
56 | + * 注解所在方法的方法体为空 | |
57 | + * 匹配规则可以和逻辑运算符(&&、||、!)配合使用 | |
58 | + * 匹配规则:注解【"@annotation(com.lifeontrip.base.annotation.RecordLog)"】 | |
59 | + * 匹配规则:方法【"execution(public * com.lifeontrip.base.controller..*.*(..))"】 | |
60 | + * 匹配规则:注解【“@within(com.lifeontrip.base.annotation.RecordLog)”】 | |
61 | + * 匹配规则:代理对象【“@this”】 | |
62 | + * 匹配规则:类注解【“@target”】 | |
63 | + * 匹配规则:方法入参【“@args”】 | |
64 | + */ | |
65 | + @Pointcut("@annotation(org.thingsboard.server.controller.yunteng.aspect.annotation.AutoLog)") | |
66 | + public void accessLog() { | |
67 | + } | |
68 | + | |
69 | + | |
70 | + @Around("accessLog()") | |
71 | + public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { | |
72 | + | |
73 | + /**执行切入点所在方法的业务逻辑*/ | |
74 | + Object result = joinPoint.proceed(); | |
75 | + | |
76 | + | |
77 | + produceLog(joinPoint, result); | |
78 | + return result; | |
79 | + | |
80 | + } | |
81 | + | |
82 | + | |
83 | + /** | |
84 | + * 切入点方法执行异常,调用该方法 | |
85 | + * | |
86 | + * @param joinPoint 切入点相关信息的实例 | |
87 | + * @param e 切入点抛出的异常 | |
88 | + */ | |
89 | + @AfterThrowing(value = "accessLog()", throwing = "e") | |
90 | + public void doException(JoinPoint joinPoint, Exception e) { | |
91 | + log.error("日志功能AOP异常【{}】", e); | |
92 | + } | |
93 | + | |
94 | + | |
95 | + /** | |
96 | + * 生产日志并缓存到队列中 | |
97 | + * | |
98 | + * @param joinPoint 切入点相关信息的实例 | |
99 | + * @param jsonResult 切入点执行后返回的结果 | |
100 | + */ | |
101 | + void produceLog(final JoinPoint joinPoint, Object jsonResult) throws ThingsboardException { | |
102 | + | |
103 | + SecurityUser currentUser = getCurrentUser(); | |
104 | + | |
105 | + //方法注解 | |
106 | + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | |
107 | + Method method = signature.getMethod(); | |
108 | + AutoLog methodAnnotate = method.getAnnotation(AutoLog.class); | |
109 | + | |
110 | + Asset entity = new Asset(); | |
111 | + if (methodAnnotate != null) { | |
112 | + entity.setName(methodAnnotate.value()); | |
113 | + } | |
114 | + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); | |
115 | + if(requestAttributes == null){ | |
116 | + return; | |
117 | + } | |
118 | + HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); | |
119 | + //请求相关信息 | |
120 | + SysLogOperateDTO additionalInfo = new SysLogOperateDTO(); | |
121 | + | |
122 | + | |
123 | + additionalInfo.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); | |
124 | + additionalInfo.setData(request.getMethod()); | |
125 | + additionalInfo.setApi(request.getRequestURI()); | |
126 | + additionalInfo.setClientIp(LogUtils.clientIP(request)); | |
127 | + additionalInfo.setServerIp(LogUtils.serverIP()); | |
128 | + additionalInfo.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); | |
129 | + additionalInfo.setMethod(request.getMethod()); | |
130 | + | |
131 | + | |
132 | + EntityId operateId = new EntityId() { | |
133 | + @Override | |
134 | + public UUID getId() { | |
135 | + return Uuids.timeBased(); | |
136 | + } | |
137 | + | |
138 | + @Override | |
139 | + public EntityType getEntityType() { | |
140 | + return EntityType.REST_API; | |
141 | + } | |
142 | + }; | |
143 | + | |
144 | + | |
145 | + auditLogService.logEntityAction(currentUser.getTenantId(),currentUser.getCustomerId(),currentUser.getId(), currentUser.getName(), operateId,entity, ActionType.LOG_OPERATE,null,additionalInfo); | |
146 | + } | |
147 | + | |
148 | + protected SecurityUser getCurrentUser() throws ThingsboardException { | |
149 | + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | |
150 | + if (authentication != null && authentication.getPrincipal() instanceof SecurityUser) { | |
151 | + return (SecurityUser) authentication.getPrincipal(); | |
152 | + } else { | |
153 | + throw new ThingsboardException("You aren't authorized to perform this operation!", ThingsboardErrorCode.AUTHENTICATION); | |
154 | + } | |
155 | + } | |
156 | + | |
157 | +} | ... | ... |
application/src/main/java/org/thingsboard/server/controller/yunteng/aspect/annotation/AutoLog.java
0 → 100644
1 | +package org.thingsboard.server.controller.yunteng.aspect.annotation; | |
2 | + | |
3 | +import java.lang.annotation.*; | |
4 | + | |
5 | +/** | |
6 | + * 操作日志注解 | |
7 | + * | |
8 | + * @author Administrator | |
9 | + */ | |
10 | +@Target(ElementType.METHOD) | |
11 | +@Retention(RetentionPolicy.RUNTIME) | |
12 | +@Documented | |
13 | +public @interface AutoLog { | |
14 | + | |
15 | + /** | |
16 | + * 功能名称 | |
17 | + */ | |
18 | + String value() default ""; | |
19 | + | |
20 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.utils.yunteng; | |
17 | + | |
18 | +import lombok.Data; | |
19 | +import lombok.extern.slf4j.Slf4j; | |
20 | +import org.apache.commons.lang3.StringUtils; | |
21 | + | |
22 | +import javax.servlet.http.HttpServletRequest; | |
23 | +import java.io.Serializable; | |
24 | +import java.net.InetAddress; | |
25 | +import java.net.UnknownHostException; | |
26 | + | |
27 | +@Data | |
28 | +@Slf4j | |
29 | +public class LogUtils implements Serializable { | |
30 | + | |
31 | + | |
32 | + public static String clientIP(HttpServletRequest request) { | |
33 | + String ip = null; | |
34 | + try { | |
35 | + ip = request.getHeader("x-forwarded-for"); | |
36 | + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { | |
37 | + ip = request.getHeader("Proxy-Client-IP"); | |
38 | + } | |
39 | + if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { | |
40 | + ip = request.getHeader("WL-Proxy-Client-IP"); | |
41 | + } | |
42 | + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { | |
43 | + ip = request.getHeader("HTTP_CLIENT_IP"); | |
44 | + } | |
45 | + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { | |
46 | + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); | |
47 | + } | |
48 | + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { | |
49 | + ip = request.getRemoteAddr(); | |
50 | + } | |
51 | + } catch (Exception e) { | |
52 | + log.error("客户端IP异常【{}】", e); | |
53 | + } | |
54 | + | |
55 | + return ip; | |
56 | + } | |
57 | + | |
58 | + | |
59 | + /** | |
60 | + * 当前主机IP | |
61 | + * @return | |
62 | + * @throws UnknownHostException | |
63 | + */ | |
64 | + public static String serverIP() { | |
65 | + String ip = null; | |
66 | + try { | |
67 | + ip = InetAddress.getLocalHost().getHostAddress(); | |
68 | + } catch (UnknownHostException e) { | |
69 | + log.error("服务端IP异常【{}】 ", e); | |
70 | + } | |
71 | + return ip; | |
72 | + } | |
73 | + | |
74 | +} | ... | ... |
... | ... | @@ -562,6 +562,8 @@ audit-log: |
562 | 562 | "edge": "${AUDIT_LOG_MASK_EDGE:W}" |
563 | 563 | "tb_resource": "${AUDIT_LOG_MASK_RESOURCE:W}" |
564 | 564 | "ota_package": "${AUDIT_LOG_MASK_OTA_PACKAGE:W}" |
565 | + "running_exception": "${AUDIT_LOG_RUNNING_EXCEPTION:W}" | |
566 | + "rest_api": "${AUDIT_LOG_REST_API:W}" | |
565 | 567 | sink: |
566 | 568 | # Type of external sink. possible options: none, elasticsearch |
567 | 569 | type: "${AUDIT_LOG_SINK_TYPE:none}" | ... | ... |
... | ... | @@ -19,5 +19,7 @@ package org.thingsboard.server.common.data; |
19 | 19 | * @author Andrew Shvayka |
20 | 20 | */ |
21 | 21 | public enum EntityType { |
22 | - TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, API_USAGE_STATE, TB_RESOURCE, OTA_PACKAGE, EDGE, RPC; | |
22 | + TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, API_USAGE_STATE, TB_RESOURCE, OTA_PACKAGE, EDGE, RPC | |
23 | + //Thingskit function | |
24 | + , RUNNING_EXCEPTION, REST_API; | |
23 | 25 | } | ... | ... |
... | ... | @@ -48,7 +48,10 @@ public enum ActionType { |
48 | 48 | PROVISION_SUCCESS(false), |
49 | 49 | PROVISION_FAILURE(false), |
50 | 50 | ASSIGNED_TO_EDGE(false), // log edge name |
51 | - UNASSIGNED_FROM_EDGE(false); | |
51 | + UNASSIGNED_FROM_EDGE(false), | |
52 | + //Thingskit function | |
53 | + LOG_EXCEPTION(false), | |
54 | + LOG_OPERATE(false); | |
52 | 55 | |
53 | 56 | private final boolean isRead; |
54 | 57 | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/SysLogOperateDTO.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.dto; | |
2 | + | |
3 | +import io.swagger.annotations.ApiModel; | |
4 | +import io.swagger.annotations.ApiModelProperty; | |
5 | +import lombok.Data; | |
6 | +import lombok.EqualsAndHashCode; | |
7 | + | |
8 | +@EqualsAndHashCode(callSuper = false) | |
9 | +@Data | |
10 | +public class SysLogOperateDTO { | |
11 | + | |
12 | + | |
13 | + private String serverIp; | |
14 | + | |
15 | + | |
16 | + private String remark; | |
17 | + | |
18 | + | |
19 | + private String clientIp; | |
20 | + private String clientAddr; | |
21 | + private String userAgent; | |
22 | + private String api; | |
23 | + private String data; | |
24 | + private String method; | |
25 | +} | ... | ... |