SpringBoot+Vue – Table operation

Tool environment: JDK1.8, MyQL5.7, WebStorm2018, IDEa2018, SQLyog, Postman

The project recommended just entering the springboot development of friends practice use

Business profile

Create a page that displays player information, supports the addition and deletion of players, and supports the import and export of page tables.

purpose

Sort out business logic and development process, understand and develop independently. Keep the steps as brief as possible

Results the preview

The development process

Creating database scripts

Example Import userinfo script information

/*Table structure for table `userInfo` */

DROP TABLE IF EXISTS `userInfo`;

CREATE TABLE `userInfo` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) DEFAULT NULL COMMENT 'Username'.`gameLevel` enum('black iron'.'brass'.'silver'.'gold'.'diamond') DEFAULT NULL.`createDate` timestamp NULL DEFAULT CURRENT_TIMESTAMP.`enabled` tinyint(1) DEFAULT '1',
  PRIMARY KEY (`id`))ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=utf8;

/*Data for the table `userInfo` */

INSERT  INTO `userInfo`(`id`.`username`.`gameLevel`.`createDate`.`enabled`) VALUES 
(1.'Joe'.'diamond'.'the 2018-01-11 21:19:14'.1),
(2.'bill'.NULL.'the 2018-01-11 21:19:20'.1),
(3.'Cathy'.'silver'.'the 2018-01-11 21:35:39'.1),
(4.'Daisy'.'brass'.'the 2018-01-11 22:42:12'.0),
(5.'little red'.'black iron'.'the 2018-01-14 16:18:50'.1),
(6.'Ming'.'gold'.'the 2018-01-14 16:19:00'.1),
(7.'flower'.'brass'.'the 2018-01-14 16:19:14'.1),
(8.'Han Meimei'.'silver'.'the 2018-01-14 16:19:24'.1);
Copy the code

The effect is as follows:

Configure the back-end SpringBoot project

1. Import related dependencies

(pom.xml)

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.0.1</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.10</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.27</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.google.code.google-collections</groupId>
        <artifactId>google-collect</artifactId>
        <version>snapshot-20080530</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>4.0.1</version>
    </dependency>
</dependencies>
Copy the code

Pay attention to

  • Idea defaults to install the latest version of the dependency, I am mysql5.7, so specifically specify the following version

  • You can start by defining a HelloController test class to make sure your Web project starts properly.

3. Configure database connections and network ports

(application. The properties)

Server port = 8081 # print log logging.level.com.chety.sheetdemo.mapper=debug spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql:///test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true spring.datasource.username=root spring.datasource.password=1234Copy the code

4. Create entity classes

  • Define the entity class user.java and the persistence layer UserMapper interface and XML mapping files that can be generated using reverse engineering.

  • Since the table has fields with dates, JSON conversion will cause errors, so use annotations to indicate the content format

(User. Java)

public class User {
    private Integer id;

    private String nickname;

    private String gamelevel;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "Asia/Shanghai")
    private Date createdate;

    private Boolean enabled;
    
    //getter and setter...
    
}    
Copy the code

Add database component and configure scan of mybatis mapping file in startup class

(SheetdemoApplication. Java)

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@MapperScan(basePackages = "com.chety.sheetdemo.mapper")
public class SheetdemoApplication {

    public static void main(String[] args) { SpringApplication.run(SheetdemoApplication.class, args); }}Copy the code

6. Configure the data source path (POM.xml)

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
Copy the code

To save space, only the front and back end of the query detailed steps. The purpose is to clarify the thinking, understand the business logic, the following can be a reference, can also refer to the complete code behind.

Write back-end interface code

1. Define user query methods

(UserController. Java)

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    UserService userService;

    @GetMapping("/")
    public List<User> getAllUser(a) {
        returnuserService.getAllUser(); }}Copy the code

2. Query the service class

(UserService.java)

@Service
public class UserService {
    @Autowired
    UserMapper userMapper;

    public List<User> getAllUser(a) {
        returnuserMapper.getAllUser(); }}Copy the code

3. Define interface methods

(UserMapper.java)

List<User> getAllUser(a);
Copy the code

4. SQL statements

(UserMapper. XML)

<select id="getAllUser" resultMap="BaseResultMap">
  select * from userinfo;
</select>
Copy the code

5, back-end test using the postman get request at http://127.0.0.1:8081/user/. Returns a JSON array of player information

Front-end Vue project setup

The page template

1. Open the Terminal window of WebStorm and install the dependencies of ElementUI and Axios

npm i element-ui -S
npm install axios
Copy the code

2. Introduce the resource you just downloaded

