oidc_使用Java EE和OIDC构建Java REST API

oidc

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。

Java EE允许您使用JAX-RS和JPA快速轻松地构建Java REST API。 Java EE是保护伞标准规范,它描述了许多Java技术,包括EJB,JPA,JAX-RS和许多其他技术。 它最初旨在允许Java应用程序服务器之间的可移植性,并在2000年代初期蓬勃发展。 那时,应用程序服务器风行一时,并由许多知名公司(例如IBM,BEA和Sun)提供。 JBoss是一家新兴公司,它破坏了现状,并表明有可能将Java EE应用服务器开发为一个开源项目,并免费提供它。 JBoss在2006年被RedHat收购。

在2000年代初期,Java开发人员使用servlet和EJB来开发其服务器应用程序。 Hibernate和Spring分别于2002年和2004年问世。 两种技术都对各地的Java开发人员产生了巨大的影响,表明他们可以编写没有EJB的分布式,健壮的应用程序。 Hibernate的POJO模型最终被用作JPA标准,并且对EJB的影响也很大。

快进到2018年,Java EE肯定不像以前那样! 现在,它主要是POJO和注释,并且使用起来更简单。

为什么要使用Java EE而不是Spring Boot构建Java REST API?

Spring Boot是Java生态系统中我最喜欢的技术之一。 它极大地减少了Spring应用程序中必需的配置,并使得仅用几行代码即可生成REST API。 但是,最近有一些不使用Spring Boot的开发人员提出了许多API安全性问题。 其中一些甚至没有使用Spring!

出于这个原因,我认为构建一个Java REST API(使用Java EE)很有趣,该API与我过去开发的Spring Boot REST API相同。 即,我的Bootiful AngularBootiful React帖子中的“啤酒” API。

使用Java EE构建Java REST API

首先,我在Twitter上询问了我的网络,是否存在诸如start.spring.io之类的Java EE快速入门。 我收到了一些建议,并开始进行一些研究。 David Blevins建议我看一下tomee-jaxrs-starter-project ,所以我从那里开始。 我还研究了Roberto Cortez推荐的TomEE Maven原型

我喜欢jaxrs-starter项目,因为它展示了如何使用JAX-RS创建REST API。 TomEE Maven原型也很有用,特别是因为它展示了如何使用JPA,H2和JSF。 我将两者结合在一起,创建了自己的最小启动器,可用于在TomEE上实现安全的Java EE API。 您不必在这些示例中使用TomEE,但是我尚未在其他实现上对其进行测试。

如果您在其他应用服务器上使用了这些示例,请告诉我,我将更新此博客文章。

在这些示例中,我将使用Java 8和Java EE 7.0以及TomEE 7.1.0。 TomEE 7.x是EE 7兼容版本; 有一个TomEE 8.x分支用于EE8兼容性工作,但尚无发行版本。 我希望您也安装了Apache Maven

首先,将我们的Java EE REST API存储库克隆到您的硬盘驱动器,然后运行它:

git clone https://github.com/oktadeveloper/okta-java-ee-rest-api-example.git javaee-rest-api
cd javaee-rest-api
mvn package tomee:run

导航到http:// localhost:8080并添加新啤酒。

Java REST API

单击添加 ,您应该看到成功消息。

Java REST API

单击查看存在的啤酒查看啤酒的完整列表。

Java REST API
您还可以在http://localhost:8080/good-beers查看系统中的优质啤酒列表。 以下是使用HTTPie时的输出。

$ http :8080/good-beers
HTTP/1.1 200
Content-Type: application/json
Date: Wed, 29 Aug 2018 21:58:23 GMT
Server: Apache TomEE
Transfer-Encoding: chunked
[
    {
        "id": 101,
        "name": "Kentucky Brunch Brand Stout"
    },
    {
        "id": 102,
        "name": "Marshmallow Handjee"
    },
    {
        "id": 103,
        "name": "Barrel-Aged Abraxas"
    },
    {
        "id": 104,
        "name": "Heady Topper"
    },
    {
        "id": 108,
        "name": "White Rascal"
    }
]

