51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Spring Boot集成olingo快速入门demo

1.什么是olingo?

Apache Olingo 是个 Java 库,用来实现 Open Data Protocol (OData)。 Apache Olingo 包括服务客户端和 OData 服务器方面。

Open Data Protocol (开放数据协议,OData)

是用来查询和更新数据的一种Web协议,其提供了把存在于应用程序中的数据暴露出来的方式。OData运用且构建于很多 Web技术之上,比如HTTP、Atom Publishing Protocol(AtomPub)和JSON,提供了从各种应用程序、服务和存储库中访问信息的能力。OData被用来从各种数据源中暴露和访问信息, 这些数据源包括但不限于:关系数据库、文件系统、内容管理系统和传统Web站点。

2.代码工程

实验目标

利用olingo实现oData协议

pom.xml

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <parent>        <artifactId>springboot-demo</artifactId>        <groupId>com.et</groupId>        <version>1.0-SNAPSHOT</version>    </parent>    <modelVersion>4.0.0</modelVersion>
    <artifactId>olingo</artifactId>
    <properties>        <maven.compiler.source>8</maven.compiler.source>        <maven.compiler.target>8</maven.compiler.target>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>
        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-autoconfigure</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-jpa</artifactId>        </dependency>        <dependency>            <groupId>org.apache.olingo</groupId>            <artifactId>olingo-odata2-core</artifactId>            <version>2.0.11</version>            <exclusions>                <exclusion>                    <groupId>javax.ws.rs</groupId>                    <artifactId>javax.ws.rs-api</artifactId>                </exclusion>            </exclusions>        </dependency>        <dependency>            <groupId>org.apache.olingo</groupId>            <artifactId>olingo-odata2-jpa-processor-core</artifactId>            <version>2.0.11</version>        </dependency>        <dependency>            <groupId>org.apache.olingo</groupId>            <artifactId>olingo-odata2-jpa-processor-ref</artifactId>            <version>2.0.11</version>            <exclusions>                <exclusion>                    <groupId>org.eclipse.persistence</groupId>                    <artifactId>eclipselink</artifactId>                </exclusion>            </exclusions>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-jersey</artifactId>        </dependency>

    </dependencies>    <profiles>        <profile>            <id>local</id>            <activation>                <activeByDefault>true</activeByDefault>            </activation>            <properties>                <activatedProperties>local</activatedProperties>            </properties>            <dependencies>                <dependency>                    <groupId>com.h2database</groupId>                    <artifactId>h2</artifactId>                    <scope>runtime</scope>                </dependency>            </dependencies>        </profile>
        <profile>            <id>cloud</id>            <activation>                <activeByDefault>false</activeByDefault>            </activation>            <properties>                <activatedProperties>cloud</activatedProperties>            </properties>        </profile>    </profiles>
    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build></project>

config

