javascript
使用React,Spring Boot和用户身份验证构建CRUD应用程序
建筑物身份管理,包括身份驗(yàn)證和授權(quán)? 嘗試Stormpath! 我們的REST API和強(qiáng)大的Java SDK支持可以消除您的安全風(fēng)險(xiǎn),并且可以在幾分鐘內(nèi)實(shí)現(xiàn)。 注冊(cè) ,再也不會(huì)建立auth了!
React是用于創(chuàng)建Web應(yīng)用程序前端的最受歡迎的庫之一。 使用Spring Boot 為面向React的應(yīng)用程序創(chuàng)建CRUD后端比以往任何時(shí)候都更加容易。 在本教程中,我們將它們捆綁在一起,然后使用Stormpath添加身份驗(yàn)證和授權(quán)協(xié)議。
我們將從使用React創(chuàng)建一個(gè)靜態(tài)數(shù)據(jù)視圖開始。 然后,我們將使用Spring Boot創(chuàng)建一個(gè)REST后端,進(jìn)行綁定,并使用Stormpath添加用戶安全性。 即使您以前從未使用過React,一切也應(yīng)該簡單明了。
支持這篇文章的源代碼可以在這個(gè)GitHub repo中找到。
服務(wù)前線
通常,React應(yīng)用程序是使用Node.js來提供服務(wù)的,但是如果您是Java開發(fā)人員,則可能會(huì)對(duì)這種Spring Boot方法感到非常滿意。
最初,您將整個(gè)應(yīng)用程序放在一個(gè)文件index.html 。 要告訴Spring Boot將其用作主頁,可以使用@Controller批注。
@Controller public class HomeController {@RequestMapping(value = "/")public String index() {return "index.html";} }創(chuàng)建一個(gè)空目錄,并將上面的代碼放入src/main/java/tutorial/HomeController.java 。 然后,當(dāng)您加載站點(diǎn)時(shí),Spring Boot將尋找src/main/resources/static/index.html 。
<!DOCTYPE html> <html> <head><title>React + Spring</title> </head> <body> </body> </html>創(chuàng)建一個(gè)pom.xml和一個(gè)Spring Boot應(yīng)用程序類。 將以下內(nèi)容用于您的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>將以下內(nèi)容放入src/main/java/tutorial/Application.java 。
@SpringBootApplication public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);} }當(dāng)使用mvn spring-boot:run啟動(dòng)服務(wù)器并訪問localhost:8080您應(yīng)該看到一個(gè)空白頁,標(biāo)題為“ React + Spring”。
刪除重啟
通常,每次更改前端時(shí)都必須重新啟動(dòng)服務(wù)器,這很麻煩。 使用Spring Boot的開發(fā)人員工具可以使我們解決這個(gè)問題。 將以下依賴項(xiàng)添加到您的POM。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional> </dependency>還要將此配置添加到您的Spring Boot Maven插件中:
<configuration><addResources>true</addResources> </configuration>現(xiàn)在,當(dāng)您更改應(yīng)用程序或重新編譯任何類時(shí),刷新瀏覽器時(shí)它應(yīng)該會(huì)更新。
反應(yīng)準(zhǔn)系統(tǒng)HTML
開始反應(yīng)! 最基本的React頁面包含三件事:根元素,JavaScript導(dǎo)入和腳本標(biāo)簽。
<!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的位置。 導(dǎo)入引入了三個(gè)庫-兩個(gè)用于React本身,另一個(gè)用于使用babel翻譯我們的視圖模板。
注意:為了便于測試,我們使用CDN引入庫,但是通常您會(huì)使用webpack之類的東西將所有Javascript合并到一個(gè)文件中。
現(xiàn)在,將您的React代碼放入script標(biāo)簽中。
React基礎(chǔ)
如反應(yīng)教程中的想法所述,您應(yīng)該通過將接口分解為components來開始對(duì)應(yīng)用程序進(jìn)行編碼。
<script type="text/babel"> var Employee = React.createClass({}); var EmployeeTable = React.createClass({}); </script>在這里,您創(chuàng)建了兩個(gè)-一個(gè)用于雇員表,另一個(gè)用于雇員條目。 然后,每個(gè)組件都需要一個(gè)渲染函數(shù),該函數(shù)描述要生成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代碼轉(zhuǎn)換為正確的React語句的地方。 注意div標(biāo)簽如何從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>通過刷新瀏覽器,您應(yīng)該看到您創(chuàng)建的簡單文本元素。
要查看插入到根元素中HTML React,可以使用瀏覽器的檢查器(Chrome中的Ctrl-Shift-J)。
將組件捆綁在一起
現(xiàn)在您已經(jīng)有了組件,讓我們將它們綁在一起。 您可以從嘗試呈現(xiàn)硬編碼的數(shù)據(jù)開始。 您稍后將使用REST服務(wù)器。
在ReactDOM命令上方,輸入以下內(nèi)容:
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} ];然后在實(shí)例化表時(shí)添加employees={EMPLOYEES} 。
ReactDOM.render(<EmployeeTable employees={EMPLOYEES} />, document.getElementById('root') );如您所料,這會(huì)將數(shù)據(jù)傳遞到名為employees的變量中。 在EmployeeTable內(nèi)部,您可以使用this.props進(jìn)行訪問。 讓我們用它來為每個(gè)雇員生成一個(gè)帶有一行的表。
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>);} });這將為數(shù)據(jù)中的每個(gè)元素實(shí)例化一個(gè)新的Employee類(設(shè)置employee屬性)并將其推入數(shù)組。 然后{rows}從子類中放入所需HTML。
現(xiàn)在,您需要做的就是更新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以使表看起來不錯(cuò)。 在腳本導(dǎo)入標(biāo)簽的下方添加以下內(nèi)容:
<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>刷新瀏覽器應(yīng)該可以很好地查看您硬編碼的數(shù)據(jù)!
添加真實(shí)數(shù)據(jù)
要使用來自服務(wù)器的數(shù)據(jù)對(duì)象,您需要添加服務(wù)器! 使用Spring Boot做到這一點(diǎn)非常簡單。 在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 。
現(xiàn)在,使用Spring Data JPA創(chuàng)建一個(gè)存儲(chǔ)庫。
public interface EmployeeRepository extends CrudRepository<Employee, Long> {}要加載數(shù)據(jù),請(qǐng)創(chuàng)建一個(gè)CommandLineRunner實(shí)現(xiàn),該實(shí)現(xiàn)使用存儲(chǔ)庫在數(shù)據(jù)庫中創(chuàng)建新記錄。
@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));} }剩下的唯一事情就是引入依賴關(guān)系。 將以下內(nèi)容添加到pom.xml將使您的存儲(chǔ)庫成為REST端點(diǎn)。
<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創(chuàng)建getter和setter)。
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version><scope>provided</scope> </dependency>并且您需要一個(gè)數(shù)據(jù)庫(Spring Boot會(huì)自動(dòng)配置該數(shù)據(jù)庫)。 您可以使用H2,它是嵌入式的(即在內(nèi)存中/不會(huì)重新啟動(dòng))。
<dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId> </dependency>就是這樣! 如果現(xiàn)在重新啟動(dòng),您將擁有一個(gè)具有數(shù)據(jù)功能的REST服務(wù)器。
映射URL
如果將以下內(nèi)容添加到src/main/resources/application.properties則所有REST端點(diǎn)調(diào)用都將位于localhost:8080/api
spring.data.rest.basePath=/api從命令行調(diào)用localhost:8080/api/employees應(yīng)該會(huì)給出您加載的數(shù)據(jù)的列表。
反應(yīng)和REST
現(xiàn)在,您需要將數(shù)據(jù)從REST端點(diǎn)拉入React視圖。 您可以使用jQuery完成此操作。 將以下導(dǎo)入添加到HTML:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>現(xiàn)在創(chuàng)建一個(gè)包裝器類,該包裝器類在其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進(jìn)行初始化來設(shè)置state ,然后使用componentDidMount來完成加載所有內(nèi)容時(shí)所需的操作。
現(xiàn)在,將主ReactDOM.render替換為新類。
ReactDOM.render(<App />, document.getElementById('root') );刷新后,您應(yīng)該會(huì)看到與以前相同的視圖,只是現(xiàn)在正在從服務(wù)器加載數(shù)據(jù)。
互動(dòng)性
您需要為前端做的最后一件事是交互性。 讓我們添加一個(gè)delete按鈕,看看它如何工作。
將以下列添加到您的員工渲染中。
<td><button className="btn btn-info" onClick={this.handleDelete}>Delete</button> </td>您將在handleDelete秒鐘內(nèi)編寫handleDelete方法。 在雇員表類中添加另一個(gè)標(biāo)題后,您應(yīng)該看到每個(gè)條目旁邊都出現(xiàn)了按鈕。
從服務(wù)器刪除
在將刪除請(qǐng)求發(fā)送到后端之前,最好添加通知消息。 為此,您可以使用Toastr ,這將允許您顯示彈出窗口。 在HTML頂部添加以下內(nèi)容:
<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">現(xiàn)在,您可以在腳本中使用toastr.error('something went wrong')類的命令發(fā)送消息。
讓我們測試一下! 將您的員工類別更改為以下內(nèi)容:
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>);} });這將設(shè)置一個(gè)display狀態(tài),該狀態(tài)決定是否渲染。 如果成功刪除了員工,則此變量設(shè)置為true。 handleDelete方法將刪除請(qǐng)求發(fā)送到服務(wù)器(使用從get請(qǐng)求返回的href)。 如果成功,則將display設(shè)置為false并更新渲染。 否則,Toastr會(huì)通知用戶發(fā)生錯(cuò)誤。
嘗試刪除條目并刷新頁面。 它應(yīng)該保持刪除狀態(tài)。
注意:由于您正在使用內(nèi)存數(shù)據(jù)庫,因此重新啟動(dòng)服務(wù)器將恢復(fù)相同的數(shù)據(jù)。
添加用戶身份驗(yàn)證
讓我們?cè)赗eact應(yīng)用程序中添加一項(xiàng)最終功能,即Stormpath,以進(jìn)行用戶身份驗(yàn)證。 您將需要使用Stormpath永久免費(fèi)的開發(fā)人員帳戶 。
您需要做的第一件事是將Stormpath應(yīng)用程序詳細(xì)信息放在application.properties 。
stormpath.application.href = <your app href> stormpath.client.apiKey.id = <your api key id> stormpath.client.apiKey.secret = <your api key secret>注意:出于安全原因,您不應(yīng)將Stormpath密鑰存儲(chǔ)在項(xiàng)目文件中。 而是使用環(huán)境變量。 看這里 。
接下來,將Stormpath啟動(dòng)器添加到您的Maven依賴項(xiàng)中。
<dependency><groupId>com.stormpath.spring</groupId><artifactId>stormpath-default-spring-boot-starter</artifactId><version>1.1.2</version> </dependency>您還需要將index.html文件移動(dòng)到src/main/resources/templates這是因?yàn)镾tormpath的Spring Boot啟動(dòng)程序默認(rèn)使用Thymeleaf模板庫。 更改HomeController以也返回index 。
@Controller public class HomeController {@RequestMapping(value = "/")public String index() {return "index";} }您還需要將您的React代碼移動(dòng)到一個(gè)單獨(dú)的文件中。 這是因?yàn)門hymeleaf不喜歡某些角色。 將代碼從腳本標(biāo)簽的內(nèi)部移至src/main/webapp/public/app.js 默認(rèn)情況下,此文件夾對(duì)公眾開放。 然后將此腳本導(dǎo)入HTML的底部。
<script type="text/babel" src="/public/app.js"></script>然后創(chuàng)建一個(gè)安全適配器,調(diào)用該適配器適用于stormpath() 。
@Configuration public class Security extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.apply(stormpath());} }現(xiàn)在,當(dāng)您重新啟動(dòng)服務(wù)器并嘗試訪問主頁時(shí),將出現(xiàn)登錄頁面提示。
輸入您在application.properties放入的Stormpath應(yīng)用程序附帶的詳細(xì)信息,應(yīng)像以前一樣將您帶到數(shù)據(jù)視圖頁面。
注銷
您還需要能夠注銷。 這就像添加一個(gè)將帖子發(fā)送到/logout的表單一樣簡單(Stormpath會(huì)默認(rèn)設(shè)置該表單)。
<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根元素和表單,以更好地對(duì)齊。
單擊注銷按鈕將使您返回到以前的登錄屏幕。
設(shè)置授權(quán)
最后,您只想讓具有正確訪問權(quán)限的用戶刪除員工。 要鎖定內(nèi)容,可以使用Spring Security的PreAuthorize注釋。 將存儲(chǔ)庫代碼更改為以下內(nèi)容:
public interface EmployeeRepository extends CrudRepository<Employee, Long> {@PreAuthorize("hasAuthority('ROLE_ADMIN')")@Overridevoid delete(Long aLong); }現(xiàn)在,只有具有ROLE_ADMIN權(quán)限的用戶才能刪除。 如果重新啟動(dòng)服務(wù)器并嘗試單擊“刪除”,則應(yīng)收到一條消息,提示“訪問被拒絕”。
要為用戶提供所需的權(quán)限,您需要通過管理控制臺(tái)將其添加到Stormpath組中。
在此示例中,有一個(gè)名為Supervisor的組已附加到相關(guān)應(yīng)用程序。 要與該組集成,只需將ROLE_ADMIN字符串替換為該組的HREF并重新啟動(dòng)。 如果登錄的用戶是Supervisor組的成員(請(qǐng)參閱帳戶),則應(yīng)允許您刪除。
塵埃落定
就像您已經(jīng)創(chuàng)建了一個(gè)以授權(quán)和React為前端的兼容CRUD Web應(yīng)用程序。 希望本教程對(duì)您有所幫助! 如果您對(duì)集成React,Spring Boot和Stormpath有任何疑問,請(qǐng)發(fā)表評(píng)論。
要查看使用Spring Boot后端的更完整的React應(yīng)用程序,請(qǐng)參閱React.js和Spring Data REST 。
建筑物身份管理,包括身份驗(yàn)證和授權(quán)? 嘗試Stormpath! 我們的REST API和強(qiáng)大的Java SDK支持可以消除您的安全風(fēng)險(xiǎn),并且可以在幾分鐘內(nèi)實(shí)現(xiàn)。 注冊(cè) ,再也不會(huì)建立auth了!
翻譯自: https://www.javacodegeeks.com/2016/12/build-crud-application-react-spring-boot-user-authentication.html
總結(jié)
以上是生活随笔為你收集整理的使用React,Spring Boot和用户身份验证构建CRUD应用程序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 联想电脑网线怎么接(联想电脑网线接口什么
- 下一篇: 沧田打印机不打印是什么原因(沧田打印机无