使用React,Spring Boot和用户身份验证构建CRUD应用程序

建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!

React是用于创建Web应用程序前端的最受欢迎的库之一。 使用Spring Boot 为面向React的应用程序创建CRUD后端比以往任何时候都更加容易。 在本教程中,我们将它们捆绑在一起,然后使用Stormpath添加身份验证和授权协议。

我们将从使用React创建一个静态数据视图开始。 然后,我们将使用Spring Boot创建一个REST后端,进行绑定,并使用Stormpath添加用户安全性。 即使您以前从未使用过React,一切也应该简单明了。

支持这篇文章的源代码可以在这个GitHub repo中找到。

服务前线

通常,React应用程序是使用Node.js来提供服务的,但是如果您是Java开发人员,则可能会对这种Spring Boot方法感到非常满意。

最初,您将整个应用程序放在一个文件index.html 。 要告诉Spring Boot将其用作主页,可以使用@Controller批注。

@Controller
public class HomeController {@RequestMapping(value = "/")public String index() {return "index.html";}
}

创建一个空目录,并将上面的代码放入src/main/java/tutorial/HomeController.java 。 然后,当您加载站点时,Spring Boot将寻找src/main/resources/static/index.html

<!DOCTYPE html>
<html>
<head><title>React + Spring</title>
</head>
<body>
</body>
</html>

创建一个pom.xml和一个Spring Boot应用程序类。 将以下内容用于您的POM。

<project><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.4.1.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

将以下内容放入src/main/java/tutorial/Application.java

@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

当使用mvn spring-boot:run启动服务器并访问localhost:8080您应该看到一个空白页,标题为“ React + Spring”。

5563044

删除重启

通常,每次更改前端时都必须重新启动服务器,这很麻烦。 使用Spring Boot的开发人员工具可以使我们解决这个问题。 将以下依赖项添加到您的POM。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional>
</dependency>

还要将此配置添加到您的Spring Boot Maven插件中:

<configuration><addResources>true</addResources>
</configuration>

现在,当您更改应用程序或重新编译任何类时,刷新浏览器时它应该会更新。

反应准系统HTML

开始反应! 最基本的React页面包含三件事:根元素,JavaScript导入和脚本标签。

<!DOCTYPE html>
<html>
<head><title>React + Spring</title>
</head>
<body><div id='root'></div><script src="https://fb.me/react-15.0.1.js"></script><script src="https://fb.me/react-dom-15.0.1.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script><script type="text/babel"></script>
</body>
</html>

根元素是React将在其中插入视图HTML的位置。 导入引入了三个库-两个用于React本身,另一个用于使用babel翻译我们的视图模板。

注意:为了便于测试,我们使用CDN引入库,但是通常您会使用webpack之类的东西将所有Javascript合并到一个文件中。

现在,将您的React代码放入script标签中。

React基础

如反应教程中的想法所述,您应该通过将接口分解为components来开始对应用程序进行编码。

<script type="text/babel">
var Employee = React.createClass({});
var EmployeeTable = React.createClass({});
</script>

在这里,您创建了两个-一个用于雇员表,另一个用于雇员条目。 然后,每个组件都需要一个渲染函数,该函数描述要生成HTML。

<script type="text/babel">
var Employee = React.createClass({render: function() {return (<div>employee</div>);}
});
var EmployeeTable = React.createClass({render: function() {return (<div>employee table</div>);}
});
</script>

这是Babel编译器用来将HTML代码转换为正确的React语句的地方。 注意div标签如何从render语句返回。

您需要告诉React将父组件HTML插入根元素。 这是使用ReactDOM.render方法完成的。

<script type="text/babel">
var Employee = React.createClass({render: function() {return (<div>employee</div>);}
});
var EmployeeTable = React.createClass({render: function() {return (<div>employee table</div>);}
});ReactDOM.render(<EmployeeTable />, document.getElementById('root')
);
</script>

通过刷新浏览器,您应该看到您创建的简单文本元素。

26089170

要查看插入到根元素中HTML React,可以使用浏览器的检查器(Chrome中的Ctrl-Shift-J)。

22301758

将组件捆绑在一起

现在您已经有了组件,让我们将它们绑在一起。 您可以从尝试呈现硬编码的数据开始。 您稍后将使用REST服务器。

ReactDOM命令上方,输入以下内容:

var EMPLOYEES = [{name: 'Joe Biden', age: 45, years: 5},{name: 'President Obama', age: 54, years: 8},{name: 'Crystal Mac', age: 34, years: 12},{name: 'James Henry', age: 33, years: 2}
];

然后在实例化表时添加employees={EMPLOYEES}

ReactDOM.render(<EmployeeTable employees={EMPLOYEES} />, document.getElementById('root')
);

如您所料,这会将数据传递到名为employees的变量中。 在EmployeeTable内部,您可以使用this.props进行访问。 让我们用它来为每个雇员生成一个带有一行的表。

var EmployeeTable = React.createClass({render: function() {var rows = [];this.props.employees.forEach(function(employee) {rows.push(<Employee employee={employee} />);});return (<table><thead><tr><th>Name</th><th>Age</th><th>Years</th></tr></thead><tbody>{rows}</tbody></table>);}
});

这将为数据中的每个元素实例化一个新的Employee类(设置employee属性)并将其推入数组。 然后{rows}从子类中放入所需HTML。

现在,您需要做的就是更新Employee上的render方法。

var Employee = React.createClass({render: function() {return (<tr><td>{this.props.employee.name}</td><td>{this.props.employee.age}</td><td>{this.props.employee.years}</td></tr>);}
});

您可以添加Bootstrap以使表看起来不错。 在脚本导入标签的下方添加以下内容:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

然后用容器div包围主表,并为表元素提供一些Bootstrap类名称。

<div className="container"><table className="table table-striped"><thead><tr><th>Name</th><th>Age</th><th>Years</th></tr></thead><tbody>{rows}</tbody></table>
</div>

刷新浏览器应该可以很好地查看您硬编码的数据!

86263098

添加真实数据

要使用来自服务器的数据对象,您需要添加服务器! 使用Spring Boot做到这一点非常简单。 在src/main/java/tutorial/Employee.java添加以下代码:

@Data
@Entity
public class Employee {private @Id @GeneratedValue Long id;private String name;private int age;private int years;private Employee() {}public Employee(String name, int age, int years) {this.name = name;this.age = age;this.years = years;}
}

这是我们的豆。 注意: @Data批注来自Project Lombok 。

现在,使用Spring Data JPA创建一个存储库。

public interface EmployeeRepository extends CrudRepository<Employee, Long> {}

要加载数据,请创建一个CommandLineRunner实现,该实现使用存储库在数据库中创建新记录。

@Component
public class DatabaseLoader implements CommandLineRunner {private final EmployeeRepository repository;@Autowiredpublic DatabaseLoader(EmployeeRepository repository) {this.repository = repository;}@Overridepublic void run(String... strings) throws Exception {this.repository.save(new Employee("Joe Biden", 45, 5));this.repository.save(new Employee("President Obama", 54, 8));this.repository.save(new Employee("Crystal Mac", 34, 12));this.repository.save(new Employee("James Henry", 33, 2));}
}

剩下的唯一事情就是引入依赖关系。 将以下内容添加到pom.xml将使您的存储库成为REST端点。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

您还需要包括Project Lombok (可让您忽略为bean创建getter和setter)。

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version><scope>provided</scope>
</dependency>

并且您需要一个数据库(Spring Boot会自动配置该数据库)。 您可以使用H2,它是嵌入式的(即在内存中/不会重新启动)。

<dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId>
</dependency>

就是这样! 如果现在重新启动,您将拥有一个具有数据功能的REST服务器。

映射URL

如果将以下内容添加到src/main/resources/application.properties则所有REST端点调用都将位于localhost:8080/api

spring.data.rest.basePath=/api

从命令行调用localhost:8080/api/employees应该会给出您加载的数据的列表。

反应和REST

现在,您需要将数据从REST端点拉入React视图。 您可以使用jQuery完成此操作。 将以下导入添加到HTML:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

现在创建一个包装器类,该包装器类在其render方法中返回EmployeeTable

var App = React.createClass({loadEmployeesFromServer: function () {var self = this;$.ajax({url: "http://localhost:8080/api/employees"}).then(function (data) {self.setState({employees: data._embedded.employees});});},getInitialState: function () {return {employees: []};},componentDidMount: function () {this.loadEmployeesFromServer();},render() {return ( <EmployeeTable employees={this.state.employees}/> );}
});

您必须首先使用getInitialState进行初始化来设置state ,然后使用componentDidMount来完成加载所有内容时所需的操作。

现在,将主ReactDOM.render替换为新类。

ReactDOM.render(<App />, document.getElementById('root') );

