Spring Boot+Angular 5+Spring Data+ Rest事例(CRUD)

java技术文章

2018-11-29

78

0

这篇文章提供了一个用Spring boot,Angular 5和spring data构建一个端到端单页面java web应用程序事例。我们将使用spring boot1.5提供一个rest apis和用带有路由功能的angular5构建从服务端调用服务的客户端。同时,我们将使用后端代码集成mysql数据库进行crud操作。我们将使用angular CLI去生成angular项目并且spring boot初始化软件去生成spring boot项目。在这边文章的最后,你将构建一个带有crud操作的用户管理应用程序,且你能选择发布到一个单独的tomcat或者部署客户端和服务端到跨源请求的不同服务上。

Angular 7于2018年10月发布并且这里有一个Angular 7的事例Angular 7 full stack App example with Spring Boot.

在下一章节中,我们将流量不同方法用maven共同打包spring boot和angular 5 应用《different ways to package spring boot and angular 5 application》成一个war包和部署到单独的tomcat。你也可能对这个集成应用感兴趣:《Angular5 JWT Authentication with Spring Boot Security》。

最后的angular版本为6并且这里有一个事例《CRUD Example with Angular 6

Table of Contents
1. Angular 5 Features 
2. Environment Setup
2.1 Angular 5 Environment SetUp
2.2 Spring Boot Environment SetUp
3. Default Files Generated by CLI command
4. Spring Boot Implementation
4.1 Spring Boot Rest APIs
4.2 Spring Boot Service Implementation
4.3 Spring Data Implementation
4.4 Spring Boot Datasource Configuration
5. Angular Implementation
5.1 Create Angular Component
5.2 Create Angular Views
5.3 Angular Routing
5.4 Angular Module
6 Angular CLI Proxy Configuration
7. Running Spring Boot Application
8. Running Angular App

Angular 5 特性

1、Angular 5 更快,更轻和容易使用。

2、组件设计灵活并且改进优化了编译构建

3、新的HttpClientModule 被引进,它完全重写了已经存在的HttpModule。

4、支持TypeScript 2.4

5、支持响应表单。

环境安装

我们将要构建的应用存在客户端和服务端两部分,因此,环境安装指的就是客户端和服务端。

Angular 5环境安装

这里我们将有一个简单的angular项目安装,看看这边文章angular 5 项目集成组件设计《integrate material design in angular 5 project》。Angular 5提供了一个漂亮的工具- Angular CLI。这里我们将使用同一个工具生成一个简单angular app并且修改它匹配我们的环境。为了使用Angular CLI,需要安装node,因此我们需要使用NPM工具。你需要使用 node -v 检查下你的机器是否安装了node。在我的机器上显示如下结果:

如果没有安装,访问 NodeJs official website安装node,现在,如果已经安装,跳的到你的工作空间目录,并且执行如下命令安装angular cli 和生成一个简单的angular项目。

npm install -g @angular/cli
ng new portal-app
在做好这些后,你打开到工作目录,将看见angular cli生成包括所有文件和目录的portal-app。现在你就可以打开你的编辑器导入当前项目。我导入这个项目到IntellijIdea,显示目录结构如下:
 

这里需要注意的是,如果你使用sudo命令安装你的NodeJs,接着你可能出现安装angular cli的权限问题。为了避免这些问题,通常推荐使用brew命令安装新的软件。

如果你遇到这些问题,接着给文件夹/usr/local/lib/node_modules 提供读写权限或者操作这里的命令-Mac Support

对于windows用户,你能使用git命令或者cygwin 命令安装。

Spring boot 环境安装

Spring boot团队提供了一个初始化软件构造spring boot环境。打开这个地址:https://start.spring.io/ 并且生成如下项目。

现在解压user-portal.zip和导入到java IDE.项目结构如下:

通过CLI命令生成默认文件

现在我们试图去生成理解不同文件。

Modules-模块将应用程序分解到逻辑代码块。每一个代码块和模型被设计成执行单一任务的模块。所有模块被main.ts加载。

Component-组件常常和模块一起使用。

tsconfig.json-存在目录中的tsconfig.json文件表明目录是typescript 项目的根目录。这个文件指定了根文件和typescript 编译运行所需的typescript文件。

