Spring Boot和React js FullStack应用程序

朱华皓
2023-12-01

Full-stack application with Spring boot and React js, with WEBPACK & BABEL. JUNIT Tests , RESTful API.

使用Spring Boot和React js以及WEBPACK和BABEL的全栈应用程序 JUNIT测试,RESTful API。

1. Spring Boot(初始化器) (1. Spring Boot (Initializer))

To start off with you can use Spring Initializr to get the Spring Boot project structure for you, and this can be found here

首先,您可以使用Spring Initializr为您获取Spring Boot项目结构,可以在这里找到

Once you get there in this case im using Maven , and that’s my personal preference over Gradle since it gives a nice xml layout for your setup , in terms of installing dependency , plugins etc. its essentially a tool for your project management, just like package.json for those who are familiar with node js.

在这种情况下,一旦您到达那里,我将使用Maven,这是我个人对Gradle的偏爱,因为它在安装依赖项,插件等方面为您的设置提供了不错的xml布局。它实际上是项目管理的工具,就像软件包一样.json供熟悉Node js的人使用。

You also need to add a couple of dependencies which are

您还需要添加几个依赖项,分别是

  • JPA — Data persistence in SQL stores with Java Persistence API

    JPA —使用Java Persistence APISQL存储中的数据持久性
  • thymeleaf — A modern server-side Java template engine

    thymeleaf —现代的服务器端Java模板引擎
  • WEB — Build web, including RESTful, applications using Spring MVC

    WEB —使用Spring MVC构建Web,包括RESTful应用程序
  • H2 — Provides a volatile in-memory database

    H2 —提供易失的内存数据库
  • Lombok — Java annotation library which helps reduce boilierplate code

    Lombok — Java注释库,可帮助减少盲板代码

2. Rest API服务 (2. Rest API Service)

一个。 楷模 (a. models)

Now lets create the REST API service for the backend application which will be able to perform basic CRUD (Create, Read, Update ,Delete) functionality.

现在,让我们为后端应用程序创建REST API服务,该服务将能够执行基本的CRUD(创建,读取,更新,删除)功能。

First create a package name models. Inside models create class User for your user model. See code below

首先创建一个包名称模型。 内部模型为您的用户模型创建类User。 见下面的代码

First you will notice the @Entity annotation- this tell Spring that it is a JPA entity and it is mapped to table named User. If you want to the the table name you will have to annotate it with @Table(name = “new_table_name_here”) You probably noticed that this is too much of code to create an entity not to worry, Remember the Lambok dependency this is the best time to use it since it offers a functionality of writing code with less boiler plate of code.

首先,您会注意到@Entity批注-这告诉Spring这是一个JPA实体,并且已映射到名为User的表。 如果要使用表名,则必须使用@Table(name =“ new_table_name_here”)对其进行注释。您可能已经注意到,太多代码无法创建实体,请记住,最好是使用Lambok依赖项有时间使用它了,因为它提供了用更少的样板代码编写代码的功能。

In the above snippet you will notice we have added a couple of annotations @Data — is a convenient shortcut that bundles features of @toString, @EqualsAndHashCode, @Getter / @Setter and @RequiredArgsConstructor . @NoArgsConstructor provides the default construct @AllArgsConstructor bundles the non default constructor.

在上面的代码片段中,您会注意到我们添加了几个注释@Data -是方便快捷的快捷方式,它捆绑了@ toString,@ EqualsAndHashCode,@ Getter / @ Setter和@RequiredArgsConstructor的功能。 @NoArgsConstructor提供默认构造函数@AllArgsConstructor捆绑非默认构造函数。

b。 仓库 (b. repositories)

Lets create a repositories package will an interface called UserRepository. The interface extends the Jpa repository so that we can have all methods that is provided by the JpaRepository that allows us to query our database.

让我们创建一个存储库包将一个名为UserRepository的接口。 该接口扩展了Jpa存储库,因此我们可以使用JpaRepository提供的所有方法来查询数据库。

C。 控制器 (c. controllers)

Now that you got you repository setup its time to create a controllers package and with a class called UserController. The is where the REST service with Spring begins. The controller will save all end points of our user controller, which will then be consumed by the outside world. All the action feature required by our CRUD app are going to seat here ie GET, POST, PUT and DELETE actions. See code below:

