乐趣区

关于java:全栈教程Spring-Boot-和-Vuejs-入门

在本教程中,你将创立一个 CoffeeBot 应用程序。该应用程序就像机器人咖啡机的控制器。遗憾的是,它实际上不会为你提供咖啡,但它将演示大量有用的编程技术。该应用程序将有一个 Vue.js 客户端和一个 Spring Boot 资源服务器。它将应用 JHipster 进行疏导,节俭大量工夫并演示一些最佳实际,包含在客户端和服务器中主动配置端到端 JWT 身份验证。你还将应用 Split 来展现如何别离应用 Split 的 Javascript SDK 和 Java SDK 在运行时动静地应用性能标记来治理前端和后端的功能集。
该应用程序自身提供饮料。服务器保护着一份饮料清单,次要是咖啡,附有尺寸、价格和名称。为简略起见,饮料列表将应用内存中的开发数据库进行保留,但如果须要,能够轻松地重新配置以实现持久性。客户端从服务器申请饮料列表,如果用户通过身份验证,则传递任何身份验证数据。

客户端接管此列表并将饮料列表显示为按钮列表。第二次宰割纯正与客户无关。增加了一项新性能:可能在饮料中增加奶油。正如你能够设想的那样,思考到人们对咖啡中奶油的青睐水平,虚构骚乱曾经开始要求此性能。人们在叫嚷。但经理们心愿在宽泛公布之前确保奶油性能失常工作(CoffeeBot 有时会失灵)。因而,依据通过身份验证的用户,增加奶油的能力被切换。你能够在这个链接:

看到如何应用 Split 的 Javascript SDK 来管制客户端的奶油性能,以及如何应用 Split 的 Java SDK 来管制服务器的饮料列表

Java + Vue.js 教程依赖项

Java: 我在本教程中应用了 Java 12。你能够拜访 AdaptOpenJdk 网站下载并装置 Java。或者你能够应用 SDKMAN 甚至 Homebrew 等版本管理器。

Node: 依照 Node 网站上的阐明装置 Node。本教程是应用 Node 12.14.0 编写的。

JHipster: 一旦装置了 Java 和 Node,就能够装置 JHipster。依照其网站上的阐明进行操作(如果呈现问题,有助于排除故障)或只需运行此命令:npm install -g generator-jhipster@6.9.0 应用 npm.

拆分:如果你还没有收费的拆分帐户,请注册一个。这就是实现性能标记的形式。

应用 JHipster 疏导你的 Spring Boot 应用程序

要创立示例 CoffeBot 应用程序,你将应用 JHipster。正如其网站上所述,“JHipster 是一个疾速生成、开发和部署古代 Web 应用程序和微服务架构的开发平台。”它容许你疾速启动具备各种前端和服务器配置的基于 Java 的我的项目。本教程将应用 Vue.js。

JHipster 的长处之一是它为你创立了一个蕴含 Java 服务器应用程序和 Vue.js 前端应用程序的组合我的项目。它还包含将创立数据模型实体和 Web 服务控制器的生成器。它做了很多事件并创立了很多文件。如果你对这些平台绝对生疏,那么我的项目构造可能看起来有点令人难以承受,但他们在网站上记录了所有内容,做得很好。他们安排的我的项目遵循以后的最佳实际,因而它是一个很好的学习工具。

关上 shell 并为你的我的项目创立一个根目录,例如 CoffeeBotApp. 导航到该目录。你将在此处生成我的项目文件。

通常,当你运行 JHipster 时,它会询问你许多无关你正在疏导的我的项目的问题。然而,为了简化事件,你将应用此.yo-rc.json 文件来事后配置我的项目,从而绕过询问。
在根我的项目目录中,创立一个.yo-rc.json 蕴含以下内容的文件。此配置的一些亮点是:

applicationType: 整体应用程序:典型的规范应用程序(实质上不是微服务)

baseName : coffeebot– 应用程序的名称

packageName : com.split.coffeebot– 根底 Java 包

authenticationType : jwt– JSON Web 令牌身份验证

devDatabaseType : h2Memory– 开发数据库应用内存中的 H2 数据库,该数据库不会跨会话长久化

clientFramework : vue– 应用 Vue.js 作为前端客户端框架

SkipFakeData : true– JHipster 默认状况下会为数据模型生成一组随机的假数据,咱们心愿在本教程中跳过这些数据

有很多抉择。请参阅文档以深刻理解这一点。

{
  "generator-jhipster": {
    "promptValues": {"packageName": "com.split.coffeebot"},
    "jhipsterVersion": "6.9.0",
    "applicationType": "monolith",
    "baseName": "coffeebot",
    "packageName": "com.split.coffeebot",
    "packageFolder": "com/split/coffeebot",
    "serverPort": "8080",
    "authenticationType": "jwt",
    "cacheProvider": "ehcache",
    "enableHibernateCache": true,
    "websocket": false,
    "databaseType": "sql",
    "devDatabaseType": "h2Memory",
    "prodDatabaseType": "mysql",
    "searchEngine": false,
    "messageBroker": false,
    "serviceDiscoveryType": false,
    "buildTool": "gradle",
    "enableSwaggerCodegen": false,
    "jwtSecretKey": "ZDg4ZjkzMDJkNWQ4YWJlMjUxOTY3YjE1MDNjY2ZkMzJjYWQwYjJiOTkyMWQ3YTE5ZTgwNWY3Y2E1ZDg0OWViZjM0Nzg1NDE3MjNlMGY1MDBkNTg4YWU1MmZmNTU1ZGEzOTJiMTVlMWZjZDc5NDUyMTlmZmRmYTU0NDJjMDdiODA=",
    "embeddableLaunchScript": false,
    "useSass": true,
    "clientPackageManager": "npm",
    "clientFramework": "vue",
    "clientTheme": "none",
    "clientThemeVariant": "","creationTimestamp": 1601147759112,"testFrameworks": [],"jhiPrefix":"jhi","entitySuffix":"",
    "dtoSuffix": "DTO",
    "otherModules": [
      {
        "name": "generator-jhipster-vuejs",
        "version": "1.8.0"
      }
    ],
    "enableTranslation": false,
    "blueprints": [
      {
        "name": "generator-jhipster-vuejs",
        "version": "1.8.0"
      }
    ],
    "skipFakeData": true
  }
}

通过运行以下命令(在蕴含该文件的根我的项目目录中.yo-rc.json)创立入门应用程序。

jhipster

当 JHipster 创立我的项目时,你将看到大量控制台输入。它应该以以下行完结。

INFO! Congratulations, JHipster execution is complete!

代码语言:Swift(斯威夫特)
JHipster 曾经创立了一个 Git 存储库并进行了初始提交。此时,你能够通过关上两个 shell(一个用于客户端,一个用于服务器)并运行以下命令来运行入门应用程序。

Spring Boot 服务器:

./gradlew

Vue.js 客户端:

npm start

生成 Spring Boot 数据模型

当初你想要应用 JHipster 生成数据模型或实体。它们定义了将存储在数据库中并由 REST 服务提供服务的数据结构。当你应用 JHipster 的生成器创立实体时,JHipster 和 Spring 会为你实现许多杰出的幕后工作。它创立示意数据结构的 Java 类,并应用容许将数据保留到数据库的 JPA 正文进行正文。它还创立一个实现创立、读取、更新和删除 (CRUD) 性能的资源文件,该文件会主动受到所选身份验证计划(在咱们的示例中为 JWT)的爱护。

在前端,生成器创立必要的文件,容许你与实体的资源服务器进行交互,以及前端文件来创立、更新和查看持久数据实体(要拜访它,你必须以管理员用户身份登录)。

在我的项目根目录中,创立一个新文件:entities.jdl. 该文件定义了一种具备四个属性的实体类型,以及该实体中应用的枚举类型。

enum DrinkSize {
    Small,
    Medium,
    Large,
    XLarge,
    XXLarge
}

entity Drink {
    name String required,
    size DrinkSize required,
    caffeineMilligrams Integer required,
    priceDollars Integer required,
}

通过运行生成实体文件:

jhipster import-jdl entities.jdl

当它询问你是否覆盖文件时,只需键入 ato overwrite this and all others。

当初是运行入门应用程序并摸索疏导性能的好时机。请记住,你须要运行两个不同的过程。

Spring Boot Java 服务器 `

./gradlew

Vue.js 客户端(你可能须要期待一分钟左右服务器能力实现运行):

npm start

客户端应用程序应主动关上。如果没有,请关上 http://localhost:9000

应用默认凭据以管理员用户身份登录 admin:admin。查看“治理”菜单下的所有性能。另请查看“实体”菜单。你能够在此处查看、增加和更新你创立的实体。在咱们的例子中,这是 Drink 实体,它有四个属性:name、size、caffeine mgs 和 Price Dollars。
Vue.js 客户端应用 TypeScript 和类组件,并将模板和组件申明拆分为两个独自的文件。如果你习惯于更传统的.vue 单文件构造,一开始这可能看起来有点奇怪,但大多数差别都是不言自明的。如果你须要帮忙,请查看文档中的官网页面以获取更多信息。

将性能标记增加到你的 Spring Boot Java 服务器

你将应用 Split 在客户端和服务器上实现性能标记。你应该曾经注册了一个收费帐户(如果没有,请立刻注册)。目前,你要将 Java Split SDK 集成到 Spring Boot 应用程序中。我将疏导你实现此过程,但如果你须要更多信息或遇到麻烦,请查看他们的 Java SDK 文档。

首先,将 Split 依赖增加到 build.gradle 文件中(在我的项目根目录中)。该 build.gradle 文件蕴含大量内容。只需在开端左近增加以下行,就在开始的正文行上方 //jhipster-needle-gradle-dependency。

dependencies {
    ....
    compile 'io.split.client:java-client:4.0.1'
    //jhipster-needle-gradle-dependency - JHipster will add additional dependencies here
}

你将须要你的 Split API 密钥。关上你的拆分仪表板。通过转到仪表板左上角的方形工作区图标(可能显示默认为 DE)找到 API 密钥,单击它,而后单击 Admin Settings。单击左侧面板中“工作区设置”下的“API 密钥”。
你将看到已创立四个 API 密钥,其中两个用于生产,两个用于暂存。服务器端 SDK 应用和客户端 Javascript 应用有不同的密钥。SDK 和 staging-default 密钥是你稍后须要的。

将 API 密钥增加到配置文件的开端 application.yml。
src/main/resources/application.yml

#application:
split:
    api-key: <yourSplitApiKey> 代码语言:小黄瓜(gherkin)

我只是指出,在这里你将其增加到全局配置文件中,但在更理论的用例中,你可能会应用两个不同的 API 密钥,一个用于暂存和生产,别离将它们增加到 和 application-dev.yml 文件 application-prod.yml 中。

创立一个名为 的 Java 文件,SplitConfig.java 该文件将在 Spring Boot 应用程序中配置 Split 客户端。它创立了一个可用于依赖注入的 Spring Bean,并且因为 Bean 的默认行为是创立一个单例实例,因而这与 Split 本人的领导统一,倡议只创立一个客户端实例。

src/main/java/com/split/coffeebot/config/SplitConfig.java

@Configurationpublic class SplitConfig {@Value("#{ @environment['split.api-key'] }")
    private String splitApiKey;
    @Bean
    public SplitClient splitClient() throws Exception {SplitClientConfig config = SplitClientConfig.builder()
                .setBlockUntilReadyTimeout(1000)
                .enableDebug()
                .build();
        SplitFactory splitFactory = SplitFactoryBuilder.build(splitApiKey, config);
        SplitClient client = splitFactory.client();
        client.blockUntilReady();
        return client;
    }
}

你还须要向 DrinkRepository. 它 JPARepository 为你提供了相当多的性能,无需任何自定义,但在这个应用程序中,你将须要一个自定义办法,该办法容许你从规范办法中排除一些饮料 findAll()。该办法 findByNameNotIn() 是一个 JPA 查询方法,其语法和实现由 Spring Boot 提供。你所要做的就是定义方法以使其可供使用。无关更多信息,请参阅 Spring Data JPA 查询方法的文档。

src/main/java/com/split/coffeebot/repository/DrinkRepository.java

@SuppressWarnings("unused")  @Repository  public interface DrinkRepository extends JpaRepository<Drink, Long> {List<Drink> findByNameNotIn(Collection<String> names);  
}

当初创立一个 CoffeeBotResource.java 文件,其中蕴含 CoffeeBot 应用程序的业务逻辑和 REST 端点。

src/main/java/com/split/coffeebot/web/rest/CoffeeBotResource.java

package com.split.coffeebot.web.rest;
…
@RestController
@RequestMapping("/api/coffee-bot")public class CoffeeBotResource {private final Logger log = LoggerFactory.getLogger(CoffeeBotResource.class);
    SplitClient splitClient;
    DrinkRepository drinkRepository;
    public CoffeeBotResource(SplitClient splitClient, DrinkRepository drinkRepository) {
        this.splitClient = splitClient;
        this.drinkRepository = drinkRepository;
    }
    private Drink makeDrink(String name, DrinkSize size, Integer caffeineMg, Integer price) {Drink drink = new Drink();
        drink.setCaffeineMilligrams(caffeineMg);
        drink.setName(name);
        drink.setSize(size);
        drink.setPriceDollars(price);
        return drink;
    }
    @EventListener
    public void onApplicationEvent(ContextRefreshedEvent event) {drinkRepository.save(makeDrink("Water", DrinkSize.Small, 0, 1));
        drinkRepository.save(makeDrink("Soda", DrinkSize.Medium, 30, 3));
        drinkRepository.save(makeDrink("Coffee", DrinkSize.XLarge, 50, 5));
        drinkRepository.save(makeDrink("Coffee", DrinkSize.Small, 30, 3));
        drinkRepository.save(makeDrink("Coffee", DrinkSize.Medium, 40, 3));
        drinkRepository.save(makeDrink("Latte", DrinkSize.Large, 100, 8));
        drinkRepository.save(makeDrink("Latte", DrinkSize.Small, 80, 6));
        drinkRepository.save(makeDrink("Latte", DrinkSize.Medium, 60, 5));
    }
    @GetMapping("/list-drinks")
    public List<Drink> listDrinks() {Optional<String> userName = SecurityUtils.getCurrentUserLogin();
        String treatment = splitClient.getTreatment(userName.get(),"drink-types");
        if (treatment.equals("on")) {return drinkRepository.findAll();
        }
        else {return drinkRepository.findByNameNotIn(Arrays.asList("Latte", "Soda"));
        }
    }
}

和办法作为辅助办法,用于在应用程序启动时创立一些示例 makeDrink() 数据 onApplicationEvent()(请记住,它应用的是内存数据库,不会在会话之间保留任何数据)。

该类应用 Spring 的依赖注入来使两个对象可用:DrinkRepository,这是主动创立的接口,定义应用程序如何操作实体(饮料);,SplitClient 它是负责与 Split 通信并获取给定密钥和医治名称的医治的客户端。

你很快就会创立这种医治办法。当初,请留神该 getTreatment() 办法至多须要两个参数。一种是文本键,它是任意字符串值,通常是用户名、帐户 ID 或用于辨别用户的另一个惟一键。另一个是宰割名称,它指定应用哪种解决来进行宰割。

业余提醒:可选的第三个 getTreatment 参数(咱们在这里不会应用)是一个属性 映射对象,蕴含名称 - 值对中的用户属性。即便是敏感的用户数据也能够在此映射中传递,因为这些数据都不会发送到斯普利特的云。相同,属性映射会在本地内存中与你在拆分 UI 中输出的定位规定进行比拟。更多内容请参见 Split SDK 文档:应用属性映射进行自定义定位。

如果医治是 on,它会返回所有可用的饮料。如果解决不是 on(off 或 control 或任何其余值),则返回除 Latte 和之外的所有饮料 Soda。这演示了一种基于拆分来分叉代码的简略办法。更简单的宰割和医治用例是可能的。
在你搬家之前,最初一项扭转。关上 SecurityConfiguration 文件并容许 api/coffee-bot 资源门路上的所有流量。这将容许匿名用户取得饮料清单。

你要增加这一行:

.antMatchers("/api/coffee-bot/**").permitAll()  代码语言:Bash(bash)

至 configure(HttpSecurity http) 办法。立场很重要。该行须要增加到该.antMatchers(“/api/**”).authenticated() 行之前。

src/main/java/com/split/coffeebot/config/SecurityConfiguration.java

@Overridepublic void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http
    ...
    .and()
        .authorizeRequests()
        .antMatchers("/api/authenticate").permitAll()
        .antMatchers("/api/register").permitAll()
        .antMatchers("/api/activate").permitAll()
        .antMatchers("/api/account/reset-password/init").permitAll()
        .antMatchers("/api/account/reset-password/finish").permitAll()
        .antMatchers("/api/coffee-bot/**").permitAll()
        .antMatchers("/api/**").authenticated()
        .antMatchers("/management/health").permitAll()
        .antMatchers("/management/info").permitAll()
        .antMatchers("/management/prometheus").permitAll()
        .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
    ...
    // @formatter:on
}

创立特色标记解决

如果你对医治和 Split 不相熟,你可能须要浏览 Split 网站上的入门信息。简而言之,宰割定义了一个决策点,一个标记,能够在代码中应用它来批改出现给一组用户的性能。键(以及可选的属性映射)是依据拆分中定义的规定确定标记状态的值。这个决定是在运行时调用该办法时做出的。SplitClientgetTreatment()

在咱们非常简单的示例中,你将创立一个名为 Drink-types 的拆分。这个宰割将是一个简略的开 / 关宰割,就像一个布尔标记(除了开和关之外,还能够有多个值)。宰割将默认为 off,但 on 如果 admin 用户在场,则宰割将变为。这是一个十分童稚的例子。举个例子,在生产中,你能够依据用户群的一部分来定义这种划分,以在细分中推出新性能;或者,你能够先将性能仅提供给公共 Beta 测试人员,而后再将其公布给整个用户群。
关上拆分仪表板。你应该位于默认工作区中。

单击左侧的“拆分”。

单击蓝色的“创立拆分”按钮。

为宰割命名:drink-types。你能够将其余部分留空。

单击创立。

从环境下拉列表中抉择暂存 - 默认。

单击增加规定按钮。

请留神,在定义解决局部下,定义了两个值:on 和 off。对于咱们的用例来说,这十分棒。

在“创立单个指标”下,单击“增加指标”按钮。增加名为 的用户 admin。这意味着用户 admin 将受到医治 on。

单击面板右上角的保留更改。

单击下一个面板上的“确认”以确认更改。

更新 Vue.js 客户端应用程序

客户端代码应用 axios 向资源服务器发出请求。你还须要装置 Split 模块依赖项。从我的项目根目录增加依赖项。

npm install --save axios @splitsoftware/splitio@10.14.2

更新 home.component.ts 文件以创立 CoffeeBot 应用程序。你须要为上面代码中的地位增加 Javascript – staging-default 键。const SPLIT_AUTH_KEY<yourStagingSplitAuthKey>
src/main/webapp/app/core/home/home.component.ts

import Component from 'vue-class-component';
import {Inject, Vue, Watch} from 'vue-property-decorator';
import LoginService from '@/account/login.service';
import {SplitFactory} from '@splitsoftware/splitio';
import {IClient} from '@splitsoftware/splitio/types/splitio';
import axios from 'axios';const SPLIT_AUTH_KEY = <yourSplitAuthKey>;
@Component
export default class Home extends Vue {@Inject('loginService')
  private loginService: () => LoginService;
  private splitClient: IClient = null;
  // our list of drinks
  private drinks = [];
  // holds the drink that is the current order
  private currentOrder = null;
  // cream or no cream?
  private withCream = false;
  // the current Split.io treatment
  private treatment = null;
  public openLogin(): void {this.loginService().openLogin((<any>this).$root);
  }
  public get authenticated(): boolean {return this.$store.getters.authenticated;}
  public get username(): string {return this.$store.getters.account ? this.$store.getters.account.login : '';}
  async getTreatment() {
    // create a configured SplitFactory
    const splitFactory = SplitFactory({
      core: {
        authorizationKey: SPLIT_AUTH_KEY,  // your Split.io auth key
        key: this.username,  // identifier for this treatment (username in this case)
        trafficType: 'user'
      },
      startup: {readyTimeout: 1.5 // 1.5 sec}
    });
    // create the split client (NOT READY TO USE YET)
    this.splitClient = splitFactory.client();
    // block untli the client is ready
    this.splitClient.on(this.splitClient.Event.SDK_READY, function() {
      // client is ready, get the treatment
      this.treatment = this.splitClient.getTreatment('drink-types');
    }.bind(this));
  }
  // triggered when username changes to update list
  // of drinks and Split.io treatment
  @Watch('username')
  async usernameChanged(newVal: string, oldVal: String) {
    // get treatment from split.io
    await this.getTreatment();
    // call the REST service to load drinks
    await this.loadDrinks();
        // clear the current order
        this.currentOrder = null;
  }
  async loadDrinks() {const response = await axios.get('http://localhost:8080/api/coffee-bot/list-drinks');
    console.log(response);
    if (response && response.status === 200) {this.drinks = response.data;}
    else {this.drinks = [];
    }
  }
  async mounted() {await this.getTreatment();
    await this.loadDrinks();}
  beforeDestroy() {this.splitClient.destroy();
  }
}

该组件的身份验证局部是通过 JHipster 疏导程序收费提供的。通过该办法从 Spring Boot 资源服务器加载数据 loadDrinks(),该办法只是将饮料存储在本地数组中,奇妙地称为 drinks. 当装置组件和用户更改时(因为可用的饮料取决于医治,而医治由用户决定),则会调用此办法。你可能会留神到此办法没有传递用户名。这是因为用户名会主动通过 JWT(JSON Web 令牌)传递到服务器,由 Spring Security 解决,身份验证代码由 JHipster 疏导。

另一个重要的函数是 usernameChanged() 办法,当属性更改时调用该办法 username。每次有新用户时,都须要创立新的 Split 客户端并从新加载解决。你还须要从服务器从新加载饮料。这个办法解决所有这些。

请留神此处的个别流程。首先,SplitFactory 应用宰割身份验证密钥和新用户名配置 a。该 SplitFactory 实例用于创立 SplitClient 实例。然而,客户此时不肯定筹备好。该代码会阻塞,直到 SDK_READY 事件被触发(参见上面的代码),而后才尝试从 获取解决 SplitClient,否则它将仅返回 control 解决。

// block until SDK is readythis.splitClient.on(this.splitClient.Event.SDK_READY, function () {
  // ready now, so get treatment
  this.treatment = this.splitClient.getTreatment('drink-types');
}.bind(this))

home.vue 当初更新与该组件对应的模板文件。

src/main/webapp/app/core/home/home.vue

<template>
    <div class="container">
        <div class="home row justify-content-md-center">
            <div class="col-md-6">
                <div class="title">
                    <h1 class="display-4">CoffeeBot!</h1>
                    <p class="lead">Drink coffee!</p>
                    <p>{{username ? username : "anonymous"}}, treatment: {{treatment}}</p>
                </div>

                <div v-for="drink in drinks">
                    <b-button variant="outline-primary" class="menu-button" @click="currentOrder=drink">{{drink.name}} {{drink.size}} - ${{drink.priceDollars}}</b-button>
                </div>

                <div v-if="currentOrder !== null">

                    <div v-if="treatment==='on'">
                        <b-button v-if="!withCream" variant="success" class="menu-button" @click="withCream=true">Add Cream - FREE</b-button>
                        <b-button v-if="withCream" variant="danger" class="menu-button" @click="withCream=false">Remove Cream</b-button>
                    </div>

                    <div class="card order">
                        <h4>Current order:</h4>
                        <div>
                            {{currentOrder.name}} {{currentOrder.size}} {{withCream ? "(w/ cream)" : ""}} - ${{currentOrder.priceDollars}}
                        </div>
                    </div>
                </div>

            </div>
        </div>
    </div></template>
<script lang="ts" src="./home.component.ts"></script>
<style>
    .menu-button {
        margin-bottom: 10px;
        width: 100%;
    }
    .order {
        text-align: center;
        padding:20px;
    }
    .title h1, .title p {text-align: center;}</style>

请留神,该文件应用 Vue 的条件语法依据解决状态有条件地渲染增加和删除奶油按钮。在这种状况下,即便组件中有一些与增加和删除奶油性能相干的代码未切换,这就是咱们治理性能状态所须要做的全副工作。

<div v-if="treatment==='on'">
    <b-button v-if="!withCream" variant="success" class="menu-button" @click="withCream=true">Add Cream - FREE</b-button>
    <b-button v-if="withCream" variant="danger" class="menu-button" @click="withCream=false">Remove Cream</b-button></div>

尝试实现的 Spring Boot + Vue.js 教程应用程序

你当初能够尝试实现的应用程序。启动或重新启动服务器和客户端。你可能心愿在启动客户端之前让服务器实现启动。

Spring Boot Java 服务器:

./gradlew

Vue.js 客户端:

npm start

客户端应用程序应主动关上。如果没有,请关上 http://localhost:9000

当你第一次加载应用程序时,你会看到用户是 anonymous 并且医治是对照医治。

应用默认管理员凭据 () 登录 admin:admin,你将看到扩大的饮料列表。当你增加一个饮料时,你会看到一个名为 ”Add Cream” 的按钮。该按钮的可见性或性能可能受到名为 ”split treatment” 的解决形式的管制。换句话说,依据某种宰割解决的规定或逻辑,决定了是否显示或启用这个 ”Add Cream” 按钮。

登记并以默认用户 (user:user) 身份登录,你将看到解决形式,并且 off 你将取得与该用户雷同的饮料列表 anonymous。此外,你无奈抉择增加奶油。

理解无关 Spring Boot、性能标记和生产中测试的更多信息

在本教程中,你创立了一个全栈应用程序,其中包含 Vue.js 客户端和 Spring Boot 资源服务器。Vue.js 客户端应用 TypeScript 进行更古代、无谬误的开发(因为如果应用切当,类型查看能够大大减少运行时谬误)。Spring Boot 服务器应用 Spring Security 和 Spring JPA 等技术来疾速轻松地定义数据模型(或实体),将该实体的实例保留到数据库,并在 REST 接口中提供该数据。

客户端和服务器都应用 JWT 身份验证来爱护平安。Split 用于实现性能标记,在服务器端应用 Java SDK 实现拆分,在客户端应用 Javascript SDK 实现拆分。

所有这一切都是应用 JHipster 疏导的,这使得应用古代最佳实际和技术启动新的全栈我的项目变得非常容易。

你能够在 Split 的示例 GitHub 上找到所有设置的 JHipster 的残缺源代码。

退出移动版