刷新后,您应该会看到与以前相同的视图,只是现在正在从服务器加载数据。

互动性

您需要为前端做的最后一件事是交互性。 让我们添加一个delete按钮,看看它如何工作。

将以下列添加到您的员工渲染中。

<td><button className="btn btn-info" onClick={this.handleDelete}>Delete</button>
</td>

您将在handleDelete秒钟内编写handleDelete方法。 在雇员表类中添加另一个标题后,您应该看到每个条目旁边都出现了按钮。

8223957

从服务器删除

在将删除请求发送到后端之前,最好添加通知消息。 为此,您可以使用Toastr ,这将允许您显示弹出窗口。 在HTML顶部添加以下内容:

<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.css">

现在,您可以在脚本中使用toastr.error('something went wrong')类的命令发送消息。

让我们测试一下! 将您的员工类别更改为以下内容:

var Employee = React.createClass({getInitialState: function() {return {display: true };},handleDelete() {var self = this;$.ajax({url: self.props.employee._links.self.href,type: 'DELETE',success: function(result) {self.setState({display: false});},error: function(xhr, ajaxOptions, thrownError) {toastr.error(xhr.responseJSON.message);}});},render: function() {if (this.state.display==false) return null;else return (<tr><td>{this.props.employee.name}</td><td>{this.props.employee.age}</td><td>{this.props.employee.years}</td><td><button className="btn btn-info" onClick={this.handleDelete}>Delete</button></td></tr>);}
});

这将设置一个display状态,该状态决定是否渲染。 如果成功删除了员工,则此变量设置为true。 handleDelete方法将删除请求发送到服务器(使用从get请求返回的href)。 如果成功,则将display设置为false并更新渲染。 否则,Toastr会通知用户发生错误。

尝试删除条目并刷新页面。 它应该保持删除状态。

注意:由于您正在使用内存数据库,因此重新启动服务器将恢复相同的数据。

添加用户身份验证

让我们在React应用程序中添加一项最终功能,即Stormpath,以进行用户身份验证。 您将需要使用Stormpath永久免费的开发人员帐户 。

您需要做的第一件事是将Stormpath应用程序详细信息放在application.properties

stormpath.application.href = <your app href>
stormpath.client.apiKey.id = <your api key id>
stormpath.client.apiKey.secret = <your api key secret>

注意:出于安全原因,您不应将Stormpath密钥存储在项目文件中。 而是使用环境变量。 看这里 。

接下来,将Stormpath启动器添加到您的Maven依赖项中。

<dependency><groupId>com.stormpath.spring</groupId><artifactId>stormpath-default-spring-boot-starter</artifactId><version>1.1.2</version>
</dependency>

您还需要将index.html文件移动到src/main/resources/templates这是因为Stormpath的Spring Boot启动程序默认使用Thymeleaf模板库。 更改HomeController以也返回index

@Controller
public class HomeController {@RequestMapping(value = "/")public String index() {return "index";}
}

您还需要将您的React代码移动到一个单独的文件中。 这是因为Thymeleaf不喜欢某些角色。 将代码从脚本标签的内部移至src/main/webapp/public/app.js 默认情况下,此文件夹对公众开放。 然后将此脚本导入HTML的底部。

<script type="text/babel" src="/public/app.js"></script>

然后创建一个安全适配器,调用该适配器适用于stormpath()

@Configuration
public class Security extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.apply(stormpath());}
}

现在,当您重新启动服务器并尝试访问主页时,将出现登录页面提示。

3503857

输入您在application.properties放入的Stormpath应用程序附带的详细信息,应像以前一样将您带到数据视图页面。

注销

您还需要能够注销。 这就像添加一个将帖子发送到/logout的表单一样简单(Stormpath会默认设置该表单)。

<div class='container'><div id='root'></div><form action="/logout" method="post"><input class="btn btn-danger center-block" type="submit" value="Logout" /></form>
</div>

您可以用Bootstrap容器包围React根元素和表单,以更好地对齐。

3245088

单击注销按钮将使您返回到以前的登录屏幕。

设置授权

最后,您只想让具有正确访问权限的用户删除员工。 要锁定内容,可以使用Spring Security的PreAuthorize注释。 将存储库代码更改为以下内容:

public interface EmployeeRepository extends CrudRepository<Employee, Long> {@PreAuthorize("hasAuthority('ROLE_ADMIN')")@Overridevoid delete(Long aLong);
}

现在,只有具有ROLE_ADMIN权限的用户才能删除。 如果重新启动服务器并尝试单击“删除”,则应收到一条消息,提示“访问被拒绝”。

36408723

要为用户提供所需的权限,您需要通过管理控制台将其添加到Stormpath组中。

73134913-1024x423

在此示例中,有一个名为Supervisor的组已附加到相关应用程序。 要与该组集成,只需将ROLE_ADMIN字符串替换为该组的HREF并重新启动。 如果登录的用户是Supervisor组的成员(请参阅帐户),则应允许您删除。

尘埃落定

就像您已经创建了一个以授权和React为前端的兼容CRUD Web应用程序。 希望本教程对您有所帮助! 如果您对集成React,Spring Boot和Stormpath有任何疑问,请发表评论。

要查看使用Spring Boot后端的更完整的React应用程序,请参阅React.js和Spring Data REST 。

建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!

翻译自: https://www.javacodegeeks.com/2016/12/build-crud-application-react-spring-boot-user-authentication.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/351532.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java基本数据类型所占长度_java基本数据类型长度详解

java基本数据类型基础知识机器数和真值机器数一个数在计算机中的二进制表示形式,叫做这个数的机器数机器数是带符号的&#xff0c;在计算机用一个数的最高位存放符号, 正数为0, 负数为1例如:dec 3 bit 00000011dec -3 bit 10000011真值将带符号位的机器数对应的真正数值称为机…

解释型语言和编译型语言的区别

解释型语言和编译型语言的区别 首先&#xff0c;我们编程都是用的高级语言(写汇编和机器语言的大牛们除外)&#xff0c;计算机不能直接理解高级语言&#xff0c;只能理解和运行机器语言&#xff0c;所以必须要把高级语言翻译成机器语言&#xff0c;计算机才能运行高级语言所编写…

解决tomcat中文传输乱码问题

<Connector URIEncoding"utf-8" connectionTimeout"20000" encoding"utf-8" port"8080" protocol"HTTP/1.1" redirectPort"8443"/> 在server.xml中找到这句即可&#xff0c;加上URIEncodingUTF-8即可。转载…

关于java结构中描述正确的是_下列关于Java中类的构造方法的描述,正确的是()...

A&#xff1a;构造函数没有返回值&#xff0c;也不能用void修饰。如果不小心给构造函数前面添加了返回值类型&#xff0c;那么这将使这个构造函数变成一个普通的方法&#xff0c;在运行时将产生找不到构造方法的错误。C&#xff1a;super(参数)&#xff1a;调用父类中的某一个构…

如何合理地估算线程池大小?

如何合理地估算线程池大小&#xff1f; 这个问题虽然看起来很小&#xff0c;却并不那么容易回答。大家如果有更好的方法欢迎赐教&#xff0c;先来一个天真的估算方法&#xff1a;假设要求一个系统的TPS&#xff08;Transaction Per Second或者Task Per Second&#xff09;至少为…

使用Arquillian,Docker和Selenium使Web UI测试再次变得出色(第1部分)

问题简介 大多数时候&#xff0c;当您需要为Web UI编写功能测试/端到端测试时&#xff0c;您最终会使用Selenium &#xff0c;它可以被视为Java世界中用于Web UI测试的事实上的工具。 我确定您已经将其用于此类测试。 但是可能同时&#xff0c;您遇到了功能测试中一些最常见的…

os sys hashlib

os模块 os模块是与操作系统交互的一个接口​ ?123456789101112131415161718192021222324252627282930313233343536<em>#和文件夹相关os.makedirs(dirname1/dirname2) 可生成多层递归目录os.removedirs(dirname1) 若目录为空&#xff0c;则删除&#xff0c;并递归到…

mysql 打包 脚本_windows下mysql自动备份压缩打包时间命名批处理脚本

我在此文章上做修改&#xff1a;把时间修改成不记录小时分和秒  新建一个名字后缀为“。bat”的文件  set d%date:~0,10%  set d%d:-%  set t%time:~0,8%  set t%t::%  set dzxpathmysql%p%%d%.sql  set ucpathuc%p%%d%%t%.sql  set folderd:\test\  echo of…

java sql 登录失败_java – 接收连接到SQL Server 2008的SQLException“用户登录失败”

我试图通过Java连接到SQL Server 2008.>我已将sqljdbc4.jar添加到我的项目库中.>没有为访问数据库的数据库设置用户名和密码(Windows身份验证).> 1433端口正在侦听,但我仍然收到此异常&#xff1a;SQL Exception: com.microsoft.sqlserver.jdbc.SQLServerException: L…

js-for (var in )遍历顺序乱了

存放的key 为如下&#xff1a; “01”&#xff0c;“02”&#xff0c;“03”&#xff0c;“10”&#xff0c;“11”&#xff0c;“12” 遍历之后“10”&#xff0c;“11”&#xff0c;“12”&#xff0c; “01”&#xff0c;“02”&#xff0c;“03”&#xff0c; 解决办法&…

springboot ---坑 tomcat部署springboot 一直运行不起来

1、首先部署springboot项目的tomcat的版本必须在8.0之后 2、springboot 同样是基于maven的&#xff0c;那么在pom.xml中的tomcat的依赖&#xff1a; <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web&l…

Java新手造假_老板居然让我在Java项目中“造假”

1. 前言老板说&#xff0c;明天甲方要来看产品&#xff0c;你得造点数据&#xff0c;而且数据必须是“真”的&#xff0c;演示效果要好看一些&#xff0c;这样他才会买我们的产品&#xff0c;我好明年给你换个嫂子。一般开发接到这种过分要求都不会很乐意去做&#xff0c;这完全…

设计模式 四人帮_四人帮–代理设计模式

设计模式 四人帮代理是另一种结构设计模式 &#xff0c;可以“代表”另一个对象或“代替”另一个对象以访问后面的对象。 何时使用此模式&#xff1f; 当我们需要创建一个包装来覆盖客户端的主要对象的复杂性时&#xff0c;将使用代理模式。 有哪些使用场景&#xff1f; 虚…

uniq 去除重复命令使用方法介绍

Linux Shell学习&#xff1a;uniq命令使用方法介绍uniq命令的作用&#xff1a;显示唯一的行&#xff0c;对于那些连续重复的行只显示一次&#xff01;接下来通过实践实例说明. [关键字] Linux Shell uniq 看test.txt文件的内容&#xff0c;可以看到其中的连续重复行 [roothexu.…

sqoop导数据出现问题

执行下面命令的时候报错 ./sqoop import \ --connect jdbc:mysql://mini1:3306/userdb \ --username root \ --password 123456 \ --table emp --m 1 ERROR manager.SqlManager: Error executing statement: java.sql.SQLException: Access denied for user rootmini1 (using p…

java导出jar带第三方库_在.jar文件中导出java库

我仍然是java的新手,我对导出.jar文件非常新.我有一个小游戏,我想发送给一些朋友,我被告知在另一个问题,我应该将它导出到一个可执行的jar文件.好吧,我终于在我的计算机上工作了但是当我把它发送给其他人时它不起作用,因为他们没有图书馆.我正在导入objectdraw库,没有它我的程序…

15分钟内使用Twilio和Stormpath在Spring Boot中进行身份管理

建筑物身份管理&#xff0c;包括身份验证和授权&#xff1f; 尝试Stormpath&#xff01; 我们的REST API和强大的Java SDK支持可以消除您的安全风险&#xff0c;并且可以在几分钟内实现。 注册 &#xff0c;再也不会建立auth了&#xff01; 今天&#xff0c;不到30秒左右的时间…

Spark系列之:使用spark合并hive数据库多个分区的数据到一个分区中

Spark系列之&#xff1a;使用spark合并hive数据库多个分区的数据到一个分区中 把两个分区的数据合并到同一个分区下把其中一个分区的数据通过append方式添加到另一个分区即可 %spark val df spark.sql("select * from optics_prod.product_1h_a where datetime202311142…

window下查看dll, lib文件是32位还是64位

工具&#xff1a;dumpbin.exe 依赖&#xff1a;link.exe, mspdb100.dll 命令&#xff1a; dumpbin /headers E:\math.dll 结果&#xff1a; Dump of file E:\math.dll PE signature found File Type: DLL FILE HEADER VALUES 14C machine (x86) -----…

【转载】分布式之redis复习精讲

注&#xff1a; 本篇文章转自&#xff1a;分布式之redis复习精讲 引言 为什么写这篇文章? 博主的《分布式之消息队列复习精讲》得到了大家的好评&#xff0c;内心诚惶诚恐&#xff0c;想着再出一篇关于复习精讲的文章。但是还是要说明一下&#xff0c;复习精讲的文章偏面试准备…