现在,您已经完成了存储库设置,现在可以创建一个控制器包并使用一个名为UserController的类。 使用Spring的REST服务从此处开始。 控制器将保存用户控制器的所有端点,然后供外界使用。 我们的CRUD应用程序所需的所有动作功能都将放在此处,即GET,POST,PUT和DELETE动作。 参见下面的代码:

In the above code the class is annotated with @RestController telling Spring that the data returned by each method will be written straight into the response body instead of rendering a template. The UserRepository is injected by constructor into the controller. The @Autowired enable automatic dependency injection.

在上面的代码中,该类用@RestController注释,告诉Spring每个方法返回的数据将直接写入响应主体中,而不是呈现模板。 UserRepository由构造函数注入到控制器中。 @Autowired启用自动依赖项注入。

The @PostMapping , @GetMapping, @PutMapping and @DeleteMapping corresponds to the POST, GET, UPDATE and DELETE actions. One thing to note here is the @DeleteMapping and @GetMapping which is calling a ResourceNotFoundException class that will output the runtime exception.

@PostMapping,@GetMapping,@PutMapping和@DeleteMapping对应于POST,GET,UPDATE和DELETE操作。 这里要注意的一件事是@DeleteMapping和@GetMapping,它们正在调用ResourceNotFoundException类,该类将输出运行时异常。

Lets quickly implement the ResourceNotFoundException class.

让我们快速实现ResourceNotFoundException类。

d。 例外情况 (d. exceptions)

I like to keep my code clean and packaged. So just quickly create a package called exceptions with a class ResourceNotFoundException. See code below:

我喜欢保持代码清洁和打包。 因此,只需使用类ResourceNotFoundException快速创建一个名为exceptions的包。 参见下面的代码:

The above class extends the RuntimeException which will give us access to all methods that are in that class. In this case just call super in the constructor with message variable. That’s it .,now whenever a user is not found it will return the run time exception with user not Found message and status of HttpStatus.NOT_FOUND.

上面的类扩展了RuntimeException,它将使我们能够访问该类中的所有方法。 在这种情况下,只需在构造函数中使用message变量调用super即可。 就是这样,现在无论何时找不到用户,它都将返回运行时异常,其中包含“未找到”用户消息和HttpStatus.NOT_FOUND的状态。

e。 数据库 (e. database)

  • NB Since we have added the H2 in -memory DB . Spring automatically runs it whenever there is persistence to the db. Please note that H2 Database is volatile meaning it will be automatically be created when the server ran and whenever you stop the server it will tear down the db and its contents. By default, Spring Boot configures the application to connect to an in-memory store with the username sa and an empty password. However, we can change those parameters by adding the following properties to the application.properties file:

    注意:由于我们添加了H2内存数据库。 只要对数据库存在持久性,Spring就会自动运行它。 请注意,H2数据库是易失性的,这意味着它将在服务器运行时自动创建,并且每当您停止服务器时,它将破坏数据库及其内容。 默认情况下,Spring Boot将应用程序配置为使用用户名sa和空密码连接到内存中的存储。 但是,我们可以通过将以下属性添加到application.properties文件来更改这些参数:
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
# Enabling H2 Console
spring.h2.console.enabled=true
# Custom H2 Console URL
spring.h2.console.path=/h2
# Whether to enable remote access.
spring.h2.console.settings.web-allow-others=true
server.error.include-stacktrace=never

F。 REST API测试(JPA单元测试) (f. REST API TESTING(JPA UNIT TESTING))

Now that everything is setup its time for the truth to be reviewed. I like to do things differently so instead of testing our API using Postman im going to do JPA Unit testing. If you are familiar with JPA Unit Testing feel free to test with Postman or jump to next section (INTEGRATING REACTJS)

现在,一切都已准备就绪,可以回顾真相了。 我喜欢做不同的事情,所以不要使用Postman测试我们的API来进行JPA单元测试。 如果您熟悉JPA单元测试,请随时与Postman进行测试或跳到下一部分(INTEGRATING REACTJS)

Now to get things started quickly install JPA Unit testing dependency in your pom.xml file.

