Springboot-주해-조작 로그 의 실현 방식
12787 단어 Springboot주해로그
누구?
이 구성 요 소 는 현재 Spring-boot 에 대해 Autoconfig 를 만 들 었 습 니 다.SpringMVC 라면 xml 에서 bean 을 초기 화 할 수 있 습 니 다.
사용 방식
기본 사용
maven 의존 SDK 의존 추가
<dependency>
<groupId>io.github.mouzt</groupId>
<artifactId>bizlog-sdk</artifactId>
<version>1.0.1</version>
</dependency>
SpringBoot 입구 에서 스위치 를 열 고@EnableLogRecord 주 해 를 추가 합 니 다.tenant 는 세입 자 를 대표 하 는 표지 로 보통 하나의 서비스 나 한 업무 에서 의 여러 서 비 스 는 하나의 tenant 를 쓰 면 된다.
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableTransactionManagement
@EnableLogRecord(tenant = "com.mzt.test")
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
로그 매 립 점1.일반적인 기록 로그
pefix:bizNo 에 로그 로 연결 되 어 있 는 표지 입 니 다.bizNo 가 정수 ID 일 때 다른 업무 의 ID 와 중복 되 지 않도록 합 니 다.예 를 들 어 주문 ID,사용자 ID 등
bizNo:바로 업무 의 ID 입 니 다.예 를 들 어 주문 ID 입 니 다.저희 가 조회 할 때 bizNo 에 따라 관련 작업 로 그 를 조회 할 수 있 습 니 다.
success:방법 호출 성공 후 success 를 로그 내용 에 기록 합 니 다.
SpEL 표현 식:이중 괄호 로 둘러싸 인(예:{\#order.purchase Name})\#order.purchase Name 은 SpEL 표현 식 입 니 다.Spring 에서 지원 하 는 것 은 모두 지원 합 니 다.예 를 들 어 정적 방법,세 가지 표현 식 을 호출 합 니 다.SpEL 은 방법 중의 모든 인 자 를 사용 할 수 있 습 니 다.
@LogRecordAnnotation(success = "{{#order.purchaseName}} , 「{{#order.productName}}」, :{{#_ret}}",
prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")
public boolean createOrder(Order order) {
log.info("【 】orderNo={}", order.getOrderNo());
// db insert order
return true;
}
이 때 작업 로 그 를 인쇄 합 니 다."장 3 에서 주문 서 를 내 렸 습 니 다.상품 을 구 매 합 니 다."초 특급 할인 불고기 세트"를 구 매 합 니 다.주문 결과:true"2.실패 로 그 를 기록 하 기 를 원 합 니 다.이상 을 던 지면 fail 로 그 를 기록 하고 success 로 그 를 기록 하지 않 습 니 다.
@LogRecordAnnotation(
fail = " , :「{{#_errorMsg}}」",
success = "{{#order.purchaseName}} , 「{{#order.productName}}」, :{{#_ret}}",
prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")
public boolean createOrder(Order order) {
log.info("【 】orderNo={}", order.getOrderNo());
// db insert order
return true;
}
그 중의\#errorMsg 는 이상 한 errorMessage 를 던 지 는 방법 입 니 다.3.로그 지원 종류
예 를 들 어 주문 한 작업 로그,일부 작업 로 그 는 사용자 가 직접 작 동 합 니 다.일부 작업 은 시스템 운영 자가 수정 한 작업 로 그 를 만 들 었 습 니 다.저희 시스템 은 운영 로 그 를 사용자 에 게 노출 시 키 고 싶 지 않 습 니 다.
그러나 운영 은 사용자 의 로그 와 자신 이 조작 한 로 그 를 볼 수 있 기 를 기대 합 니 다.이 작업 로 그 를 운영 하 는 bizNo 는 모두 주문 번호 이기 때문에 형식 필드 를 확장 하기 위해 로 그 를 분류 하고 조회 가 편리 하 며 더 많은 업 무 를 지원 합 니 다.
@LogRecordAnnotation(
fail = " , :「{{#_errorMsg}}」",
category = "MANAGER",
success = "{{#order.purchaseName}} , 「{{#order.productName}}」, :{{#_ret}}",
prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")
public boolean createOrder(Order order) {
log.info("【 】orderNo={}", order.getOrderNo());
// db insert order
return true;
}
4.작업 의 상세 한 내용 이나 추가 정 보 를 기록 하 는 것 을 지원 합 니 다.한 작업 이 많은 필드 를 수정 하 였 으 나,success 로그 모드 에 서 는 너무 길 지 않도록 수정 정 보 를 모두 보 여 주지 못 합 니 다.이 럴 때 수정 정 보 를 detail 필드 에 저장 해 야 합 니 다.
detail 은 String 입 니 다.스스로 정렬 해 야 합 니 다.여기\#order.toString()은 Order 의 toString()방법 을 호출 했 습 니 다.
JSON 을 저장 하면 Order 의 toString()방법 을 직접 다시 쓰 면 된다.
@LogRecordAnnotation(
fail = " , :「{{#_errorMsg}}」",
category = "MANAGER_VIEW",
detail = "{{#order.toString()}}",
success = "{{#order.purchaseName}} , 「{{#order.productName}}」, :{{#_ret}}",
prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")
public boolean createOrder(Order order) {
log.info("【 】orderNo={}", order.getOrderNo());
// db insert order
return true;
}
5.로그 조작 자 를 어떻게 지정 합 니까?프레임 워 크 는 두 가지 방법 을 제공 했다.첫 번 째:LogRecord 의 주석 에 수 동 으로 지정 합 니 다.이런 필요 한 방법 은 매개 변수 에 operator 가 있다.
@LogRecordAnnotation(
fail = " , :「{{#_errorMsg}}」",
category = "MANAGER_VIEW",
detail = "{{#order.toString()}}",
operator = "{{#currentUser}}",
success = "{{#order.purchaseName}} , 「{{#order.productName}}」, :{{#_ret}}",
prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")
public boolean createOrder(Order order, String currentUser) {
log.info("【 】orderNo={}", order.getOrderNo());
// db insert order
return true;
}
이 방법 은 수 동 으로 지정 되 며,방법 적 매개 변수 에 operator 인자 가 있 거나,SpEL 을 통 해 정적 방법 으로 현재 사용 자 를 가 져 올 수 있 습 니 다.두 번 째:기본 구현 클래스 를 통 해 작업 자 를 자동 으로 가 져 옵 니 다.대부분의 웹 응용 프로그램 에서 현재 사용 자 는 하나의 스 레 드 컨 텍스트 에 저장 되 어 있 기 때문에 모든 주석 에 operator 를 추가 하여 작업 자 를 가 져 오 는 것 이 중복 되 어 있 기 때문에 확장 인 터 페 이 스 를 제공 하여 작업 자 를 가 져 옵 니 다.
프레임 워 크 는 확장 인 터 페 이 스 를 제공 합 니 다.프레임 워 크 를 사용 하 는 업 무 는 implements 라 는 인 터 페 이 스 를 사용 하여 현재 사용자 의 논 리 를 가 져 올 수 있 습 니 다.
Springboot 를 사용 하 는 것 은 IOperatorGetService 인 터 페 이 스 를 실현 한 다음 에 이 서 비 스 를 하나의 예 로 Spring 의 컨 텍스트 에 넣 어야 합 니 다.Spring Mvc 를 사용 하려 면 이 bean 들 을 직접 조립 해 야 합 니 다.
@Configuration
public class LogRecordConfiguration {
@Bean
public IOperatorGetService operatorGetService() {
return () -> Optional.of(OrgUserUtils.getCurrentUser())
.map(a -> new OperatorDO(a.getMisId()))
.orElseThrow(() -> new IllegalArgumentException("user is null"));
}
}
// :
@Service
public class DefaultOperatorGetServiceImpl implements IOperatorGetService {
@Override
public OperatorDO getUser() {
OperatorDO operatorDO = new OperatorDO();
operatorDO.setOperatorId("SYSTEM");
return operatorDO;
}
}
6.로그 문안 조정업데이트 등 방법 에 대해 방법의 매개 변 수 는 대부분 주문 ID 나 제품 ID 등 입 니 다.
예 를 들 어 다음 과 같은 예:로그 기록 의 success 내용 은"주문{\#orderId}을 업 데 이 트 했 습 니 다.업데이트 내용 은..."입 니 다.운영 이나 제품 에 있어 서 이해 하기 어렵 기 때문에 사용자 정의 함수 기능 을 도입 하 였 습 니 다.
사용 방법 은 원래 변수의 두 개의 큰 괄호 사이 에 함수 이름 을 추가 하 는 것 입 니 다.예 를 들 어"{ORDER{\#orderId}"그 중에서 ORDER 는 함수 이름 입 니 다.하나의 함수 이름 만 으로 는 부족 합 니 다.이 함수 의 정의 와 실현 을 추가 해 야 합 니 다.아래 의 예 를 볼 수 있다
사용자 정의 함 수 는 프레임 안의 IParse Function 인 터 페 이 스 를 실현 해 야 합 니 다.두 가지 방법 이 필요 합 니 다.
functionName()방법 은 주석 위의 함수 이름 을 되 돌려 줍 니 다.
apply()함수 인 자 는"{ORDER{\#orderId}}"에서 SpEL 이 해석 한\#orderId 의 값 입 니 다.여 기 는 숫자 1223110 입 니 다.다음은 실 현 된 클래스 에서 ID 를 읽 을 수 있 는 문자열 로 변환 하면 됩 니 다.
일반적으로 조사 문 제 를 편리 하 게 하기 위해 서 는 이름과 ID 를 모두 보 여 줘 야 한다.예 를 들 어'주문 이름(ID)'의 형식 이다.
여기에 문제 가 있 습 니 다.사용자 정의 함 수 를 추가 한 후에 프레임 워 크 를 어떻게 호출 할 수 있 습 니까?
답:Spring boot 애플 리 케 이 션 은 간단 합 니 다.Spring 의 컨 텍스트 에 만 노출 시 키 면 됩 니 다.Spring 의@Component 또는@Service 를 추가 하면 편리 합 니 다.😄。Spring mvc 응용 프로그램 은 스스로 Bean 을 조립 해 야 한다.
//
@LogRecordAnnotation(success = " {{#orderId}}, ....",
prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}",
detail = "{{#order.toString()}}")
public boolean update(Long orderId, Order order) {
return false;
}
// , {{#orderId}} functionName
@LogRecordAnnotation(success = " ORDER{#orderId}}, ...",
prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}",
detail = "{{#order.toString()}}")
public boolean update(Long orderId, Order order) {
return false;
}
//
@Component
public class OrderParseFunction implements IParseFunction {
@Resource
@Lazy // Lazy,
private OrderQueryService orderQueryService;
@Override
public String functionName() {
// ORDER
return "ORDER";
}
@Override
// value Order JSON ,
public String apply(String value) {
if(StringUtils.isEmpty(value)){
return value;
}
Order order = orderQueryService.queryOrder(Long.parseLong(value));
// , ID
return order.getProductName().concat("(").concat(value).concat(")");
}
}
7.로그 문안 조정 은 SpEL 세 가지 표현 식 을 사용 합 니 다.
@LogRecordAnnotation(prefix = LogRecordTypeConstant.CUSTOM_ATTRIBUTE, bizNo = "{{#businessLineId}}",
success = "{{#disable ? ' ' : ' '}} {ATTRIBUTE{#attributeId}}")
public CustomAttributeVO disableAttribute(Long businessLineId, Long attributeId, boolean disable) {
return xxx;
}
프레임 의 확장 점Operator GetServiceImpl 을 다시 쓰 고 컨 텍스트 를 통 해 사용자 의 확장 을 가 져 옵 니 다.예 는 다음 과 같 습 니 다.
@Service
public class DefaultOperatorGetServiceImpl implements IOperatorGetService {
@Override
public Operator getUser() {
return Optional.ofNullable(UserUtils.getUser())
.map(a -> new Operator(a.getName(), a.getLogin()))
.orElseThrow(()->new IllegalArgumentException("user is null"));
}
}
ILogRecordService 저장/조회 로그 의 예 를 들 어 사용 자 는 데이터 양 에 따라 데이터베이스/또는 ES 에 저장 할 수 있 습 니 다.스스로 저장 과 삭 제 를 하 시 면 됩 니 다.또한 조회 의 인터페이스 만 실현 할 수 있다.왜냐하면 업무 의 저장 에 저장 되 어 있 기 때문에 조회 업 무 는 스스로 실현 할 수 있 고 ILogRecordService 라 는 인 터 페 이 스 를 가지 않 는 다.왜냐하면 제품 매니저 는 기괴 한 조회 수 요 를 제기 할 수 있 기 때문이다.
@Service
public class DbLogRecordServiceImpl implements ILogRecordService {
@Resource
private LogRecordMapper logRecordMapper;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void record(LogRecord logRecord) {
log.info("【logRecord】log={}", logRecord);
LogRecordPO logRecordPO = LogRecordPO.toPo(logRecord);
logRecordMapper.insert(logRecordPO);
}
@Override
public List<LogRecord> queryLog(String bizKey, Collection<String> types) {
return Lists.newArrayList();
}
@Override
public PageDO<LogRecord> queryLogByBizNo(String bizNo, Collection<String> types, PageRequestDO pageRequestDO) {
return logRecordMapper.selectByBizNoAndCategory(bizNo, types, pageRequestDO);
}
}
IParseFunction 사용자 정의 변환 함수 인터페이스,IParseFunction 로그 레코드 주석 에 사용 할 함수 확장 실현예:
@Component
public class UserParseFunction implements IParseFunction {
private final Splitter splitter = Splitter.on(",").trimResults();
@Resource
@Lazy
private UserQueryService userQueryService;
@Override
public String functionName() {
return "USER";
}
@Override
// 11,12 11( ),12( )
public String apply(String value) {
if (StringUtils.isEmpty(value)) {
return value;
}
List<String> userIds = Lists.newArrayList(splitter.split(value));
List<User> misDOList = userQueryService.getUserList(userIds);
Map<String, User> userMap = StreamUtil.extractMap(misDOList, User::getId);
StringBuilder stringBuilder = new StringBuilder();
for (String userId : userIds) {
stringBuilder.append(userId);
if (userMap.get(userId) != null) {
stringBuilder.append("(").append(userMap.get(userId).getUsername()).append(")");
}
stringBuilder.append(",");
}
return stringBuilder.toString().replaceAll(",$", "");
}
}
변수 관련LogRecordAnnotation 에서 사용 할 수 있 는 변 수 는 인자 가 나 와 도 반환 값 을 사용 할 수 있 습 니 다\#ret 변수 및 이상 한 오류 정보\#errorMsg,SpEL 의 T 방식 으로 정적 방법 을 호출 할 수 있 습 니 다.
확장 을 기다리다
Log 의 Context 를 실현 하면 방법 매개 변수 에 없 는 변 수 를 해결 할 수 있 지만 사용 하고 싶 은 문 제 를 해결 할 수 있 습 니 다.초보적인 아 이 디 어 는 방법 에서 add 변수의 형식 으로 실현 할 수 있 고 곧 실현 할 수 있 습 니 다.😄
주의 점:
전체 로그 차단 은 방법 이 실 행 된 후에 기록 되 기 때문에 방법 내부 에서 방법 매개 변 수 를 수정 한 후에 LogRecordAnnotation 의 주석 에 있 는 SpEL 이 변수 에 대한 추출 값 은 수 정 된 값 입 니 다~
소스 코드
https://github.com/mouzt/mzt-biz-log
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.만약 잘못 이 있 거나 완전히 고려 하지 않 은 부분 이 있다 면 아낌없이 가르침 을 주시 기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.