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

在过去的几年中,React受到了很多积极的报导,使其成为Java开发人员的吸引人的前端选择! 一旦了解了它的工作原理,它就会变得很有意义,并且可以很有趣地进行开发。 不仅如此,而且速度也很快! 如果您一直在关注我,或者已经阅读了此博客,那么您可能还记得我的《 使用Spring Boot和Angular进行Bootiful开发》教程。 今天,我将向您展示如何构建相同的应用程序,除了这次使用React。 在深入探讨之前,让我们先讨论一下React有什么用处,以及我为什么选择在本文中探索它。

首先,React不是一个成熟的Web框架。 它更像是用于开发UI的工具包,如la GWT。 如果您想发出HTTP请求以从服务器获取数据,React将不提供任何实用程序。 但是,它确实有一个庞大的生态系统,提供许多库和组件。 我所说的巨大意味着什么? 这么说:根据npmjs.com , Angular有17,938个软件包 。 反应几乎三倍多在42428!

Angular是我的好朋友,已经有很长时间了。 我并没有放弃我的老朋友采用React。 我只是结交新朋友。 拥有很多具有不同背景和不同见解的朋友,对于人类的观点来说是件好事!

这篇文章展示了如何将UI和API构建为单独的应用程序。 您将学习如何使用Spring MVC创建REST端点,如何配置Spring Boot以允许CORS,以及如何创建一个React应用来显示其数据。 该应用程序将显示API中的啤酒列表,然后从GIPHY提取与啤酒名称匹配的GIF。 我还将向您展示如何集成Okta及其OpenID Connect(OIDC)支持以锁定API并向UI添加身份验证。

让我们开始吧!

使用Spring Boot构建API

注意:以下有关构建Spring Boot API的说明与使用Spring Boot和Angular进行Bootiful开发中的说明相同。 为了方便起见,我在下面将它们复制了下来。

要开始使用Spring Boot,请导航到start.spring.io 。 在“搜索依赖项”字段中,选择以下内容:

  • H2 :内存数据库
  • JPA :Java的标准ORM
  • 其余存储库 :允许您将JPA存储库公开为REST端点
  • Web :具有Jackson(用于JSON),Hibernate Validator和嵌入式Tomcat的Spring MVC

如果你喜欢命令行更好,你可以使用下面的命令来下载一个demo.zip与文件HTTPie 。

http https://start.spring.io/starter.zip \
dependencies==h2,data-jpa,data-rest,web -d

创建一个名为spring-boot-react-example目录,其中包含server目录。 将demo.zip的内容demo.zipserver目录中。

在您喜欢的IDE中打开“服务器”项目,然后运行DemoApplication或使用./mvnw spring-boot:run从命令行启动它。

在其中创建com.example.demo.beer程序包和Beer.java文件。 此类将是保存您的数据的实体。

