java 는 JEXL 을 이용 하여 동적 표현 식 컴 파일 을 실현 합 니 다.

배경
프로젝트 를 하 다가 갑자기 이런 수요 에 부 딪 혔 다.
시스템 은 여러 데이터 원본 의 데 이 터 를 가 져 와 처리 하고 마지막 으로 여러 필드 를 출력 해 야 합 니 다.필드 의 계산 규칙 은 일반적으로 간단 한 수치 에 가장 많은 조건 을 더 해 판단 한다.
그리고 동적 변동 이 필요 해!!예 를 들 어 한 필드 a 의 값 을 추출 합 니 다.a>10 시 에 10,a<=10 을 출력 하면 a 를 출력 합 니 다.이곳 의 10 은 하루 후에 8 로 바 뀔 수도 있 고 모레 12 로 바 뀔 수도 있다.물론 하나의 숫자의 변동 이 라면 우 리 는 데이터 베 이 스 를 이용 하여 저장 할 수 있다.그러나 만약 에 어느 날 수요 가 갑자기 a<10 시 출력 10,a>=10 시 출력 a 가 되면 코드 를 바 꾸 고 테스트 한 다음 에 발표 해 야 생산 환경 에서 사용 할 수 있 습 니 다.
한두 개의 이런 필드 는 아직 아무것도 아니다.만약 에 전체 시스템 이 의존 하 는 필드 에 이런 속성 이 있다 면 우 리 는 동태 적 인 로드 논 리 를 실현 하 는 방법 을 찾 아야 한다.
다음 에 소 개 된 JEXL 이 이런 문 제 를 해결 할 수 있 습 니 다.
JEXL(Java Expression Language)소개
JEXL C Apache Commons JEXL Overview
다음은 JEXL 의 사용법 을 실례 를 들 어 소개 하 겠 습 니 다.
실례
maven 의존:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-jexl</artifactId>
    <version>2.0</version>
</dependency>
정규 표현 식 일치
먼저 공공 방법 을 쓰 세 요.

public class Util {
    public static boolean regMatch(String regEx, String str) {
        Pattern pattern = Pattern.compile(regEx);
        return pattern.matcher(str).matches();
    }
}
다음은 JEXL 호출 방법 입 니 다.

public void RL() {
    JexlContext jc = new MapContext();
    String str = "          ";
    jc.set("Util", new Util());
    jc.set("str", str);
    jc.set("ans", "");
    String expression = "ans = Util.regMatch(\"[\u4e00-\u9fa5]{10,}\",str)";
    Expression e = new JexlEngine().createExpression(expression);
    e.evaluate(jc);
    System.out.println(jc.get("ans"));
}
코드 에 있 는 expression 변 수 는 동적 으로 컴 파일 할 수 있 는 표현 식 입 니 다.표현 식 에 나타 나 는 모든 변 수 는 JexlContext 에 미리 설정 해 야 합 니 다.그렇지 않 으 면 오류 가 발생 할 수 있 습 니 다.여기 에는 여러 가지 형식의 오류 가 있다.
① set"Util"이 없 으 면 프로그램 실행 중 이상 을 던 집 니 다.
org.apache.commons.jexl2.JexlException: TmpTest.RL@40![13,40]:'ans=QeUtil.regMatch('[1-]{10,}',str);'attempting to call method on null
② set"str"가 없 으 면 프로그램 이 이상 을 던 지지 않 고 null 을 출력 합 니 다.만약 당신 의 regMatch 방법 중 에 판정 처리 가 있다 면,판정 결 과 를 출력 할 것 입 니 다.빈 처리 가 없 으 면 콘 솔 에서 출력 은 다음 과 같 습 니 다.
경고:TmpTest.RL@39![36,39]:'ans=QeUtil.regMatch('[1-]{10,}',str);'undefined variable str
2 월 21,2017 4:00:41 오후 org.apache.comons.jexl2.JexlEngine invocationFailed
경고:TmpTest.RL@39![13,40]:'ans=QeUtil.regMatch('[1-]{10,}',str);'method invocation error
java.lang.NullPointerException
③ set"ans"가 없 으 면 프로그램 이 정상적으로 실행 되 고 정확 한 값 을 출력 합 니 다.
안전 을 위해 서 는 표현 식 에 나타 나 는 모든 변 수 를 JexlContext 에 미리 설정 해 야 합 니 다.
순환 하 다.
JEXL 은 두 가지 순환 방식 을 지원 합 니 다.

for(item : list) {
    x = x + item;
}
화해시키다

while (x lt 10) {
    x = x + 2;
}
다음은 while 를 사용 하 는 실례 입 니 다.

public void loop() {
    JexlContext jc = new MapContext();
    jc.set("a", 1);
    jc.set("b", "0");
    jc.set("ans", new StringBuffer());
    Expression e = new JexlEngine().createExpression("while (a < 10) {a = a + 1;ans.append(b);}");
    e.evaluate(jc);
    System.out.println(jc.get("ans"));
}
get\set 방법 호출
JEXL 은 대상 을 전송 하고 대상 을 호출 하 는 방법 을 지원 합 니 다.
아래 의 간단 한 get\set 방법의 인 스 턴 스:

public void getSet() {
    TmpTest tmpTest = new TmpTest();
    tmpTest.setA(1);
    JexlContext jc = new MapContext();
    jc.set("tmpTest", tmpTest);
    jc.set("ans", "");
    Expression e = new JexlEngine().createExpression("ans = tmpTest.getA()");
    e.evaluate(jc);
    System.out.println(jc.get("ans"));
    e = new JexlEngine().createExpression("ans = tmpTest.setA(2)");
    e.evaluate(jc);
    TmpTest tmpTest1 = (TmpTest) jc.get("tmpTest");
    System.out.println(tmpTest1.getA());
}
위의 사용 예 는 콘 솔 에서 1 을 먼저 출력 하고 2 를 출력 합 니 다.
다음은 다른 네티즌 들 의 댓 글 입 니 다.
ScriptEngine 은 이것 보다 n 배 편리 하고 js function 을 동적 으로 수행 할 수 있 습 니 다.알 아 보 세 요.

좋은 웹페이지 즐겨찾기