使用Java EE构建REST API

我向您展示了该应用程序可以做什么,但是我还没有谈论它是如何构建的。 它有一些XML配置文件,但是我将跳过其中的大多数。 目录结构如下所示:

$ tree .
.
├── LICENSE
├── README.md
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── okta
    │   │           └── developer
    │   │               ├── Beer.java
    │   │               ├── BeerBean.java
    │   │               ├── BeerResource.java
    │   │               ├── BeerService.java
    │   │               └── StartupBean.java
    │   ├── resources
    │   │   └── META-INF
    │   │       └── persistence.xml
    │   └── webapp
    │       ├── WEB-INF
    │       │   ├── beans.xml
    │       │   └── faces-config.xml
    │       ├── beer.xhtml
    │       ├── index.jsp
    │       └── result.xhtml
    └── test
        └── resources
            └── arquillian.xml

12 directories, 16 files

最重要的XML文件是pom.xml ,它定义了依赖关系,并允许您运行TomEE Maven插件。 它很短很甜,只有一个依赖项和一个插件。

<?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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.okta.developer</groupId>
    <artifactId>java-ee-rest-api</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>Java EE Webapp with JAX-RS API</name>
    <url>http://developer.okta.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <failOnMissingWebXml>false</failOnMissingWebXml>
        <javaee-api.version>7.0</javaee-api.version>
        <tomee.version>7.1.0</tomee.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>${javaee-api.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomee.maven</groupId>
                <artifactId>tomee-maven-plugin</artifactId>
                <version>${tomee.version}</version>
                <configuration>
                    <context>ROOT</context>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

主要实体是Beer.java

package com.okta.developer;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Beer {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String name;

    public Beer() {}

    public Beer(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String beerName) {
        this.name = beerName;
    }

    @Override
    public String toString() {
        return "Beer{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

数据库(又名数据源)在src/main/resources/META-INF/persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="beer-pu" transaction-type="JTA">
        <jta-data-source>beerDatabase</jta-data-source>
        <class>com.okta.developer.Beer</class>
        <properties>
            <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
        </properties>
    </persistence-unit>
</persistence>

BeerService.java类使用JPA的EntityManager处理该实体的读取并将其保存到数据库。

package com.okta.developer;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import java.util.List;

@Stateless
public class BeerService {

    @PersistenceContext(unitName = "beer-pu")
    private EntityManager entityManager;

    public void addBeer(Beer beer) {
        entityManager.persist(beer);
    }

    public List<Beer> getAllBeers() {
        CriteriaQuery<Beer> cq = entityManager.getCriteriaBuilder().createQuery(Beer.class);
        cq.select(cq.from(Beer.class));
        return entityManager.createQuery(cq).getResultList();
    }

    public void clear() {
        Query removeAll = entityManager.createQuery("delete from Beer");
        removeAll.executeUpdate();
    }
}

有一个StartupBean.java ,用于在启动时填充数据库,并在关闭时清除数据库。

package com.okta.developer;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
import java.util.stream.Stream;

@Singleton
@Startup
public class StartupBean {
    private final BeerService beerService;

    @Inject
    public StartupBean(BeerService beerService) {
        this.beerService = beerService;
    }

    @PostConstruct
    private void startup() {
        // Top beers from https://www.beeradvocate.com/lists/top/
        Stream.of("Kentucky Brunch Brand Stout", "Marshmallow Handjee", 
                "Barrel-Aged Abraxas", "Heady Topper",
                "Budweiser", "Coors Light", "PBR").forEach(name ->
                beerService.addBeer(new Beer(name))
        );
        beerService.getAllBeers().forEach(System.out::println);
    }

    @PreDestroy
    private void shutdown() {
        beerService.clear();
    }
}

这三个类构成了应用程序的基础,还有一个BeerResource.java类,它使用JAX-RS公开/good-beers端点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值