REST over Servlet

    当微服务部署到web容器中时,相对于独立运行,会涉及到web root以及servlet url pattern对url的改变。
    对于传统开发框架而言,需要consumer感知对方的完整url;比如web root为/mywebapp,url pattern为/rest,业务级path为/application,则consumer代码必须通过/mywebapp/rest/application来访问。
    这将导致一旦部署方式发生变化,比如从web容器变成standalone运行,则consumer或是producer必须修改代码来适配这个变化。

    建议使用ServiceComb的部署解耦特性,无论是consumer,还是producer,在代码中都不要感知web root以及url pattern,这样ServiceComb在运行时,会自动适配producer实例的web root以及url pattern。

    对于一些遗留系统改造,用户期望继续使用restTemplate.getForObject(“cse://serviceName/mywebapp/rest/application”…),这个时候,用户必须将接口定义的path定位为: /mywebapp/rest/application,例如:

    尽管如此,仍然推荐使用部署形态无关的方式来编码,可以减少后续由于部署形态变化,带来的修改代码问题。

    maven依赖

    1. <groupId>org.apache.servicecomb</groupId>
    2. <artifactId>transport-rest-servlet</artifactId>
    3. </dependency>

    与servlet机制配合,涉及到以下几个概念:

    • 启动spring context
      注意以下几种启动方式,是N选1的关系,不要同时使用。

      • 不使用springMVC的UI或RestController

        1. <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        2. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        3. version="3.0">
        4. <context-param>
        5. <param-name>contextConfigLocation</param-name>
        6. <param-value>classpath*:META-INF/spring/*.bean.xml</param-value>
        7. </context-param>
        8. <listener>
        9. <listener-class>org.apache.servicecomb.transport.rest.servlet.RestServletContextListener</listener-class>
        10. </listener>
        11. </web-app>
      • 使用springMVC的UI或RestController,且存在org.apache.servicecomb.transport.rest.servlet.CseDispatcherServlet

        1. <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        2. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        3. version="3.0">
        4. <servlet>
        5. <servlet-name>SpringMVCServlet</servlet-name>
        6. <servlet-class>org.apache.servicecomb.transport.rest.servlet.CseDispatcherServlet</servlet-class>
        7. <load-on-startup>1</load-on-startup>
        8. </servlet>
        9. <servlet-mapping>
        10. <servlet-name>SpringMVCServlet</servlet-name>
        11. <url-pattern>yourUrlPattern</url-pattern>
        12. </web-app>

        注意:
        该servlet不是ServiceComb的处理入口,仅仅是UI或RestController的处理入口

      • 使用springMVC的UI或RestController,且不存在org.apache.servicecomb.transport.rest.servlet.CseDispatcherServlet
        需要继承springMVC的DispatcherServlet,再按CseDispatcherServlet的方式,配置自己的实现类

    • ServiceComb servlet
      url pattern根据业务自身规划设置即可,下面的/rest/*仅仅是示例,不是固定值。
      url pattern必须以/*结尾
      以下两种声明方式也是多选一的关系,不要同时使用

      • 标准声明

        1. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        2. version="3.0">
        3. <servlet>
        4. <servlet-name>RestServlet</servlet-name>
        5. <servlet-class>org.apache.servicecomb.transport.rest.servlet.RestServlet</servlet-class>
        6. <load-on-startup>1</load-on-startup>
        7. <async-supported>true</async-supported>
        8. </servlet>
        9. <servlet-mapping>
        10. <servlet-name>RestServlet</servlet-name>
        11. <url-pattern>/rest/*</url-pattern>
        12. </servlet-mapping>
        13. </web-app>
      • 快捷声明

        在microservice.yaml文件中指定urlPattern,ServiceComb启动时会自动创建RestServlet,并设置相应的urlPattern:

        1. servicecomb.rest.servlet.urlPattern: /rest/*

    典型场景配置示例

      1. <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      2. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      3. version="3.0">
      4. <listener>
      5. <listener-class>org.apache.servicecomb.transport.rest.servlet.RestServletContextListener</listener-class>
      6. </listener>
      7. <servlet>
      8. <servlet-name>RestServlet</servlet-name>
      9. <servlet-class>org.apache.servicecomb.transport.rest.servlet.RestServlet</servlet-class>
      10. <load-on-startup>1</load-on-startup>
      11. <async-supported>true</async-supported>
      12. </servlet>
      13. <servlet-mapping>
      14. <servlet-name>RestServlet</servlet-name>
      15. </servlet-mapping>
    • 纯ServiceComb,快捷声明
      web.xml

      microservice.yaml:

      1. servicecomb.rest.servlet.urlPattern: /rest/*
    • springMVC UI或RestController接入请求,通过ServiceComb作为consumer发送到内部微服务
      web.xml:

      1. <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      2. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      3. version="3.0">
      4. <servlet>
      5. <servlet-name>SpringMVCServlet</servlet-name>
      6. <servlet-class>org.apache.servicecomb.transport.rest.servlet.CseDispatcherServlet</servlet-class>
      7. <load-on-startup>1</load-on-startup>
      8. </servlet>
      9. <servlet-mapping>
      10. <servlet-name>SpringMVCServlet</servlet-name>
      11. <url-pattern>yourUrlPattern</url-pattern>
      12. </servlet-mapping>
      13. </web-app>

      microservice.yaml:不配置servicecomb.rest.address以及servicecomb.rest.servlet.urlPattern

    • springMVC UI或RestController接入一些请求,同时通过ServiceComb接入另一些请求
      web.xml:

      1. <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      2. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      3. version="3.0">
      4. <servlet>
      5. <servlet-name>SpringMVCServlet</servlet-name>
      6. <servlet-class>org.apache.servicecomb.transport.rest.servlet.CseDispatcherServlet</servlet-class>
      7. <load-on-startup>1</load-on-startup>
      8. </servlet>
      9. <servlet-mapping>
      10. <servlet-name>SpringMVCServlet</servlet-name>
      11. <url-pattern>yourUrlPattern</url-pattern>
      12. </servlet-mapping>
      13. </web-app>

      microservice.yaml:

    RestServlet工作于异步模式,根据servlet 3.0的标准,整条工作链都必须是异步模式,所以,如果业务在这个流程上增加了servlet filter,也必须将它配置为异步:

    1. <filter>
    2. ......
    3. <async-supported>true</async-supported>

    配置项

    表1-1 REST over Servlet配置项说明