package.json-它包括了angular项目定义的所有依赖。一旦我们安装nom,这些依赖将自动下载。

karma.conf.json- karma单元测试配置文件。

.angular-cli.json 将有所有所有的应用配置,诸如关于root的信息和输出目录。欢迎或者沿用主要ts文件的主要html文件。所有环境的其他相关信息将表现在这里。

 

现在是时候运行默认生成应用并且在浏览器中查看。如果你使用IntellijIdea,接着你从末端能运行ng 服务命令,不然的话,在末端敲下如下命令。

cd portal-app
 ng serve

之后打开你的浏览器,输入如下URL http://localhost:4200/并且angular app已经启动。现在我们能启动修改app创建了用户管理入口。

Spring Boot Rest APIs

现在,让我们开始创建我们的第一个APIs。我们有一个UerController包括暴露CRUD操作的所有APIs。@CrossOrigin通常允许跨源资源分享,因此我们的angular应用运行在不同的服务器上,并且可以从浏览器中请求这些APIs。我们也可以在angular端使用proxy.config.json配置代理,这里讲在下一章节讨论。

UserController.java
package com.devglan.userportal;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
@RestController
@RequestMapping({"/api"})
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public User create(@RequestBody User user){
        return userService.create(user);
    }

    @GetMapping(path = {"/{id}"})
    public User findOne(@PathVariable("id") int id){
        return userService.findById(id);
    }

    @PutMapping
    public User update(@RequestBody User user){
        return userService.update(user);
    }

    @DeleteMapping(path ={"/{id}"})
    public User delete(@PathVariable("id") int id) {
        return userService.delete(id);
    }

    @GetMapping
    public List findAll(){
        return userService.findAll();
    }
}
Spring Boot Service实现
这个服务类这里没有额外的逻辑和一个非常简单的实现
UserServiceImpl.java
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository repository;

    @Override
    public User create(User user) {
        return repository.save(user);
    }

    @Override
    public User delete(int id) {
        User user = findById(id);
        if(user != null){
            repository.delete(user);
        }
        return user;
    }

    @Override
    public List findAll() {
        return repository.findAll();
    }

    @Override
    public User findById(int id) {
        return repository.findOne(id);
    }

    @Override
    public User update(User user) {
        return null;
    }
}

Spring Data实现

我们将使用spring data实现ORM相关解决方案。想知道Spring data内部实现,你可以访问我的其他文章- Spring Boot JPAand Spring Boot Hibernate implementation.

UserRepository.java
package com.devglan.userportal;

import org.springframework.data.repository.Repository;

import java.util.List;

public interface UserRepository extends Repository {

    void delete(User user);

    List findAll();

    User findOne(int id);

    User save(User user);
}
Spring Boot Datasource 配置

application.properties
server.contextPath=/user-portal
spring.datasource.url=jdbc:mysql://localhost:3306/testdb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
默认的Scripts
CREATE TABLE user(id INT NOT NULL AUTO_INCREMENT,email VARCHAR(255),first_name  VARCHAR(255),last_name VARCHAR(255),PRIMARY KEY (id))ENGINE=InnoDB;
创建Angular组件
Angular CLI 生成命令创建组件。输入命令ng生成组件用户ng generate component user并且它将创建一个用户目录在app文件。这个用户文件将有所有用户所需要的文件。
 
首先我们将对用户列表修改app.component.html去包括两个链接和添加用户。所有我们的视图将加载到router-outlet中。
app.component.html

Welcome to !

List Users Add User

因此,我们有两个路由定义在上面,我们需要两个不同的试图user.component.html, add-user.component.html和每次点击的渲染组件。现在让我们实现 user.component.ts的代码。这里,当组件被调用时方法ngOnInit() 将被调用并且它将获取所有的用户记录和并且HTML页面数据将被填充。

user.compnent.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import { User } from '../models/user.model';
import { UserService } from './user.service';

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styles: []
})
export class UserComponent implements OnInit {

  users: User[];

  constructor(private router: Router, private userService: UserService) {

  }

  ngOnInit() {
    this.userService.getUsers()
      .subscribe( data => {
        this.users = data;
      });
  };

  deleteUser(user: User): void {
    this.userService.deleteUser(user)
      .subscribe( data => {
        this.users = this.users.filter(u => u !== user);
      })
  };

}
类似的我们有add-user.component.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router';

import { User } from '../models/user.model';
import { UserService } from './user.service';

@Component({
  templateUrl: './add-user.component.html'
})
export class AddUserComponent {

  user: User = new User();

  constructor(private router: Router, private userService: UserService) {

  }

  createUser(): void {
    this.userService.createUser(this.user)
        .subscribe( data => {
          alert("User created successfully.");
        });

  };

}
user.model.ts
export class User {

  id: string;
  firstName: string;
  lastName: string;
  email: string;
}
user.service.ts
import {Injectable} from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

import { User } from '../models/user.model';


const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

@Injectable()
export class UserService {

  constructor(private http:HttpClient) {}

  //private userUrl = 'http://localhost:8080/user-portal/user';
	private userUrl = '/api';

  public getUsers() {
    return this.http.get<User[]>(this.userUrl);
  }

  public deleteUser(user) {
    return this.http.delete(this.userUrl + "/"+ user.id);
  }

  public createUser(user) {
    return this.http.post(this.userUrl, user);
  }

}

创建一个Angular视图

作为讨论,我们将有两个视图user.component.html和add-user.component.html

user.component.html

User Details

FirstName LastName Email Action
     
add-user.component.html

Add User

Angular路由
现在是时候在angular配置路由。在这个配置中,我们将配置路径和跳转到各种视图的相对于组件。下面是我们的路由配置:
app.routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { UserComponent } from './user/user.component';
import {AddUserComponent} from './user/add-user.component';

const routes: Routes = [
  { path: 'users', component: UserComponent },
  { path: 'add', component: AddUserComponent }
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes)
  ],
  exports: [
    RouterModule
  ],
  declarations: []
})
export class AppRoutingModule { }
Angular模型
现在我们大部分已经完成我们的应用,我们仅仅需要包括所有的实现到我们的主module中。
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { UserComponent } from './user/user.component';
import { AppRoutingModule } from './app.routing.module';
import {UserService} from './user/user.service';
import {HttpClientModule} from "@angular/common/http";
import {AddUserComponent} from './user/add-user.component';

@NgModule({
  declarations: [
    AppComponent,
    UserComponent,
    AddUserComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    FormsModule
  ],
  providers: [UserService],
  bootstrap: [AppComponent]
})
export class AppModule { }
Angular CLI代理配置
为了在angular cli中配置代理,我们需要在angular项目的根目录创建代理proxy.config.json文件和在package.json中编辑启动脚本。
proxy.config.json
{
  "/api/*": {
    "target": "http://localhost:8080/user-portal",
    "secure": false
  }
}
这里的目标值是应用根目录的上下文和用户API终端API。
package.json
"start": "ng serve --proxy-config proxy.config.json",
这样做,这个请求http://localhost:4200/api将被代理到 http://localhost:8080/user-portal.
 
 
修复上面的错误,在package.json中替换"@angular/cli": "1.6.3", with "@angular/cli": "^1.6.3"并且运行npm更新。之后就能正常工作了。
现在确信在user.service.ts文件中改变userUrl 到'/api'并且在UserController.java中添加@CrossOrigin注解。一旦这样做后,使用ng服务--代理配置proxy.config.json或者npm start启动angular app。
 
最终Application 结构
 
运行Spring boot应用
我们将使用spring boot嵌入到tomcat部署应用。对于更多的描述,请看这里 check this.
UserPortalApplication.java
package com.devglan.userportal;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class UserPortalApplication {

	public static void main(String[] args) {
		SpringApplication.run(UserPortalApplication.class, args);
	}
}
运行Angular app
现在服务已经启动,输入命令ng serve去部署angular 应用并且测试应用
输入URL http://localhost:4200/ ,你讲看到如下内容:
现在,点击添加用户连接,将看到如下内容:
现在,点击用户列表之后的添加多用户
 
 
结论:
这是一个非常漂亮的关于spring boot和angular 5教程。在下一章节,我们将看再maven和tomcat中部署应用程序《 deploying this application 》。你可以下载从这里下载源代码《 here》。如果时间允许,我们将试图用它集成spring security。
 

发表评论

全部评论:0条

鸿福951

努力打造一个好用的webui

热评文章

推荐文章