package com.example.demo.beer;import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;@Entity
public class Beer {@Id@GeneratedValueprivate Long id;private String name;public Beer() {}public Beer(String name) {this.name = name;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Beer{" +"id=" + id +", name='" + name + '\'' +'}';}
}

添加一个利用Spring Data在此实体上执行CRUD的BeerRepository类。

package com.example.demo.beer;import org.springframework.data.jpa.repository.JpaRepository;interface BeerRepository extends JpaRepository<Beer, Long> {
}

添加使用此存储库的BeerCommandLineRunner并创建一组默认数据。

package com.example.demo.beer;import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;import java.util.stream.Stream;@Component
public class BeerCommandLineRunner implements CommandLineRunner {private final BeerRepository repository;public BeerCommandLineRunner(BeerRepository repository) {this.repository = repository;}@Overridepublic void run(String... strings) throws Exception {// Top beers from https://www.beeradvocate.com/lists/top/Stream.of("Kentucky Brunch Brand Stout", "Good Morning", "Very Hazy", "King Julius","Budweiser", "Coors Light", "PBR").forEach(name ->repository.save(new Beer(name)));repository.findAll().forEach(System.out::println);}
}

重建您的项目,您应该会在终端上看到印刷的啤酒清单。

a添加@RepositoryRestResource注释BeerRepository揭露其所有CRUD操作的REST端点。

import org.springframework.data.rest.core.annotation.RepositoryRestResource;@RepositoryRestResource
interface BeerRepository extends JpaRepository<Beer, Long> {
}

添加一个BeerController类来创建一个端点,该端点过滤出的啤酒数量少于大啤酒。

package com.example.demo.beer;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;@RestController
public class BeerController {private BeerRepository repository;public BeerController(BeerRepository repository) {this.repository = repository;}@GetMapping("/good-beers")public Collection<Beer> goodBeers() {return repository.findAll().stream().filter(this::isGreat).collect(Collectors.toList());}private boolean isGreat(Beer beer) {return !beer.getName().equals("Budweiser") &&!beer.getName().equals("Coors Light") &&!beer.getName().equals("PBR");}
}

重新构建您的应用程序并导航到http://localhost:8080/good-beers 。 您应该在浏览器中看到优质啤酒的列表。

使用HTTPie时,您也应该在终端窗口中看到相同的结果。

http localhost:8080/good-beers

使用Create React App创建一个项目

这些天来,创建API似乎很容易,这在很大程度上要归功于Spring Boot。 在本部分中,我希望向您展示使用React创建UI也非常容易。 如果您按照以下步骤操作,则将创建一个新的React应用,从API获取啤酒名称和图像,并创建用于显示数据的组件。

要创建一个React项目,请确保您已安装Node.js , Create React App和Yarn 。

npm install -g create-react-app@1.4.3

在终端窗口中,cd进入spring-boot-react-example目录的根目录并运行以下命令。 该命令将创建一个具有TypeScript支持的新React应用程序。

create-react-app client --scripts-version=react-scripts-ts

运行此过程之后,您将拥有一个新的client目录,其中安装了所有必需的依赖项。 为了验证一切正常,将cd进入client目录并运行yarn start 。 如果一切正常,您应该在浏览器中看到以下内容。

到目前为止,您已经创建了一个good-beers API和一个React应用程序,但是尚未创建UI来显示API中的啤酒列表。 为此,请打开client/src/App.tsx并添加componentDidMount()方法。

componentDidMount() {this.setState({isLoading: true});fetch('http://localhost:8080/good-beers').then(response => response.json()).then(data => this.setState({beers: data, isLoading: false}));
}

React的组件生命周期将调用componentDidMount()方法。 上面的代码使用fetch ,这是XMLHttpRequest的现代替代。 根据caniuse.com,大多数浏览器均支持该功能 。

您会看到它使用响应数据设置了beers状态。 要初始化此组件的状态,您需要重写构造函数。

constructor(props: any) {super(props);this.state = {beers: [],isLoading: false};
}

为此,您需要将参数类型添加到类签名中。 下面的代码显示了此时App类顶部的外观。

class App extends React.Component<{}, any> {constructor(props: any) {super(props);this.state = {beers: [],isLoading: false};}// componentDidMount() and render()
}

更改render()方法以具有以下JSX。 JSX是Facebook的类XML语法,可通过JavaScript呈现HTML。

render() {const {beers, isLoading} = this.state;if (isLoading) {return <p>Loading...</p>;}return (<div className="App"><div className="App-header"><img src={logo} className="App-logo" alt="logo" /><h2>Welcome to React</h2></div><div><h2>Beer List</h2>{beers.map((beer: any) =><div key={beer.id}>{beer.name}</div>)}</div></div>);
}

如果在浏览器中查看http://localhost:3000 ,则会看到“正在加载...”消息。 如果您在浏览器的控制台中查看,可能会看到有关CORS的问题。

Failed to load http://localhost:8080/good-beers: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

要解决此问题,您需要将Spring Boot配置为允许从http://localhost:3000进行跨域访问。

为Spring Boot配置CORS

在服务器项目中,打开server/src/main/java/com/example/demo/beer/BeerController.java并添加@CrossOrigin批注以启用来自客户端的跨域资源共享(CORS)( http://localhost:3000 )。

import org.springframework.web.bind.annotation.CrossOrigin;
...@GetMapping("/good-beers")@CrossOrigin(origins = "http://localhost:3000")public Collection goodBeers() {

进行了这些更改之后,重新启动服务器,刷新浏览器,您应该能够从Spring Boot API中看到啤酒列表。

创建一个BeerList组件

为了使此应用程序更易于维护,请将啤酒清单的获取和呈现从App.tsx到其自己的BeerList组件。 创建src/BeerList.tsx并使用App.tsx的代码填充它。

import * as React from 'react';class BeerList extends React.Component<{}, any> {constructor(props: any) {super(props);this.state = {beers: [],isLoading: false};}componentDidMount() {this.setState({isLoading: true});fetch('http://localhost:8080/good-beers').then(response => response.json()).then(data => this.setState({beers: data, isLoading: false}));}render() {const {beers, isLoading} = this.state;if (isLoading) {return <p>Loading...</p>;}return (<div><h2>Beer List</h2>{beers.map((beer: any) =><div key={beer.id}>{beer.name}</div>)}</div>);}
}export default BeerList;

然后更改client/src/App.tsx ,使其仅包含一个外壳和对<BeerList/>的引用。

import * as React from 'react';
import './App.css';
import BeerList from './BeerList';const logo = require('./logo.svg');class App extends React.Component<{}, any> {render() {return (<div className="App"><div className="App-header"><img src={logo} className="App-logo" alt="logo"/><h2>Welcome to React</h2></div><BeerList/></div>);}
}export default App;

创建一个GiphyImage组件

为了使其看起来更好一点,添加GIPHY组件以根据啤酒的名称获取图像。 创建client/src/GiphyImage.tsx并将以下代码放入其中。

import * as React from 'react';interface GiphyImageProps {name: string;
}class GiphyImage extends React.Component<GiphyImageProps, any> {constructor(props: GiphyImageProps) {super(props);this.state = {giphyUrl: '',isLoading: false};}componentDidMount() {const giphyApi = '//api.giphy.com/v1/gifs/search?api_key=dc6zaTOxFJmzC&limit=1&q=';fetch(giphyApi + this.props.name).then(response => response.json()).then(response => {if (response.data.length > 0) {this.setState({giphyUrl: response.data[0].images.original.url});} else {// dancing cat for no images foundthis.setState({giphyUrl: '//media.giphy.com/media/YaOxRsmrv9IeA/giphy.gif'});}this.setState({isLoading: false});});}render() {const {giphyUrl, isLoading} = this.state;if (isLoading) {return <p>Loading image...</p>;}return (<img src={giphyUrl} alt={this.props.name} width="200"/>);}
}export default GiphyImage;

更改BeerList.tsxrender()方法以使用此组件。

import GiphyImage from './GiphyImage';
...
render() {const {beers, isLoading} = this.state;if (isLoading) {return <p>Loading...</p>;}return (<div><h2>Beer List</h2>{beers.map((beer: any) =><div key={beer.id}>{beer.name}<br/><GiphyImage name={beer.name}/></div>)}</div>);
}

结果应类似于以下带有图像的啤酒名称列表。

您刚刚创建了一个React应用,该应用使用跨域请求与Spring Boot API进行通讯。 恭喜你!

添加PWA支持

Create React App开箱即用地支持渐进式Web应用程序(PWA)。 要了解其集成方式,请打开client/README.md并搜索“制作渐进式Web应用程序”。

要查看其工作方式,请在client目录中运行yarn build 。 该命令完成后,您将看到类似以下的消息。

The build folder is ready to be deployed.
You may serve it with a static server:yarn global add serveserve -s build

运行建议的命令,您应该能够打开浏览器以查看http://localhost:5000 。 您的浏览器可能会在其控制台中显示CORS错误,因此BeerController.java再次打开BeerController.java并调整其允许的来源以允许端口5000。

@CrossOrigin(origins = {"http://localhost:3000", "http://localhost:5000"})

重新启动服务器,并且http://localhost:5000应该加载啤酒名称和图像。

我在Chrome中进行了Lighthouse审核,发现此应用目前仅获得73/100的评分。

您会在上面的屏幕截图中注意到“清单没有至少512px的图标”。 听起来很容易修复。 您可以从此页面下载512像素的免费啤酒图标。

注意:此图标由Freepik从www.flaticon.com制作 。 它由CC 3.0 BY许可。

将下载的beer.png复制到client/public 。 修改client/public/manifest.json以具有特定于此应用程序的名称,并添加512像素的图标。

{"short_name": "Beer","name": "Good Beer","icons": [{"src": "favicon.ico","sizes": "192x192","type": "image/png"},{"src": "beer.png","sizes": "512x512","type": "image/png"}],"start_url": "./index.html","display": "standalone","theme_color": "#000000","background_color": "#ffffff"
}

进行此更改后,我的PWA得分达到82灯塔评分。 该报告最突出的抱怨是我没有使用HTTPS。 为了查看该应用使用HTTPS时的评分,我将其部署到Pivotal Cloud Foundry和Heroku 。 我很高兴发现它在两个平台上的得分都为

使用Spring Boot和React进行Bootiful开发相关推荐

  1. spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发

     前言 Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库. Electron通过将Chromium和Node.js合并到同一个运行时环 ...

  2. spring boot + vue + element-ui全栈开发入门

    今天想弄弄element-ui  然后就在网上找了个例子 感觉还是可以用的  第一步是完成了  果断 拿过来  放到我这里这  下面直接是连接  点进去 就可以用啊 本想着不用vue   直接导入连接 ...

  3. Spring Boot:(四)开发Web应用之JSP篇

    Spring Boot:(四)开发Web应用之JSP篇 前言 上一篇介绍了Spring Boot中使用Thymeleaf模板引擎,今天来介绍一下如何使用SpringBoot官方不推荐的jsp,虽然难度 ...

  4. Spring Boot:(三)开发Web应用之Thymeleaf篇

    Spring Boot:(三)开发Web应用之Thymeleaf篇 前言 Web开发是我们平时开发中至关重要的,这里就来介绍一下Spring Boot对Web开发的支持. 正文 Spring Boot ...

  5. Spring Boot(3) Web开发(1)静态资源处理

    Spring Boot(3) Web开发(1)静态资源处理 基于spring boot 2.4.3版本 1.静态资源访问 1.1 静态资源目录 把静态资源放在类路径下的以下目录:/static; /p ...

  6. 基于Spring Boot和Kotlin的联合开发

    基于Spring Boot和Kotlin的联合开发 版权声明:本文为博主chszs的原创文章,未获得博主授权均不能转载,否则视为侵权. 一.概述 Spring官方最近宣布,将在Spring Frame ...

  7. 《Spring Boot极简教程》第8章 Spring Boot集成Groovy,Grails开发

    第8章 Spring Boot集成Groovy,Grails开发 本章介绍Spring Boot集成Groovy,Grails开发.我们将开发一个极简版的pms(项目管理系统). Groovy和Gra ...

  8. SoJpt Boot 2.3-3.8 发布,Spring Boot 使用 Jfinal 特性极速开发

    SoJpt Boot 2.3-3.8 发布了.SoJpt Boot 基于 JFinal 与 Spring Boot制作, 实现了 Spring Boot 与 Jfinal 的混合双打,使 Spring ...

  9. spring boot + vue + element-ui全栈开发入门——前后端整合开发

    一.配置 思路是通过node的跨域配置来调用spring boot的rest api. 修改config\index.js文件,设置跨域配置proxyTable: proxyTable: {'/api ...

最新文章

  1. ORB_SLAM2回环检测
  2. Java快速创建大量对象_3分钟 快速理解JVM创建对象的步骤!
  3. SAP MM 移动平均价的商品发票价格和采购订单价格差异的处理
  4. spring boot集成swagger,自定义注解,拦截器,xss过滤,异步调用,定时任务案例...
  5. 计算机常见屏幕英语语句,计算机常见屏幕英语
  6. nosuchelementexception 是什么异常_老公出轨有哪些日常表现?老公出轨异常表现
  7. from Crypto.Cipher import AES报错
  8. eclipse更改android版本,在Android Studio和Android Eclipse 更改现有项目里的SDK版本
  9. Ubuntu 18.04配置 apache https 访问
  10. 因为项目的原因,要学习J2EE了
  11. struts2初步学习路线
  12. Mac Eclipse 主题选择
  13. 制衣软件测试自学,服装检验作业指导书.doc
  14. 34.【日期】计算后续日期--北京理工大学编程题
  15. java开发常见的问题及解决办法 - java开发中遇到的难点有哪些_java开发常见的问题及解决办法
  16. python中每个if条件后面都要使用冒号_每个if条件后面都要使用冒号。
  17. 【五年】Java打怪升级之路
  18. UE4----GC(垃圾回收)
  19. R语言(6)-数据结构之矩阵(matrices)与数组(array)
  20. 一小时人生服务器维护,TapTap《一小时人生》手游:说好的一小时人生模拟,我却只能活6分钟...

热门文章

  1. Spark入门(四)Idea远程提交项目到spark集群
  2. hive命令出现问题Failed with exception Java.io.IOException:java.lang.IllegalArgumentException: java.NET.URI
  3. JS 获取浏览器、显示器 窗体等宽度和高度
  4. JSON Web Token (JWT)生成Token及解密实战
  5. Linux指令类型(一)change指令
  6. ssh(Spring+Spring mvc+hibernate)——applicationContext-servlet.xml
  7. 2016蓝桥杯省赛---java---B---1(煤球数目)
  8. oracle 更新参数,Oracle动态、静态参数参数修改规则
  9. 鸿蒙 电视 安卓,华为鸿蒙2.0来了!打通手机、电视、PC全平台,Mate 40 整装齐发...
  10. boot gwt_带Spring Boot的GWT