package com.et.olingo.config;
import com.et.olingo.service.OdataJpaServiceFactory;import org.apache.olingo.odata2.api.ODataServiceFactory;import org.apache.olingo.odata2.core.rest.ODataRootLocator;import org.apache.olingo.odata2.core.rest.app.ODataApplication;import org.glassfish.jersey.server.ResourceConfig;import org.springframework.stereotype.Component;
import javax.inject.Inject;import javax.persistence.EntityManager;import javax.persistence.EntityManagerFactory;import javax.persistence.EntityTransaction;import javax.servlet.http.HttpServletRequest;import javax.ws.rs.ApplicationPath;import javax.ws.rs.Path;import javax.ws.rs.container.ContainerRequestContext;import javax.ws.rs.container.ContainerRequestFilter;import javax.ws.rs.container.ContainerResponseContext;import javax.ws.rs.container.ContainerResponseFilter;import javax.ws.rs.core.Context;import javax.ws.rs.ext.Provider;import java.io.IOException;
@Component@ApplicationPath("/odata")public class JerseyConfig extends ResourceConfig {
    public JerseyConfig(OdataJpaServiceFactory serviceFactory, EntityManagerFactory entityManagerFactory) {        ODataApplication oDataApplication = new ODataApplication();        oDataApplication                .getClasses()                .forEach( c -> {                    if ( !ODataRootLocator.class.isAssignableFrom(c)) {                        register(c);                    }                });        register(new ODataServiceRootLocator(serviceFactory));        register(new EntityManagerFilter(entityManagerFactory));    }
    @Path("/")    public static class ODataServiceRootLocator extends ODataRootLocator {
        private OdataJpaServiceFactory serviceFactory;
        @Inject        public ODataServiceRootLocator (OdataJpaServiceFactory serviceFactory) {            this.serviceFactory = serviceFactory;        }
        @Override        public ODataServiceFactory getServiceFactory() {            return this.serviceFactory;        }    }
    @Provider    public static class EntityManagerFilter implements ContainerRequestFilter,            ContainerResponseFilter {        public static final String EM_REQUEST_ATTRIBUTE =                EntityManagerFilter.class.getName() + "_ENTITY_MANAGER";        private final EntityManagerFactory entityManagerFactory;
        @Context        private HttpServletRequest httpRequest;        public EntityManagerFilter(EntityManagerFactory entityManagerFactory) {            this.entityManagerFactory = entityManagerFactory;        }
        @Override        public void filter(ContainerRequestContext containerRequestContext) throws IOException {            EntityManager entityManager = this.entityManagerFactory.createEntityManager();            httpRequest.setAttribute(EM_REQUEST_ATTRIBUTE, entityManager);            if (!"GET".equalsIgnoreCase(containerRequestContext.getMethod())) {                entityManager.getTransaction().begin();            }        }        @Override        public void filter(ContainerRequestContext requestContext,                           ContainerResponseContext responseContext) throws IOException {            EntityManager entityManager = (EntityManager) httpRequest.getAttribute(EM_REQUEST_ATTRIBUTE);            if (!"GET".equalsIgnoreCase(requestContext.getMethod())) {                EntityTransaction entityTransaction = entityManager.getTransaction(); //we do not commit because it's just a READ                if (entityTransaction.isActive() && !entityTransaction.getRollbackOnly()) {                    entityTransaction.commit();                }            }            entityManager.close();        }    }
}

controller

package com.et.olingo.controller;
import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;import java.util.Map;
@RestControllerpublic class HelloWorldController {    @RequestMapping("/hello")    public Map<String, Object> showHelloWorld(){        Map<String, Object> map = new HashMap<>();        map.put("msg", "HelloWorld");        return map;    }}

entity

service * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

package com.et.olingo.service;
import com.et.olingo.entity.Child;import org.apache.olingo.odata2.api.edm.EdmException;import org.apache.olingo.odata2.api.ep.EntityProviderException;import org.apache.olingo.odata2.api.exception.ODataException;import org.apache.olingo.odata2.api.exception.ODataNotFoundException;import org.apache.olingo.odata2.api.processor.ODataResponse;import org.apache.olingo.odata2.api.uri.info.*;import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;import org.apache.olingo.odata2.jpa.processor.api.ODataJPADefaultProcessor;import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import java.io.InputStream;import java.util.List;
public class CustomODataJpaProcessor extends ODataJPADefaultProcessor {
    private Logger logger = LoggerFactory.getLogger(getClass());
    public CustomODataJpaProcessor(ODataJPAContext oDataJPAContext) {        super(oDataJPAContext);    }
    @Override    public ODataResponse readEntitySet(final GetEntitySetUriInfo uriParserResultView, final String contentType) throws ODataJPAModelException, ODataJPARuntimeException, EdmException {        logger.info("READ: Entity Set {} called", uriParserResultView.getTargetEntitySet().getName());        try {            List<Object> jpaEntities = jpaProcessor.process(uriParserResultView);            return responseBuilder.build(uriParserResultView, jpaEntities, contentType);        } finally {            this.close();        }    }
    @Override    public ODataResponse readEntity(final GetEntityUriInfo uriParserResultView, final String contentType) throws ODataJPAModelException, ODataJPARuntimeException, ODataNotFoundException, EdmException {        ODataResponse response = null;        if (uriParserResultView.getKeyPredicates().size() > 1) {            logger.info("READ: Entity {} called with key {} and key {}", uriParserResultView.getTargetEntitySet().getName(), uriParserResultView.getKeyPredicates().get(0).getLiteral(), uriParserResultView.getKeyPredicates().get(1).getLiteral());        } else {            logger.info("READ: Entity {} called with key {}", uriParserResultView.getTargetEntitySet().getName(), uriParserResultView.getKeyPredicates().get(0).getLiteral());        }        try {            Object readEntity = jpaProcessor.process(uriParserResultView);            response = responseBuilder.build(uriParserResultView, readEntity, contentType);        } finally {            this.close();        }        return response;    }
    @Override    public ODataResponse createEntity(final PostUriInfo uriParserResultView, final InputStream content, final String requestContentType, final String contentType) throws ODataJPAModelException, ODataJPARuntimeException, ODataNotFoundException, EdmException, EntityProviderException {        logger.info("POST: Entity {} called", uriParserResultView.getTargetEntitySet().getName());        ODataResponse response = null;        try {            Object createdEntity = jpaProcessor.process(uriParserResultView, content, requestContentType);            if (createdEntity.getClass().equals(Child.class)) {                response = postProcessCreateChild(createdEntity, uriParserResultView, contentType);            } else {                response = responseBuilder.build(uriParserResultView, createdEntity, contentType);            }        } finally {            this.close();        }        return response;    }

    @Override    public ODataResponse updateEntity(final PutMergePatchUriInfo uriParserResultView, final InputStream content,                                      final String requestContentType, final boolean merge, final String contentType) throws ODataException, ODataJPAModelException, ODataJPARuntimeException, ODataNotFoundException {        logger.info("PUT: Entity {} called with key {}", uriParserResultView.getTargetEntitySet().getName(), uriParserResultView.getKeyPredicates().get(0).getLiteral());        ODataResponse response = null;        try {            Object updatedEntity = jpaProcessor.process(uriParserResultView, content, requestContentType);            response = responseBuilder.build(uriParserResultView, updatedEntity);        } finally {            this.close();        }        return response;    }
    @Override    public ODataResponse deleteEntity(DeleteUriInfo uriParserResultView, String contentType) throws ODataException {        logger.info("DELETE: Entity {} called with key {}", uriParserResultView.getTargetEntitySet().getName(), uriParserResultView.getKeyPredicates().get(0).getLiteral());        ODataResponse oDataResponse = null;        try {            this.oDataJPAContext.setODataContext(this.getContext());            Object deletedEntity = this.jpaProcessor.process(uriParserResultView, contentType);            oDataResponse = this.responseBuilder.build(uriParserResultView, deletedEntity);        } finally {            this.close();        }        return oDataResponse;    }
    private ODataResponse postProcessCreateChild(Object createdEntity, PostUriInfo uriParserResultView, String contentType) throws ODataJPARuntimeException, ODataNotFoundException {        Child child = (Child) createdEntity;        if (child.getSurname() == null || child.getSurname().equalsIgnoreCase("")) {            if (child.getMother().getSurname() != null && !child.getMother().getSurname().equalsIgnoreCase("")) {                child.setSurname(child.getMother().getSurname());            } else if (child.getMother().getSurname() != null && !child.getFather().getSurname().equalsIgnoreCase("")) {                child.setSurname(child.getFather().getSurname());            } else {                child.setSurname("Gashi");            }        }        return responseBuilder.build(uriParserResultView, createdEntity, contentType);    }
}
package com.et.olingo.service;
import com.et.olingo.config.JerseyConfig;import org.apache.olingo.odata2.api.ODataService;import org.apache.olingo.odata2.api.ODataServiceFactory;import org.apache.olingo.odata2.api.edm.provider.EdmProvider;import org.apache.olingo.odata2.api.exception.ODataException;import org.apache.olingo.odata2.api.processor.ODataContext;import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;import org.apache.olingo.odata2.jpa.processor.api.factory.ODataJPAAccessFactory;import org.apache.olingo.odata2.jpa.processor.api.factory.ODataJPAFactory;
import javax.persistence.EntityManager;import javax.servlet.http.HttpServletRequest;
public class CustomODataServiceFactory extends ODataServiceFactory {
    private ODataJPAContext oDataJPAContext;    private ODataContext oDataContext;
    @Override    public final ODataService createService(final ODataContext context) throws ODataException {        oDataContext = context;        oDataJPAContext = initializeODataJPAContext();
        validatePreConditions();
        ODataJPAFactory factory = ODataJPAFactory.createFactory();        ODataJPAAccessFactory accessFactory = factory.getODataJPAAccessFactory();
        if (oDataJPAContext.getODataContext() == null) {            oDataJPAContext.setODataContext(context);        }
        ODataSingleProcessor oDataSingleProcessor = new CustomODataJpaProcessor(                oDataJPAContext        );

        EdmProvider edmProvider = accessFactory.createJPAEdmProvider(oDataJPAContext);        return createODataSingleProcessorService(edmProvider, oDataSingleProcessor);
    }
    private void validatePreConditions() throws ODataJPARuntimeException {        if (oDataJPAContext.getEntityManager() == null) {            throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.ENTITY_MANAGER_NOT_INITIALIZED, null);        }    }
    public final ODataJPAContext getODataJPAContext()            throws ODataJPARuntimeException {        if (oDataJPAContext == null) {            oDataJPAContext = ODataJPAFactory.createFactory()                    .getODataJPAAccessFactory().createODataJPAContext();        }        if (oDataContext != null)            oDataJPAContext.setODataContext(oDataContext);        return oDataJPAContext;
    }
    protected ODataJPAContext initializeODataJPAContext() throws ODataJPARuntimeException {        ODataJPAContext oDataJPAContext = this.getODataJPAContext();        ODataContext oDataContext = oDataJPAContext.getODataContext();

        HttpServletRequest request = (HttpServletRequest) oDataContext.getParameter(                ODataContext.HTTP_SERVLET_REQUEST_OBJECT);        EntityManager entityManager = (EntityManager) request                .getAttribute(JerseyConfig.EntityManagerFilter.EM_REQUEST_ATTRIBUTE);        oDataJPAContext.setEntityManager(entityManager);

        oDataJPAContext.setPersistenceUnitName("default");        oDataJPAContext.setContainerManaged(true);        return oDataJPAContext;    }}
package com.et.olingo.service;
import org.springframework.stereotype.Component;
@Componentpublic class OdataJpaServiceFactory extends CustomODataServiceFactory {    //need this wrapper class for the spring framework, otherwise we face issues when auto wiring directly the CustomODataServiceFactory}

application.yaml

spring.h2.console.enabled=truespring.h2.console.path=/console

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • https://github.com/Harries/springboot-demo

3.测试

启动spring Boot应用

元数据查看

http://localhost:8080/odata/$metadata

插入

查询

4.引用

  • https://github.com/ECasio/olingo-spring-example

  • https://olingo.apache.org/

  • http://www.liuhaihua.cn/archives/710825.html

赞(5)
未经允许不得转载:工具盒子 » Spring Boot集成olingo快速入门demo