如何替换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
相关产品推荐
相关产品推荐

