IF_REST_APPLICATION原理
IF_REST_APPLICATION实现路径匹配的核心原理是:你预先定义一套“路由规则”(即 URI 模板与后端 ABAP 处理类的绑定关系),当客户端请求到来时,SAP REST 框架中的“路由器”CL_REST_ROUTER会找出匹配度最高的那条规则,自动创建对应的处理类实例,然后由其处理该请求。
下面,我们来完整地拆解一下这个过程中的关键环节。
🚀 启动:从 ICF 到 REST 应用
整个流程始于 SAP 互联网通信框架 (ICF)。当客户端发送 HTTP 请求,例如http://<server>/sap/bc/rest_cars/Cars/47时,ICF 的请求会被你预先注册的 REST 处理类(通常继承自CL_REST_HTTP_HANDLER)捕获。
这个通用的处理类会接管后续流程,调用你需要实现的IF_REST_APPLICATION~GET_ROOT_HANDLER方法,来获取整个 REST 应用的根路由器对象。这一步标志着从 ICF 的 http 层正式切入了专门的 REST 处理框架。
🗺️ 定义:注册 URI 模板与后端类
接下来,你需要在一个继承自CL_REST_HTTP_HANDLER的子类中实现IF_REST_APPLICATION~GET_ROOT_HANDLER方法,在其中完成最核心的路径匹配规则定义:
METHOD if_rest_application~get_root_handler. DATA(lo_router) = NEW cl_rest_router( ). " 注册路径模板 '/Cars' 到后端类 'CL_REST_SAMPLE_CARS' lo_router->attach( iv_template = '/Cars' iv_handler_class = 'CL_REST_SAMPLE_CARS' ). " 注册带参数和正则表达式的模板 lo_router->attach( iv_template = '/Car/{ID:[1-9][0-9]*}' iv_handler_class = 'CL_REST_SAMPLE_CAR' ). ro_root_handler = lo_router. ENDMETHOD.上面这段代码的逻辑在于:
- 创建路由器:首先创建一个
CL_REST_ROUTER对象,它是整个路径匹配的执行中枢。 - 绑定:通过反复调用
ATTACH方法,将URI 模板(IV_TEMPLATE)和后端 ABAP 处理类名(IV_HANDLER_CLASS)紧密绑定起来。
🎯 匹配:路径如何找到后端类
CL_REST_ROUTER的工作就是根据请求的 URI 找到正确的处理器。SAP REST 库支持三种由简单到复杂的 URI 模板类型:
静态模板 (Static Templates):这是最直接的匹配方式。只有当请求的路径与模板字符串完全一致时才会被匹配。
- 代码示例:
lo_router->attach( iv_template = '/Cars' ... ) - 匹配路径:仅匹配
.../Cars
- 代码示例:
带属性的模板 (With URI Attribute):使用
{属性名}作为占位符,匹配该位置上的任意内容。- 代码示例:
lo_router->attach( iv_template = '/Cars_history/{MANUFACTURER}' ... ) - 匹配路径:可以匹配
.../Cars_history/ferrari,也可以匹配.../Cars_history/maserati。
- 代码示例:
带正则表达式的模板 (With URI Regular Expression Attribute):这是功能最强的模式,允许用ABAP 正则表达式来精确控制匹配范围和格式。
- 代码示例:
lo_router->attach( iv_template = '/Car/{ID:[1-9][0-9]*}' ... ) - 匹配路径:可以匹配
.../Car/1,也可以匹配.../Car/47,但由于正则[1-9][0-9]*的限制,.../Car/0将无法匹配。
- 代码示例:
处理路径冲突
为了避免冲突,CL_REST_ROUTER会使用一个高效的排序算法来决定最终使用哪个处理类。该算法会优先选择**“文字字符”**(不是用{}包裹的变量部分)最多的模板。
例如,对于一个请求cars/1/color:
- 模板A:
/cars/{ID}/color - 模板B:
/cars/{ID}/{TYRE}
匹配算法会计算每个模板的精确文字字符数:
- 模板A包含文字
/cars/、/color,共6个(c a r s /和c o l o r)。 - 模板B包含文字
/cars/,共1个。
计算得出模板A 胜出,因为它能更精确地描述这个请求。这确保了最相关的后端类会被优先调用。
💡 执行:实例化与处理
当CL_REST_ROUTER找到最佳匹配的模板后,框架会动态创建一个该后端处理类(iv_handler_class)的新实例。
- 请求分发:路由器会调用这个处理类实例的
HANDLE方法,并将 REST 请求对象IO_REQUEST和响应对象IO_RESPONSE作为参数传入。 - 资源处理:最后,后端处理类(如
CL_REST_RESOURCE的子类)中的对应方法(如GET,POST)被执行,生成响应内容。
📈 交互流程总结
整个流程可以概括为下图所示的交互流程:
最后,你可以在后端处理类(如CL_REST_SAMPLE_CAR)的内部,通过GET_URI_ATTRIBUTE('ID')这样的方法来提取 URL 路径中的{ID}参数值。