Apache Olingo - Read Scenario

1 项目准备

1.1 示例代码下载

从Apache Olingo官网下下载项目 Olingo Tutorial 'Basic-Read' Project.

1.2 Eclipse导入项目

将下载的代码导入Eclipse,在父项目pom文件中,<plugins>标签下添加如下标签

        <!-- 配置Tomcat插件 -->
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
        </plugin>

在web项目pom文件中<build>标签下添加如下标签

            <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <configuration>
                    <port>8080</port>
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>

选中父项目maven install后,run as -> maven build ...,配置Goals: clean tomcat7:run

2 项目分析

2.1 web.xml

web项目中,将匹配/MyODataSample.svc/*路径,在 <init-param>标签中指定ServiceFactory类。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"...>
    <display-name>org.apache.olingo.odata2.sample</display-name>
    <servlet>
        <servlet-name>MyODataSampleServlet</servlet-name>
        <servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>org.apache.olingo.odata2.core.rest.app.ODataApplication</param-value>
        </init-param>
        <init-param>
            <param-name>org.apache.olingo.odata2.service.factory</param-name>
            <param-value>org.apache.olingo.odata2.sample.service.MyServiceFactory</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyODataSampleServlet</servlet-name>
        <url-pattern>/MyODataSample.svc/*</url-pattern>
    </servlet-mapping>
</web-app>

2.2 实现ServiceFactory类

在service项目中实现ODataServiceFactory 接口,制定EdmProvider 与ODataSingleProcessor

public class MyServiceFactory extends ODataServiceFactory {

  @Override
  public ODataService createService(ODataContext ctx) throws ODataException {

EdmProvider edmProvider = new MyEdmProvider();
ODataSingleProcessor singleProcessor = new MyODataSingleProcessor();

return createODataSingleProcessorService(edmProvider, singleProcessor);
  }
}

2.3 实现Entity Data Model Provider

Model关系如图所示


启动项目,查看odata service

实现getSchema方法
设置metadata中相关的标签

public List<Schema> getSchemas() throws ODataException {
List<Schema> schemas = new ArrayList<Schema>();

Schema schema = new Schema();
schema.setNamespace(NAMESPACE);

List<EntityType> entityTypes = new ArrayList<EntityType>();
entityTypes.add(getEntityType(ENTITY_TYPE_1_1));
entityTypes.add(getEntityType(ENTITY_TYPE_1_2));
schema.setEntityTypes(entityTypes);

List<ComplexType> complexTypes = new ArrayList<ComplexType>();
complexTypes.add(getComplexType(COMPLEX_TYPE));
schema.setComplexTypes(complexTypes);

List<Association> associations = new ArrayList<Association>();
associations.add(getAssociation(ASSOCIATION_CAR_MANUFACTURER));
schema.setAssociations(associations);

List<EntityContainer> entityContainers = new ArrayList<EntityContainer>();
EntityContainer entityContainer = new EntityContainer();
entityContainer.setName(ENTITY_CONTAINER).setDefaultEntityContainer(true);

List<EntitySet> entitySets = new ArrayList<EntitySet>();
entitySets.add(getEntitySet(ENTITY_CONTAINER, ENTITY_SET_NAME_CARS));
entitySets.add(getEntitySet(ENTITY_CONTAINER, ENTITY_SET_NAME_MANUFACTURERS));
entityContainer.setEntitySets(entitySets);

List<AssociationSet> associationSets = new ArrayList<AssociationSet>();
associationSets.add(getAssociationSet(ENTITY_CONTAINER, ASSOCIATION_CAR_MANUFACTURER, ENTITY_SET_NAME_MANUFACTURERS, ROLE_1_2));
entityContainer.setAssociationSets(associationSets);

entityContainers.add(entityContainer);
schema.setEntityContainers(entityContainers);

schemas.add(schema);

return schemas;
}

实现getEntityType方法,设置EntityType中内容

@Override
  public EntityType getEntityType(FullQualifiedName edmFQName) throws ODataException {
if (NAMESPACE.equals(edmFQName.getNamespace())) {

  if (ENTITY_TYPE_1_1.getName().equals(edmFQName.getName())) {

    //Properties
    List<Property> properties = new ArrayList<Property>();
    properties.add(new SimpleProperty().setName("Id").setType(EdmSimpleTypeKind.Int32).setFacets(new Facets().setNullable(false)));
    properties.add(new SimpleProperty().setName("Model").setType(EdmSimpleTypeKind.String).setFacets(new Facets().setNullable(false).setMaxLength(100).setDefaultValue("Hugo"))
        .setCustomizableFeedMappings(new CustomizableFeedMappings().setFcTargetPath(EdmTargetPath.SYNDICATION_TITLE)));
    properties.add(new SimpleProperty().setName("ManufacturerId").setType(EdmSimpleTypeKind.Int32));
    properties.add(new SimpleProperty().setName("Price").setType(EdmSimpleTypeKind.Decimal));
    properties.add(new SimpleProperty().setName("Currency").setType(EdmSimpleTypeKind.String).setFacets(new Facets().setMaxLength(3)));
    properties.add(new SimpleProperty().setName("ModelYear").setType(EdmSimpleTypeKind.String).setFacets(new Facets().setMaxLength(4)));
    properties.add(new SimpleProperty().setName("Updated").setType(EdmSimpleTypeKind.DateTime)
        .setFacets(new Facets().setNullable(false).setConcurrencyMode(EdmConcurrencyMode.Fixed))
        .setCustomizableFeedMappings(new CustomizableFeedMappings().setFcTargetPath(EdmTargetPath.SYNDICATION_UPDATED)));
    properties.add(new SimpleProperty().setName("ImagePath").setType(EdmSimpleTypeKind.String));

    //Navigation Properties
    List<NavigationProperty> navigationProperties = new ArrayList<NavigationProperty>();
    navigationProperties.add(new NavigationProperty().setName("Manufacturer")
        .setRelationship(ASSOCIATION_CAR_MANUFACTURER).setFromRole(ROLE_1_1).setToRole(ROLE_1_2));

    //Key
    List<PropertyRef> keyProperties = new ArrayList<PropertyRef>();
    keyProperties.add(new PropertyRef().setName("Id"));
    Key key = new Key().setKeys(keyProperties);

    return new EntityType().setName(ENTITY_TYPE_1_1.getName())
        .setProperties(properties)
        .setKey(key)
        .setNavigationProperties(navigationProperties);

  } else if (ENTITY_TYPE_1_2.getName().equals(edmFQName.getName())) {

    //Properties
    List<Property> properties = new ArrayList<Property>();
    properties.add(new SimpleProperty().setName("Id").setType(EdmSimpleTypeKind.Int32).setFacets(new Facets().setNullable(false)));
    properties.add(new SimpleProperty().setName("Name").setType(EdmSimpleTypeKind.String).setFacets(new Facets().setNullable(false).setMaxLength(100))
        .setCustomizableFeedMappings(new CustomizableFeedMappings().setFcTargetPath(EdmTargetPath.SYNDICATION_TITLE)));
    properties.add(new ComplexProperty().setName("Address").setType(new FullQualifiedName(NAMESPACE, "Address")));
    properties.add(new SimpleProperty().setName("Updated").setType(EdmSimpleTypeKind.DateTime)
        .setFacets(new Facets().setNullable(false).setConcurrencyMode(EdmConcurrencyMode.Fixed))
        .setCustomizableFeedMappings(new CustomizableFeedMappings().setFcTargetPath(EdmTargetPath.SYNDICATION_UPDATED)));

    //Navigation Properties
    List<NavigationProperty> navigationProperties = new ArrayList<NavigationProperty>();
    navigationProperties.add(new NavigationProperty().setName("Cars")
        .setRelationship(ASSOCIATION_CAR_MANUFACTURER).setFromRole(ROLE_1_2).setToRole(ROLE_1_1));

    //Key
    List<PropertyRef> keyProperties = new ArrayList<PropertyRef>();
    keyProperties.add(new PropertyRef().setName("Id"));
    Key key = new Key().setKeys(keyProperties);

    return new EntityType().setName(ENTITY_TYPE_1_2.getName())
        .setProperties(properties)
        .setHasStream(true)
        .setKey(key)
        .setNavigationProperties(navigationProperties);
  }
}

return null;
}

实现其他方法设置其他标签中的内容。

2.4 实现OData Processor方法提供数据

通过private DataStore dataStore = new DataStore();建立数据源,
实现readEntitySet方法,由NavigationSegments判断读取单独entity还是关联的entity,

  @Override
  public ODataResponse readEntitySet(GetEntitySetUriInfo uriInfo, String contentType) throws ODataException {

    EdmEntitySet entitySet;

    if (uriInfo.getNavigationSegments().size() == 0) {
      entitySet = uriInfo.getStartEntitySet();

      if (ENTITY_SET_NAME_CARS.equals(entitySet.getName())) {
        return EntityProvider.writeFeed(contentType, entitySet, dataStore.getCars(), EntityProviderWriteProperties.serviceRoot(getContext().getPathInfo().getServiceRoot()).build());
      } else if (ENTITY_SET_NAME_MANUFACTURERS.equals(entitySet.getName())) {
        return EntityProvider.writeFeed(contentType, entitySet, dataStore.getManufacturers(), EntityProviderWriteProperties.serviceRoot(getContext().getPathInfo().getServiceRoot()).build());
      }

      throw new ODataNotFoundException(ODataNotFoundException.ENTITY);

    } else if (uriInfo.getNavigationSegments().size() == 1) {
      //navigation first level, simplified example for illustration purposes only
      entitySet = uriInfo.getTargetEntitySet();

      if (ENTITY_SET_NAME_CARS.equals(entitySet.getName())) {
        int manufacturerKey = getKeyValue(uriInfo.getKeyPredicates().get(0));

        List<Map<String, Object>> cars = new ArrayList<Map<String, Object>>();
        cars.addAll(dataStore.getCarsFor(manufacturerKey));

        return EntityProvider.writeFeed(contentType, entitySet, cars, EntityProviderWriteProperties.serviceRoot(getContext().getPathInfo().getServiceRoot()).build());
      }

      throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
    }

    throw new ODataNotImplementedException();
  }

2.5 建立DataStore

创建DataStore类实现getCar/createCar等方法。

public class DataStore {

 //Data accessors
 public Map<String, Object> getCar(int id) {
   Map<String, Object> data = null;

   Calendar updated = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
   
   switch (id) {
   case 1:
     updated.set(2012, 11, 11, 11, 11, 11);
     data = createCar(1, "F1 W03", 1, 189189.43, "EUR", "2012", updated, "file://imagePath/w03");
     break;

   case 2:
     updated.set(2013, 11, 11, 11, 11, 11);
     data = createCar(2, "F1 W04", 1, 199999.99, "EUR", "2013", updated, "file://imagePath/w04");
     break;

   case 3:
     updated.set(2012, 12, 12, 12, 12, 12);
     data = createCar(3, "F2012", 2, 137285.33, "EUR", "2012", updated, "http://pathToImage/f2012");
     break;

   case 4:
     updated.set(2013, 12, 12, 12, 12, 12);
     data = createCar(4, "F2013", 2, 145285.00, "EUR", "2013", updated, "http://pathToImage/f2013");
     break;

   case 5:
     updated.set(2011, 11, 11, 11, 11, 11);
     data = createCar(5, "F1 W02", 1, 167189.00, "EUR", "2011", updated, "file://imagePath/wXX");
     break;

   default:
     break;
   }
   
   return data;
 }

 
 private Map<String, Object> createCar(int carId, String model, int manufacturerId, double price, String currency, String modelYear, Calendar updated, String imagePath) {
   Map<String, Object> data = new HashMap<String, Object>();
   
   data.put("Id", carId);
   data.put("Model", model);
   data.put("ManufacturerId", manufacturerId);
   data.put("Price", price);
   data.put("Currency", currency);
   data.put("ModelYear", modelYear);
   data.put("Updated", updated);
   data.put("ImagePath", imagePath);
   
   return data;
 }
 
 public Map<String, Object> getManufacturer(int id) {
   Map<String, Object> data = null;
   Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
   
   switch (id) {
   case 1:
     Map<String, Object> addressStar = createAddress("Star Street 137", "Stuttgart", "70173", "Germany");
     date.set(1954, 7, 4);
     data = createManufacturer(1, "Star Powered Racing", addressStar, date);
     break;
     
   case 2:
     Map<String, Object> addressHorse = createAddress("Horse Street 1", "Maranello", "41053", "Italy");
     date.set(1929, 11, 16);
     data = createManufacturer(2, "Horse Powered Racing", addressHorse, date);
     break;
     
   default:
     break;
   }
   
   return data;
 }

 private Map<String, Object> createManufacturer(int id, String name, Map<String, Object> address, Calendar updated) {
   Map<String, Object> data = new HashMap<String, Object>();
   data.put("Id", id);
   data.put("Name", name);
   data.put("Address", address);
   data.put("Updated", updated);
   return data;
 }
 
 private Map<String, Object> createAddress(String street, String city, String zipCode, String country) {
   Map<String, Object> address = new HashMap<String, Object>();
   address.put("Street", street);
   address.put("City", city);
   address.put("ZipCode", zipCode);
   address.put("Country", country);
   return address;
 }


 public List<Map<String, Object>> getCars() {
   List<Map<String, Object>> cars = new ArrayList<Map<String, Object>>();
   cars.add(getCar(1));
   cars.add(getCar(2));
   cars.add(getCar(3));
   cars.add(getCar(4));
   cars.add(getCar(5));
   return cars;
 }
 
 public List<Map<String, Object>> getManufacturers() {
   List<Map<String, Object>> manufacturers = new ArrayList<Map<String, Object>>();
   manufacturers.add(getManufacturer(1));
   manufacturers.add(getManufacturer(2));
   return manufacturers;
 }


 public List<Map<String, Object>> getCarsFor(int manufacturerId) {
   List<Map<String, Object>> cars = getCars();
   List<Map<String, Object>> carsForManufacturer = new ArrayList<Map<String,Object>>();
   
   for (Map<String,Object> car: cars) {
     if(Integer.valueOf(manufacturerId).equals(car.get("ManufacturerId"))) {
       carsForManufacturer.add(car);
     }
   }
   
   return carsForManufacturer;
 }
 
 public Map<String, Object> getManufacturerFor(int carId) {
   Map<String, Object> car = getCar(carId);
   if(car != null) {
     Object manufacturerId = car.get("ManufacturerId");
     if(manufacturerId != null) {
       return getManufacturer((Integer) manufacturerId);
     }
   }
   return null;
 }
}

3 运行项目

通过如下路径访问相关数据

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,188评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,464评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,562评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,893评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,917评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,708评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,430评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,342评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,801评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,976评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,115评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,804评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,458评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,008评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,135评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,365评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,055评论 2 355

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,664评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,178评论 25 707
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,823评论 6 342
  • 首先非常感谢kevinz分享的文章《springboot+gradle+vue+webpack 组合使用》,这文章...
    YU_XI阅读 3,517评论 0 7
  • 今天平安夜,我姥姥死了,而我坐在宿舍里边看电视剧边写着作业,突然就收到了我爸的微信“今天你姥姥死了。”一切都来得很...
    舍善阅读 145评论 0 0