现在,为了快速开始,请在pom.xml文件中快速安装JPA单元测试依赖项。

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>

In your test/java/com.<application-name>/ create a file class UserTests with the following testing code:

在您的test / java / com。<application-name> /中 ,使用以下测试代码创建文件类UserTests:

The @DataJpaTest tells Spring to test the persistence layer components that will autoconfigure in-memory embedded H2 database and scan for @Entity classes and Spring Data JPA repositories. We need to autowire the UserRepository so that we will have functions provided by the JPA to be able to query our DB. Spring will look for function annotated with @Test. The JUNIT ASSERT i going to assert most of the tests.

@DataJpaTest告诉Spring测试将自动配置内存中嵌入式H2数据库的持久层组件,并扫描@Entity类和Spring Data JPA存储库。 我们需要自动连接UserRepository,以便我们拥有JPA提供的功能来查询数据库。 Spring将寻找带有@Test注释的函数。 JUNIT ASSERT我将断言大多数测试。

In your terminal You can now run :

在终端中,您现在可以运行:

mvn test

If everything runs well you should have an output similar to this:

如果一切正常,您应该有类似以下的输出:

[INFO] 
[INFO] Results:
[INFO]
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.845 s
[INFO] Finished at: 2020-09-08T19:01:25+02:00
[INFO] Final Memory: 32M/370M
[INFO] ------------------------------------------------------------------------

NB At this point of your test runs successfully congratulations you have made it :) . Now you can jump in to the next section ie (INTEGRATING REACTJS)

注意:至此,测试成功运行,恭喜您成功:)。 现在您可以跳到下一部分,即(INTEGRATING REACTJS)

3.集成React (3. INTEGRATING REACTJS)

Now lets jump in to the frontend of things of our fullstack application.

现在,让我们进入全栈应用程序的前端。

In this section i am assuming you have already installed nodejs in your working environment. If not just quickly install link can be found here

在本节中,我假设您已经在工作环境中安装了nodejs。 如果不只是快速安装链接,可以在这里找到

We are not going to use npm create-react-app to create our frontend since we dont want to separately run the react js application with its own proxy port usually port 3000. We want our Spring backend application to be able to serve the front at its default port 8080, that way we get to experience the fullstack of things without having to separately running two instances servers for our front end and backend application.

我们不会使用npm create-react-app来创建前端,因为我们不想使用其自己的代理端口(通常为端口3000)单独运行react js应用程序。我们希望我们的Spring后端应用程序能够在以下位置提供前端服务它的默认端口8080,这样我们就可以体验整个过程,而不必为前端和后端应用程序分别运行两个实例服务器。

Now you can prepare the react js project structure by creating these folders in your root folder of your application.

现在,您可以通过在应用程序的根文件夹中创建这些文件夹来准备react js项目结构。

$ mkdir -p ./frontend/src/{components,actions,reducers}

The above command will create a folder structure that look like this:

上面的命令将创建一个如下所示的文件夹结构:

frontend/
src/
actions/
components/
reducers/

This is were your react frontend application is going to seat in.

这是您的React前端应用程序即将安装的地方。

3a安装软件包 (3a Installing packages)

We now need to create a package.json file which will have all your dependencies that is going to be used by reactjs framework. To create the package.json file just run

现在,我们需要创建一个package.json文件,其中将包含所有将由reactjs框架使用的依赖项。 要创建package.json文件,只需运行

$ npm init -y

Since you have already installed node this npm command should run just fine, and you now should be able to see the package.json file in your root folder of your project.

由于已经安装了节点,因此此npm命令应该可以正常运行,现在您应该可以在项目的根文件夹中看到package.json文件。

Now at this point you now need to install the following Dev Dependencies and Dependencies for your react .

现在,您现在需要安装以下Dev Dependencies和Dependencies以进行响应。

$ npm i -D webpack webpack-cli
$ npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties
$ npm i -D sass-loader css-loader
$ npm i react react-dom react-router-dom
$ npm i redux react-redux redux-thunk redux-devtools-extension
$ npm i redux-form
$ npm i axios
$ npm i lodash

This will install the Dev Dependencies required by react js .