(main. Js)

import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

import {postRequest} from "./utils/api";
import {postKeyValueRequest} from "./utils/api";
import {putRequest} from "./utils/api";
import {deleteRequest} from "./utils/api";
import {getRequest} from "./utils/api";
import {uploadFileRequest} from "./utils/api";

Vue.use(ElementUI)

Vue.config.productionTip = false

Vue.prototype.postRequest = postRequest;
Vue.prototype.postKeyValueRequest = postKeyValueRequest;
Vue.prototype.putRequest = putRequest;
Vue.prototype.deleteRequest = deleteRequest;
Vue.prototype.getRequest = getRequest;
Vue.prototype.uploadFileRequest = uploadFileRequest;

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})
Copy the code

3. Configure the back-end access path 8081

(config \ index. Js)

// Paths
assetsSubDirectory: 'static'.assetsPublicPath: '/'.proxyTable: {
  '/': {
    target: 'http://localhost:8081'.changeOrigin: true.pathRewrite: {
      '^ /': ' '}}},Copy the code

4. Import an HTTP request interface tool file

(SRC \ utils \ API. Js)

'use strict'
/ / the Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.

const path = require('path')

module.exports = {
  dev: {

    // Paths
    assetsSubDirectory: 'static'.assetsPublicPath: '/'.proxyTable: {
      '/': {
        target: 'http://localhost:8081'.changeOrigin: true.pathRewrite: {
          '^ /': ' '}}},// Various Dev Server settings
    host: 'localhost'.// can be overwritten by process.env.HOST
    port: 8080.// can be overwritten by process.env.PORT, if port is in use, a free one will be determined
    autoOpenBrowser: false.errorOverlay: true.notifyOnErrors: true.poll: false.// https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-

    
    /** * Source Maps */

    // https://webpack.js.org/configuration/devtool/#development
    devtool: 'cheap-module-eval-source-map'.// If you have problems debugging vue-files in devtools,
    // set this to false - it *may* help
    // https://vue-loader.vuejs.org/en/options.html#cachebusting
    cacheBusting: true.cssSourceMap: true
  },

  build: {
    // Template for index.html
    index: path.resolve(__dirname, '.. /dist/index.html'),

    // Paths
    assetsRoot: path.resolve(__dirname, '.. /dist'),
    assetsSubDirectory: 'static'.assetsPublicPath: '/'./** * Source Maps */

    productionSourceMap: true.// https://webpack.js.org/configuration/devtool/#production
    devtool: '#source-map'.// Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false.productionGzipExtensions: ['js'.'css'].// Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  }
}
Copy the code

Create a new component that displays player information and create a table in it. The table style comes from ElementUi

(SRC/components/User. Vue)

Table Structure

<template> <div style="margin: 20px"> <div style="display: flex; Justify -content: center"> <h2> </h2> </div> <hr> <div style="display: flex; Box-sizing: border-box! Important; word-wrap: break-word! Important;" > <div style="margin-top: 10px; > <el-table :data="userinfo" border style="width: 100%"> <el-table-column prop="id" label="ID" width="180"> </el-table-column> <el-table-column prop="nickname" Label =" nickname "> </el-table-column> <el-table-column prop="gamelevel" label=" segment "> </el-table-column> <el-table-column Prop ="createdate" label=" create time "> </el-table-column> <el-table-column prop="enabled" label=" Available "> </el-table-column> <el-table-column label=" Operation "> </el-table-column> </el-table> </div> </div> </template> <script> export default {name: Userinfo: [],}},} </script> <style scoped> </style>Copy the code

6. Configure access routes for player information

(SRC/router/index. Js)

// ...
import User from '@/components/User'

routes: [{
    path:'/user'.name:'User'.component:User,
    hidden:true
  }
   // ...    
]
Copy the code

7. Run dev and use a browser to access port http://localhost:8080/#/user

Form complete

1. Special field processing

Add a slot in the “segment” cell, display the segment name if there is a segment, empty if there is no segment, display “no segment”

<el-table-column prop="gamelevel" label=" segment "> <template slot-scope="scope"> <span V-if ="scope.row.gamelevel">{{scope.row.gamelevel}}</span> <span v-else> </span> </template> </el-table-column>Copy the code

Add slot to “Available” cell, display “Yes” if available, display “No” otherwise

<el-table-column prop="enabled" label=" available "> <template slot-scope="scope"> <el-tag type="success" V-if ="scope.row.enabled"> Yes </el-tag> <el-tag type="info" V-else > No </el-tag> </template> </el-table-column>Copy the code

In the “Actions” cell, add two buttons to edit and delete

<el-table-column label=" operation "> <template slot-scope="scope"> <el-button type="warning"> Edit </el-button> <el-button Type ="danger"> </el-button> </template> </el-table-column>Copy the code

2. Create a way to query all players

<script> export default { // ... Mounted (){this.inituser (); // Mounted (){this.inituser (); }, methods:{initUser() {// HTTP request, get this.getrequest ("/user/"). Then (resp => { If (resp) {this.userinfo=resp; } }) } } } </script>Copy the code

3, Check the page again, the existing data, OK

subsequent

The additions, deletions, and changes are all very similar. The main purpose is to clarify the ideas and steps of the front-end development API

Here is the complete code for DRUD and the import/export files

1, front-end page (SRC /components/ user.vue)

Due to the bidirectional binding nature of Vue, when modifying data data, a set of rows is recopied and defined.

<template> <div style="margin: 20px"> <div> <div style="display: flex; justify-content: Center "> <h2> Player info sheet </h2> </div> <hr> <span> added new summoner: </span> <el-input v-model=" userself. nickname" placeholder=" placeholder "style="width: 200px"></ EL-input >< el-select V-model ="userselect.gamelevel" placeholder=" select segments ">< el-option V-for ="item in userselects"  :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> <el-button type="primary" </el-button> <el-button icon="el-icon-download" type="success" @click="exportFile"> </el-button> <el-upload style="display: inline" :show-file-list="false" :on-success="onSuccess" :on-error="onError" :before-upload="beforeUpload" action="/user/import"> <el-button type="info" :disabled="! enabledUploadBtn" :icon="uploadBtnIcon">{{btnText}}</el-button> </el-upload> </div> <hr> <div style="margin-top: 10px;" > <el-table :data="userinfo" border style="width: 100%"> <el-table-column prop="id" label="ID" width="180"> </el-table-column> <el-table-column prop="nickname" </el-table-column> <el-table-column prop="gamelevel" label=" segment "> <template slot-scope="scope"> <span V-if ="scope.row.gamelevel">{{scope.row.gamelevel}}</span> <span v-else> </span> </template> </el-table-column> <el-table-column prop="createdate" label=" createdate" > </el-table-column> <el-table-column prop=" Enabled "label=" Available "> <template slot-scope="scope"> <el-tag type="success" V-if ="scope.row.enabled"> Yes </el-tag> <el-tag type="info" V-else > No </el-tag> </template> </el-table-column> <el-table-column label=" operation "> <template slot-scope="scope"> <el-button Type ="warning" @click="toUpdateUser(scope.row)"> </el-button> <el-button type="danger" @click="deleteUser(scope.row.id)"> Delete </el-button> </template> </el-table-column> </el-table> </el-table> </div> <el-dialog title=" modify" Sync ="dialogVisible" width="30%"> <div> <table> <tr> < TD > nickname </ TD >< TD ><el-input V-model ="userupdate.nickupdate" Placeholder =" new name "></el-input></td> </tr> <tr> < TD >< td> <el-select V-model ="userupdate.levelupdate" Placeholder =" please input segment "> < EL-option V-for ="item in userselects" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </td> </tr> </table> </div> <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false"> </el-button> <el-button type="primary" @click="doUpdateUser"> </el-dialog> </div> </template> <script> export default { name: "User", mounted(){ this.initUser(); }, data() {return {uploadBtnIcon:'el-icon-upload2', enabledUploadBtn:true, btnText:' import ', dialogVisible: false, userinfo: [], userselect:{ nickname:'', gamelevel:'' }, userupdate:{ id:'', nickupdate:'', levelupdate:'', createdate:'', Enabled: '}, userselects: [{value: 'diamond' label: 'diamond'}, {value: 'gold' label: 'gold'}, {value: 'silver', Label: 'silver'}, {value: 'black iron, label:' black iron '}, {value: null, label: 'no grade'},]}}, methods:{ onSuccess(response,file,fileList) { this.enabledUploadBtn=true; this.uploadBtnIcon='el-icon-upload2'; This. btnText=' import '}, onError(err, file, fileList) {this.enabledUploadBtn=true; UploadBtnIcon ='el-icon-upload2' this.btnText=' import '}, beforeUpload(file) {this.enabledUploadBtn=false; this.uploadBtnIcon='el-icon-loading'; This.btntext =' importing '}, exportFile() {window.open("/user/export", "_parent"); }, addUser() { this.postRequest("/user/",this.userselect).then(resp => { if (resp) { this.initUser(); This.$message({type: 'success', message: 'added successfully! '}); }})}, deleteUser(id) {this.$confirm(' This will make the player leave the canyon forever. Do you want to continue? ', 'confirmButtonText ', {confirmButtonText:' confirm ', cancelButtonText: 'cancel ', type: 'warning' }).then(() => { this.deleteRequest("/user/"+id).then(resp => { if (resp) { this.$message({ type: 'success', message: 'Delete successful! '}); this.initUser(); }})}). The catch (() = > {enclosing $message ({type: 'info', the message: 'cancelled delete'}); }); }, toUpdateUser(data) { // alert(JSON.stringify(data)); this.dialogVisible = true; this.userupdate.id=data.id; this.userupdate.nickupdate=data.nickname; this.userupdate.levelupdate=data.gamelevel; this.userupdate.createdate=data.createdate; this.userupdate.enabled=data.enabled }, doUpdateUser() { this.dialogVisible = false; this.userselect.id=this.userupdate.id; this.userselect.nickname=this.userupdate.nickupdate; this.userselect.gamelevel=this.userupdate.levelupdate; this.userselect.createdate=this.userupdate.createdate; this.userselect.enabled=this.userupdate.enabled; alert(JSON.stringify(this.userselect)) this.putRequest("/user/",this.userselect).then(resp => { if (resp) { this.initUser(); This.$message({type: 'success', message: 'success'! '}); }else {this.$message({type: 'info', message: 'unknown error, update failed'}); } }) }, initUser() { this.getRequest("/user/").then(resp => { if (resp) { this.userinfo=resp; } }) } } } </script> <style scoped> </style>Copy the code

2. Back-end interfaces

2.1 Unified Return information class

public class RespEntity {
    / / status code
    private Integer status;
    // Return information
    private String msg;
    // Return an object, optional
    private Object obj;

    public static RespEntity success(String msg, Object obj) {
        return new RespEntity(200, msg, obj);
    }

    public static RespEntity success(String msg) {
        return new RespEntity(200, msg, null);
    }

    public static RespEntity fail(String msg, Object obj) {
        return new RespEntity(500, msg, obj);
    }

    public static RespEntity fail(String msg) {
        return new RespEntity(500, msg, null);
    }

    private RespEntity(Integer status, String msg, Object obj) {
        this.status = status;
        this.msg = msg;
        this.obj = obj;
    }
    private RespEntity(a) {}// getter and setter...
}    
Copy the code

2.2 Tool classes for file operations

public class PoiUtils {

    /** * Returns an HTTP response body based on the collection *@paramAllUsers List of titles *@returnHTTP response entity */
    public static ResponseEntity<byte[]> exportUserExcel(List<User> allUsers) throws IOException {
        // Create an Excel file
        HSSFWorkbook workbook = new HSSFWorkbook();
        // Set the document properties
        workbook.createInformationProperties();
        // Get the summary information for the document
        DocumentSummaryInformation sumInfo = workbook.getDocumentSummaryInformation();
        // Set the summary information
        sumInfo.setCompany("towards");
        sumInfo.setManager("chet");
        sumInfo.setCategory("user information");
        // Create a new cell style and add it to the workbook's style sheet.
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        // Get the format index matching the given format string, automatically convert "text" to Excel format string to represent the text
        short format = HSSFDataFormat.getBuiltinFormat("m/d/yy");
        // Set the date format in the table, set the data format (must be valid format)
        cellStyle.setDataFormat(format);

        // Create an HSSFSheet for this HSSFWorkbook and add it to the worksheet
        HSSFSheet sheet = workbook.createSheet("Player Info Sheet");

        // Set the table column name
        // Create a new row in the worksheet
        HSSFRow row = sheet.createRow(0);
        // Create a new cell in the row with the column number
        HSSFCell cell0 = row.createCell(0);
        HSSFCell cell1 = row.createCell(1);
        HSSFCell cell2 = row.createCell(2);
        HSSFCell cell3 = row.createCell(3);
        HSSFCell cell4 = row.createCell(4);

        // Sets a string value for the cell
        cell0.setCellValue("Number");
        cell1.setCellValue("Nickname");
        cell2.setCellValue("Dan");
        cell3.setCellValue("Creation time");
        cell4.setCellValue("Available or not");

        // Loop over the data in the table
        for (int i = 0; i < allUsers.size(); i++) {
            // Returns the element at the specified position in the list
            User level = allUsers.get(i);
            HSSFRow r = sheet.createRow(i + 1);
            HSSFCell c0 = r.createCell(0);
            HSSFCell c1 = r.createCell(1);
            HSSFCell c2 = r.createCell(2);
            HSSFCell c3 = r.createCell(3);
            HSSFCell c4 = r.createCell(4);

            c0.setCellValue(level.getId());
            c1.setCellValue(level.getNickname());
            c2.setCellValue(level.getGamelevel()==null?"No segment at present":level.getGamelevel());
            // Set the date format
            c3.setCellStyle(cellStyle);
            c3.setCellValue(level.getCreatedate());
            c4.setCellValue(level.getEnabled() ? "Yes" : "No." ");
        }
        // Create an HTTP request header
        HttpHeaders headers = new HttpHeaders();
        // Settings, parameters: 1. Control mode - embedded, 2. File name, in the browser to convert format
        headers.setContentDispositionFormData("attachment".new String("Player info sheet.xls".getBytes("UTF-8"), "iso-8859-1"));
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        // Create a byte array output stream
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        workbook.write(baos);
        // Create a new HTTP entity with the given body, header, and status code
        ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(baos.toByteArray(), headers, HttpStatus.CREATED);
        return responseEntity;
    }

    public static List<User> parseFileList(MultipartFile file) throws IOException {
        List<User> Users = new ArrayList<>();
        HSSFWorkbook workbook = new HSSFWorkbook(file.getInputStream());
        HSSFSheet sheet = workbook.getSheetAt(0);
        int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
        for (int i = 1; i < physicalNumberOfRows; i++) {
            HSSFRow row = sheet.getRow(i);
            HSSFCell c0 = row.getCell(0);
            HSSFCell c1 = row.getCell(1);
            HSSFCell c2 = row.getCell(2);
            HSSFCell c3 = row.getCell(3);
            HSSFCell c4 = row.getCell(4);

            double numericCellValue = c0.getNumericCellValue();
            User level = new User();
            level.setId((int)numericCellValue);
            level.setNickname(c1.getStringCellValue());
            level.setGamelevel(c2.getStringCellValue().equals("No segment at present")?null:c2.getStringCellValue());
            level.setCreatedate(c3.getDateCellValue());
            level.setEnabled(c4.getStringCellValue().equals("Yes"));
            Users.add(level);
        }
        returnUsers; }}Copy the code

2.3 Control Layer (UserController.java)

/** * Player info table manipulation, CRUD and file manipulation */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;

    /** * query all player information *@returnThe User list * /
    @GetMapping("/")
    public List<User> getAllUser(a) {
        return userService.getAllUser();
    }

    /** * Add user *@param user
     * @returnRespEntity object * /
    @PostMapping("/")
    public RespEntity addUser(@RequestBody User user) {
        if (userService.addUser(user) == 1) {
            return RespEntity.success("Added successfully");
        }
        return RespEntity.fail("Add failed");
    }

    /** * delete * based on player id@param id
     * @returnRespEntity object * /
    @DeleteMapping("/{id}")
    public RespEntity deleteUserById(@PathVariable("id") Integer id) {
        if ((userService.deleteUserById(id)) == 1) {
            return RespEntity.success("Deleted successfully");
        }
        return RespEntity.fail("Delete failed");
    }

    /** * Update player information, only nicknames and segments can be changed *@param user
     * @returnRespEntity object * /
    @PutMapping("/")
    public RespEntity updateUser(@RequestBody User user) {
        if ((userService.updateUser(user)) == 1) {
            return RespEntity.success("Update successful");
        }
        return RespEntity.fail("Update failed");
    }

    /** * Export excel file *@return
     * @throws IOException
     */
    @GetMapping("/export")
    public ResponseEntity<byte[]> exportExcel() throws IOException {
        return PoiUtils.exportUserExcel(userService.getAllUser());
    }

    /** * Import excel file *@param file
     * @param req
     * @return
     * @throws IOException
     */
    @PostMapping("/import")
    public RespEntity importFile(MultipartFile file, HttpServletRequest req) throws IOException {
        List<User> users = PoiUtils.parseFileList(file);
        System.out.println(users);
        int n = userService.listFileToDb(users);
        System.out.println(n);
        return RespEntity.success("Import successful"); }}Copy the code

2.4 Service Class (userService.java) is omitted. No judgment logic is added here, just inject dao layer call directly.

Note: When importing files, i.e. adding players, it is not recommended to use Java code cycle insert, but directly use SQL statement batch import.

<insert id="listFileToDb">
  INSERT INTO userinfo(
  nickname,gameLevel,createDate,enabled)
  VALUES
  <foreach collection="users" item="user" separator=",">
    (#{user.nickname},#{user.gamelevel},#{user.createdate},#{user.enabled})
  </foreach>
</insert>
Copy the code