You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何替换odata-server-core-4.9.0中移除的antlr包相关类?

Olingo 4.9.0 替换已移除的ANTLR URI解析类方案

背景说明

当前项目使用odata-server-core-4.0.0版本,该版本至4.6.0版本存在Maven漏洞,计划升级到最新的4.9.0版本。但4.9.0已移除org.apache.olingo.server.core.uri.antlr包,原代码依赖的UriLexer、UriParserParser及各类EOFContext无法直接使用,需进行替换。

核心替换思路

Olingo 4.7+版本将ANTLR相关的内部URI解析逻辑封装为对外的公共API,不再暴露底层ANTLR类。我们需要使用org.apache.olingo.server.core.uri.parser包下的工具类替代原有的直接调用ANTLR的代码,同时调整URI解析和访问的逻辑。

具体代码修改步骤

1. 移除旧的ANTLR相关导入

删除所有org.apache.olingo.server.core.uri.antlr包下的导入:

// 移除这些导入
import org.apache.olingo.server.core.uri.antlr.UriLexer;
import org.apache.olingo.server.core.uri.antlr.UriParserParser;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.BatchEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.CrossjoinEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.EntityEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterExpressionEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.MetadataEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.PathSegmentEOFContext;
import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectEOFContext;

2. 导入新的URI解析工具类

添加Olingo 4.9.0提供的官方解析工具:

import org.apache.olingo.server.core.uri.parser.UriParser;
import org.apache.olingo.server.core.uri.parser.UriParserException;
import org.apache.olingo.server.core.uri.parser.UriParserResult;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriInfoKind;

3. 重构URI解析逻辑

原代码中直接调用ANTLR解析规则的部分,替换为使用UriParser类完成解析,无需手动处理ANTLR的上下文对象。以下是修改后的完整代码示例:

UriContext context = new UriContext();
UriParseTreeVisitor uriParseTreeVisitor = new UriParseTreeVisitor(edm, context);

final RawUri uri = UriDecoder.decodeUri(path, query, fragment, 0); // 0 segments are before the service url

// 读取解码后的路径片段
final String firstSegment = uri.pathSegmentListDecoded.isEmpty() ? "" : uri.pathSegmentListDecoded.get(0);

if (firstSegment.isEmpty()) {
    ensureLastSegment(firstSegment, 0, uri.pathSegmentListDecoded.size());
    context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.service);
    
} else if (firstSegment.startsWith("$batch")) {
    ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
    try {
        // 使用UriParser解析$batch URI
        UriParserResult result = UriParser.parseBatchUri(uri.pathSegmentListDecoded.get(0), edm);
        uriParseTreeVisitor.visit(result.getTree());
    } catch (UriParserException e) {
        // 根据业务需求调整异常处理逻辑
        throw new RuntimeException("解析Batch URI失败", e);
    }

} else if (firstSegment.startsWith("$metadata")) {
    ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
    try {
        // 使用UriParser解析$metadata URI
        UriParserResult result = UriParser.parseMetadataUri(uri.pathSegmentListDecoded.get(0), edm);
        uriParseTreeVisitor.visit(result.getTree());
        context.contextUriInfo.setFragment(uri.fragment);
    } catch (UriParserException e) {
        throw new RuntimeException("解析Metadata URI失败", e);
    }

} else if (firstSegment.startsWith("$entity")) {
    context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.entityId);
    if (uri.pathSegmentListDecoded.size() > 1) {
        final String typeCastSegment = uri.pathSegmentListDecoded.get(1);
        ensureLastSegment(typeCastSegment, 2, uri.pathSegmentListDecoded.size());
        try {
            // 使用UriParser解析$entity URI
            UriParserResult result = UriParser.parseEntityIdUri(typeCastSegment, edm);
            uriParseTreeVisitor.visit(result.getTree());
        } catch (UriParserException e) {
            throw new RuntimeException("解析Entity URI失败", e);
        }
    }
    // Todo: 处理参数

} else if (firstSegment.startsWith("$all")) {
    ensureLastSegment(firstSegment, 1, uri.pathSegmentListDecoded.size());
    try {
        // 使用UriParser解析$all URI
        UriParserResult result = UriParser.parseAllUri(uri.pathSegmentListDecoded.get(0), edm);
        uriParseTreeVisitor.visit(result.getTree());
    } catch (UriParserException e) {
        throw new RuntimeException("解析All URI失败", e);
    }
    // Todo: 处理参数
}

4. 调整UriParseTreeVisitor(若需要)

如果原UriParseTreeVisitor是基于ANTLR的ParseTreeVisitor实现,需要调整为适配UriParserResult返回的语法树结构。可参考Olingo官方提供的标准访问者实现修改自定义访问者。

关键说明

  • Olingo 4.7+版本通过UriParser类封装了所有URI解析逻辑,对外暴露统一的解析方法,避免直接依赖底层ANTLR实现。
  • 所有原有的XXXEOFContext类都被封装到UriParserResult内部,无需手动类型转换,直接调用visit方法即可。
  • 新增的UriParserException用于处理解析过程中的异常,需根据业务场景添加异常处理逻辑。

内容的提问来源于stack exchange,提问作者prathyusha magam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 09:40:46