这将安装react js所需的Dev Dependencies。

  • webpack — will bundle Javascript files for usage in a browser

    webpack-将捆绑Javascript文件以在浏览器中使用
  • babel — is a transpiler ie a Javascript compiler used to convert ECMAScript 2015+ code into a backwards compatible version of Javascript in current and older browser environments.

    babel —是一个编译器,即Javascript编译器,用于在当前和较旧的浏览器环境中将ECMAScript 2015+代码转换为Java的向后兼容版本。
  • react — Javascript library for building user interfaces. Developed by facebook

    react —用于构建用户界面的Javascript库。 由facebook开发
  • redux — The is a predictable state container for Js apps

    redux —这是Js应用程序的可预测状态容器
  • axios — Promise based HTTP client

    axios-基于Promise的HTTP客户端
  • lodash(optional) — Lodash is a reference library made with JavaScript.

    lodash(可选)— Lodash是使用JavaScript制作的参考库。

3b Babel配置 (3b Babel Configuration)

Add a file name .babelrc to the root directory and configure babel:

在根目录中添加文件名.babelrc并配置babel:

{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
},
"useBuiltIns": "usage",
"corejs": 3
}
],
"@babel/preset-react"
],
"plugins": ["@babel/plugin-proposal-class-properties"]
}

3c。 Webpack配置 (3c. Webpack Configuration)

Add a file name webpack.config.js to the root directory and configure webpack:

将文件名webpack.config.js添加到根目录并配置webpack:

“””Quote Spring Docs””” This webpack configuration file:

“”“引用Spring Docs”“””此Webpack配置文件:

  • Defines the entry point as ./src/main/js/App.js. In essence, App.js (a module you will write shortly) is the proverbial public static void main() of our JavaScript application. webpack must know this in order to know what to launch when the final bundle is loaded by the browser.

    将入口点定义为./src/main/js/App.js。 本质上,App.js(您将很快编写的模块)是我们JavaScript应用程序中众所周知的public static void main()。 webpack必须知道这一点,以便知道在浏览器加载最终捆绑包时要启动什么。
  • Creates sourcemaps so that, when you are debugging JS code in the browser, you can link back to original source code.

    创建源映射,以便在浏览器中调试JS代码时可以链接回原始源代码。
  • Compile ALL of the JavaScript bits into ./src/main/resources/static/built/bundle.js, which is a JavaScript equivalent to a Spring Boot uber JAR. All your custom code AND the modules pulled in by the require() calls are stuffed into this file.

    将所有JavaScript位编译为./src/main/resources/static/built/bundle.js,这是与Spring Boot uber JAR等效JavaScript。 您的所有自定义代码以及require()调用引入的模块都填充到此文件中。
  • It hooks into the babel engine, using both es2015 and react presets, in order to compile ES6 React code into a format able to be run in any standard browser.

    它使用es2015和react预设连接到babel引擎,以便将ES6 React代码编译为可以在任何标准浏览器中运行的格式。

With this webpack configuration file setup we now need to create a couple of directories.

通过此webpack配置文件设置,我们现在需要创建几个目录。

3d。 React锅炉板设置 (3d. React boiler plate Setup)

  1. Notice how the above webpack is referencing to ./src/main/js/App.js . Let create a js folder in main and an App.js file inside The App.js file should have this following code:

    注意上面的webpack如何引用./src/main/js/App.js。 让我们在main中创建一个js文件夹,在其中创建一个App.js文件。App.js文件应具有以下代码:
  1. Now we now need to prepare the html that will render the App.js we just created in Spring

    现在,我们需要准备将呈现我们刚刚在Spring中创建的App.js的html。

Remember the Thymeleaf dependency we installed at the beginning in the Spring Initializer it time to get that to use To get started you need to create an index page in src/main/resources/templates/index.html

记住我们在Spring Initializer的开头安装的Thymeleaf依赖项,是时候使用它了。开始之前,您需要在src / main / resources / templates / index.html中创建一个索引页。

The key part in this template is the <div id="app"></div> component in the middle. It is where you will direct React to plug in the rendered output.The bundle.js will automatically generated when we run our application.Spring will automatically know that the main.css file will be created under the static folder in your resources folder so go ahead and create it will use it later.With that set up you should have the Final project structure now looking to something like this:

该模板的关键部分是中间的<div id =“ app”> </ div>组件。 在这里,您将指示React插入渲染的输出.bundle.js将在我们运行应用程序时自动生成.Spring将自动知道main.css文件将在您的资源文件夹的静态文件夹下创建,所以去吧预先创建并在以后使用它。设置完成后,您现在应该使Final项目结构看起来像这样:

- frontend
- sample-project-root
- src
- main
-java
- js
App.js
index.js
- static
main.css
- resources
- templates
index.html
webpack.config.js
package.json
pom.xml

If this is you project string you are good to go and now left with one last step to test this out.

如果这是您的项目字符串,那么您可以继续进行,现在剩下最后一步进行测试了。

3e。 package.json中的脚本设置 (3e. Script Setup in package.json)

In the package.json file we need to finally replace the script tag with the following

在package.json文件中,我们最终需要将以下脚本标记替换为

...
...
"scripts": {
"watch": "webpack --watch -d --output ./target/classes/static/built/bundle.js"
},...
...

This will run the webpack and tell it to render the output (bundle.js) to ./taget/classes/static/built/ folder. The — watch tag will tell the webpack to constantly watch for changes in our code so that when there is such it will update the bundle.js file.

这将运行webpack并告诉它将输出(bundle.js)呈现到./taget/classes/static/built/文件夹。 — watch标签将告诉webpack不断监视我们代码中的更改,以便在有更改时,它将更新bundle.js文件。

3楼 最终设置步骤 (3f. Final Setup Step)

Remember when we create our UserController it had a @RestController annotation to serve the rest methods in that class. If can still recall we said the @RestController tells Spring that the data returned by each method will be written straight into the response body instead of rendering a template. Now we need an endpoint that will render a template. S So lets create a separate class in our controllers called WebMainController which will render the index page of our react App.js main component.

记住,当我们创建UserController时,它具有@RestController批注来服务该类中的其余方法。 如果仍然可以回忆,我们说@RestController告诉Spring每个方法返回的数据将直接写入响应主体中,而不是呈现模板。 现在我们需要一个可以渲染模板的端点。 因此,让我们在名为WebMainController的控制器中创建一个单独的类,该类将呈现我们的React App.js主要组件的索引页。

4.最终测试 (4. FINAL TEST)

Now lets test the full stack application First run your server

现在让我们测试完整的堆栈应用程序首先运行服务器

$ mvn spring-boot:run

If there are no error you are good it means we haven’t messed anything up since our last JUNIT TESTS. Finally transpile your react app by running:

如果没有错误,那说明您很好,这意味着自我们上一次JUNIT测试以来,我们还没有搞砸任何事情。 最后通过运行以下命令来转换您的react应用程序:

$ npm run-script watch

Now you can go to you browser http://localhost:8080/ and if this appears on your browser:

现在,您可以转到浏览器http:// localhost:8080 / ,如果浏览器上显示了此信息:

欢迎使用Spring Boot服务的React前端 (Welcome to React Front End Served by Spring Boot)

Then you have successfully integrated react js and spring boot. Full stack application. If you make changes in your app webpack should be able to update those changes, and all you have to do is to restart your browser.

然后,您已经成功集成了react js和spring boot。 全栈应用程序。 如果您在应用程序中进行更改,则Webpack应该能够更新这些更改,并且您要做的就是重新启动浏览器。

I know this was a long tutorial I will make it in parts and will create a Part 2 of this as soon as i can . So that you will now Learn React.

我知道这是一个漫长的教程,我将分部分进行,并会尽快创建该部分的第2部分。 这样您就可以学习React。

Thank you for taking your time in reading this article.

感谢您抽出宝贵的时间阅读本文。

!!END

!!结束

源代码 (Source Code)

The source code can be found on my git repository here

源代码可以在我的git仓库中找到这里

拉取请求 (Pull Requests)

I Welcome and i encourage all Pull Requests

我欢迎并鼓励所有请求请求

创建和维护者 (Created and Maintained by)

执照 (License)

MIT Licence

麻省理工学院执照

翻译自: https://medium.com/swlh/spring-boot-and-react-js-fullstack-application-7ad99139e95c

 类似资料: