Использование Vue+Spring Boot для реализации загрузки в Excel

задняя часть внешний интерфейс Excel Vue.js

Написано прежде всего

В предыдущем уроке мы представили вводный метод чтения и записи Excel и использования Selenium, а в этом выпуске мы представим функцию загрузки Excel и импорта тестовых сценариев в WebApp через Vue+Spring Boot. Технология разделения внешнего и внутреннего интерфейса используется, потому что она облегчает итерацию последующих функций.В этой статье мы задействуем только простой внешний интерфейс и простой внутренний сервис.

Отображаются текущие результаты и адрес исходного кода в конце статьи.Портал последнего выпуска:Автоматизация Java — использование Selenium+POI для автоматизации слов пакетного поиска в Excel

Список шагов

  1. Создайте интерфейсный проект с помощью Vue-Cli.
  2. Навигация по письму
  3. написание таблицы скриптов
  4. Создайте бэкэнд-проект с пружиной INATINALIZR
  5. Написание классов pojo
  6. Написание UploadController
  7. Написание UploadService
  8. Создание простого RESTful API
  9. Запускаем сервис, скрипт и загружаем

Начинай сейчас

  1. Создайте интерфейсный проект с помощью Vue-Cli.

    С помощью инструмента vue-cli можно легко создавать интерфейсные проекты, конечно, использование WebStorm для сборки будет более лаконичным (как показано на рисунке). В этой статье рекомендуется использовать WebStorm, потому что при последующей разработке IDE сделает нашу разработку более лаконичной. Часть конфигурации показана на рисунке:

  1. Навигация по письму

    Как веб-приложение, Navbar необходим как панель навигации приложения. В этом проекте автор представил бутстрап для простого создания Navbar. В vue нам нужно добавить наши компоненты в папку компонентов.Для этого проекта Navbar является первым компонентом, который мы хотим добавить.Он не зависит от маршрутизатора и всегда фиксируется в верхней части веб-страницы.

    2.1 Сначала мы используем npm для установки vue, vue-cli, bootstrap

    npm install vue
    npm install -g vue-cli
    npm install --save bootstrap jquery popper.js
    

    2.2 Затем мы создаем новый компонент vue в каталоге компонентов и вводим зависимости начальной загрузки в main.js:

    import 'bootstrap/dist/css/bootstrap.min.css'
    import 'bootstrap/dist/js/bootstrap.min'
    

    2.3 Теперь можно приступать к написанию кода. Поскольку эта статья посвящена только функциям, связанным с таблицами, все элементы на панели навигации, кроме скрипта, отключены. Код выглядит следующим образом:

<template>
  <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <span class="navbar-brand mb-0 h1">Vue-SpringBoot</span>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNav">
      <ul class="navbar-nav">
        <li class="nav-item">
          <router-link class="nav-link" to="/home">Home</router-link>
        </li>
        <li class="nav-item active">
          <router-link to="/" class="nav-link">Script</router-link>
        </li>
        <li class="nav-item">
          <router-link to="/history" class="nav-link">History</router-link>
        </li>
      </ul>
    </div>
  </nav>
</template>

<script>
    export default {
        name: "MyNavbar"
    }
</script>

<style scoped>

</style>

2.3 Представляем MyNavbar в App.vue

  1. Написание таблицы сценариев

    Неотъемлемой частью инструмента автоматизации является введение Script.Мы надеемся, что пользователи смогут свободно использовать интерфейс H5 для написания Script, поэтому мы используем двустороннюю привязку данных Vue для Table CRUD.

    3.1 Создайте новый компонент vue ScriptTable, код выглядит следующим образом:

<template>
  <div class="container-fluid" id="scriptTable">
    <h3>My Script</h3>
    <form style="margin-top: 1rem">
      <input type="file" @change="getFile($event)" class="" multiple/>
      <input type="button" value="upload" @click="submit($event)" class="btn btn-dark">
    </form>
    <table class="table table-hover text-center table-bordered"
           style="word-break: break-all; word-wrap: break-word;margin-top: 1rem;">
      <thead>
      <th>#</th>
      <th>Platform</th>
      <th>Action</th>
      <th>Path</th>
      <th>Value</th>
      <th>Wait</th>
      <th>Screenshot</th>
      <th>Change</th>
      </thead>
      <tbody>
      <tr v-cloak v-for="(item, index) in steps">
        <th>{{index+1}}</th>
        <td>{{item.platform}}</td>
        <td>{{item.action}}</td>
        <td>{{item.path}}</td>
        <td>{{item.value}}</td>
        <td>{{item.wait}}</td>
        <td>{{item.screenshot}}</td>
        <td><a href="#" v-on:click="edit(item)">Edit</a> | <a href="#" v-on:click='aaa(index)'>Delete</a>
        </td>
      </tr>
      <tr>
        <th></th>
        <td><select class="form-control" v-model="stepstemp.platform">
          <option>Web</option>
          <option>Android</option>
        </select></td>
        <td><select class="form-control" v-model="stepstemp.action">
          <option>click</option>
          <option>get</option>
          <option>input</option>
          <option>swipe</option>
        </select></td>
        <td><input class="form-control" v-model="stepstemp.path" placeholder="Enter the xPath"></td>
        <td><input class="form-control" v-model="stepstemp.value" placeholder="Enter the input value"></td>
        <td><input class="form-control" v-model="stepstemp.wait" placeholder="Waiting seconds"></td>
        <td><select class="form-control" v-model="stepstemp.screenshot">
          <option>yes</option>
          <option>no</option>
        </select></td>
        <td>
          <button class="btn btn-sm btn-dark" v-on:click='save' v-if="isNotEdit">Save</button>
          <button class="btn btn-sm btn-primary" v-on:click='saveEdit' v-else>SaveEdit</button>
        </td>
      </tr>
      </tbody>
    </table>
    <hr/>
  </div>
</template>

<script>
  import Vue from 'vue'
  import axios from 'axios'

  export default {
    name: "ScriptTable",
    data() {
      return ({
        steps: [],
        stepstemp: {
          platform: '',
          action: '',
          path: '',
          value: '',
          wait: '',
          screenshot: ''
        },
        isNotEdit: true
      });
    },
    methods: {
      save: function () {
        this.steps.push(this.stepstemp);
        this.stepstemp = {
          platform: '',
          action: '',
          path: '',
          value: '',
          wait: '',
          screenshot: ''
        };
      },
      aaa: function (index) {
        this.steps.splice(index, 1)
      },
      edit: function (item) {
        this.isNotEdit = false;
        this.stepstemp = item;
      },
      saveEdit: function () {
        this.isNotEdit = true;
        this.stepstemp = {
          platform: '',
          action: '',
          path: '',
          value: '',
          wait: '',
          screenshot: ''
        };
      }
    }
  }
</script>


<style scoped>

</style>

3.3 Запустите dev, откройте localhost:8080

npm run dev

Эффект передней страницы выглядит следующим образом:

На данный момент чистая часть интерфейса, связанная с этой статьей, почти завершена.После добавления фиктивных данных мы можем начать разработку серверной части.

  1. Создайте серверный проект с помощью Spring Initializr.

    Чтобы упростить создание проектов, создание RESTful API и более простую настройку обработки запросов, я выбрал Spring Boot в качестве серверной среды.

    4.1 Во-первых, мы используем встроенный в IDEA Spring Initializr для сборки проекта.Часть конфигурации показана на рисунке:

4.2 Затем введите зависимость poi в pom.xml и нажмите «Импортировать изменение». Следующее:

 <dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi-ooxml</artifactId>
     <version>4.0.0</version>
 </dependency>

4.3 Далее мы настраиваем server.port=8088 в application.properties отдельно от внешнего проекта.

  1. Написание класса pojo Шаг

    Далее следует подготовка класса pojo. В этой статье требуется только pojo — Step, который соответствует интерфейсной таблице. Код выглядит следующим образом:

import lombok.Data;
@Data
public class Step {
    private String platform;
    private String action;
    private String path;
    private String value;
    private int wait;
    private String screenshot;
}
  1. Написание UploadController

    Далее идет обработчик (контроллер) внешнего POST-запроса, мы загрузим этот POST-запрос, соответствующий «/uploadfile», обратите внимание на присоединение аннотаций @crossorigin для реализации кросс-доменного кода следующим образом:

package com.daniel.vuespringbootuploadbe;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

@Controller
@CrossOrigin
@ResponseBody
public class UploadController {

    private static String UPLOADED_FOLDER = "src/main/resources/static/temp/";

    @Autowired
    private LoadService loadService;

    @PostMapping("/upload")
    public List<Step> singleFileUpload(MultipartFile file) {
        try {
            // Get the file and save it somewhere
            byte[] bytes = file.getBytes();
            Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
            Files.write(path, bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // Print file data to html
        List<Step> result = loadService.castToStep(new File(UPLOADED_FOLDER + file.getOriginalFilename()));
        return result;
    }

}

  1. Написание Loadservice

    Теперь пришло время написать сервис для чтения файла, отправленного в запросе.Проще говоря, есть только один шаг, преобразовать скрипт в Excel в связанный список pojo и вернуть его как ResponseBody в контроллере.

    7.1 Сначала создайте интерфейс службы, код выглядит следующим образом:

package com.daniel.vuespringbootuploadbe;

import org.springframework.stereotype.Service;

import java.io.File;
import java.util.List;

@Service
public interface LoadService {
    List<Step> castToStep(File file);
}

7.2 Затем создайте класс реализации службы со следующим кодом:

package com.daniel.vuespringbootuploadbe;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
public class LoadServiceImpl implements LoadService {


    @Override
    public List<Step> castToStep(File file) {
        List<Step> steps = new ArrayList<>();
        Workbook workbook = null;
        try {
            workbook = new XSSFWorkbook(file);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        }
        Sheet sheet = workbook.getSheetAt(0);
        int num = sheet.getLastRowNum() - sheet.getFirstRowNum();
        //Read steps
        for (int i = 0; i < num; i++) {
            Row row = sheet.getRow(i+1);
            Step step = new Step();
            step.setPlatform(row.getCell(0).getStringCellValue());
            step.setAction(row.getCell(1).getStringCellValue());
            step.setPath(row.getCell(2).getStringCellValue());
            step.setValue(row.getCell(3).getStringCellValue());
            step.setWait((int) row.getCell(4).getNumericCellValue());
            step.setScreenshot(row.getCell(5).getStringCellValue());
            steps.add(step);
        }
        try {
            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return steps;
    }
}

  1. Создание простого RESTful API

    Статья подходит к концу.Теперь, когда самостоятельный код фронтенда и бекенда в основном разработан, пришло время строить RESTful.API в этой статье очень простой, то есть для ответа на выгрузку пишите возвращенный json в таблицу на интерфейсе и завершите импорт сценария.После того, как npm установит axios, добавьте следующий код в компонент ScriptTable:

      getFile: function (event) {
        this.file = event.target.files[0];
        console.log(this.file);
      },
      submit: function (event) {
        event.preventDefault();
        let formData = new FormData();
        formData.append("file", this.file);
        axios.post('http://localhost:8088/upload', formData)
          .then(function (response) {
            for (let i = 0; i < response.data.length; i++) {
              var tempData = {
                platform: response.data[i].platform,
                action: response.data[i].action,
                path: response.data[i].path,
                value: response.data[i].value,
                wait: response.data[i].wait,
                screenshot: response.data[i].screenshot
              };
              this.steps.push(tempData);
            }
          }.bind(this))
          .catch(function (error) {
            alert("Fail");
            console.log(error);
          });
      }
  1. Запускаем сервис, пишем скрипт и загружаем

    Затем мы создаем Excel, пишем простой скрипт в показанном формате, запускаем интерфейсные и внутренние службы и загружаем:

После запуска файл Excel будет загружен в статический временный каталог внутреннего проекта.

Отображение результатов

Эпилог

В этой статье реализована только базовая функция скрипта загрузки.Для реализации работы скрипта нам также необходимо реализовать сопутствующие сервисы в проекте BE для инкапсуляции, что требует помощи Selenium. Это будет подробно объяснено в следующих уроках, так что следите за обновлениями.

приложение

Адрес источника:

Фронтальный проект -git ee.com/Daniel_dingdingding/…

Бэкенд проект -git ee.com/Daniel_dingdingding/…