编程知识 cdmana.com

Vue + spring boot simple user login demo

1 summary

A simple user login with separate front and back ends Demo.

2 Technology stack

  • Vue
  • BootstrapVue
  • Kotlin
  • Spring Boot
  • MyBatis Plus

3 front end

3.1 Create a project

Use vue-cli establish , If not installed, you can install it first :

sudo cnpm install -g vue @vue/cli

View version :

vue -V

When the version appears, the installation is successful .

Create the initial project :

vue create bvdemo

Due to the present Vue3 There's no official release yet , Recommended Vue2

 Insert picture description here

After waiting for a period of time, the folder will be prompted and run directly :

 Insert picture description here

cd bvdemo
yarn serve

Directly through local 8080 Port to access :

 Insert picture description here

 Insert picture description here

3.2 rely on

Go to the project folder :

cd bvdemo

Installation dependency :

cnpm install bootstrap-vue axios jquery vue-router

There should be popper.js Overdue warnings , This is a bootstrap-vue Why , You can ignore :

 Insert picture description here

The dependency description is as follows :

  • bootstrap-vue: One combines Vue And Bootstrap The front end of the UI frame
  • axios It's a simple, easy to use and efficient http library , This project uses it to send login requests
  • jquery: A powerful JS library
  • vue-routerVue The official route manager for

3.3 Open and complete

Turn on before you write code bootstrap-vue Complete support for , Open Settings :

 Insert picture description here

Put... Under the project path node_modules Add to Library , Tick the front one , Then update the cache and restart (`File->Invalidate Cache/Restart
`).

3.4 App.vue

Remove the default HelloWorld Components , And modify it App.vue as follows :

<template>
    <div id="app">
        <router-view></router-view>
    </div>
</template>

<script>
export default {
    name: 'App',
}
</script>

<style>
#app {
    font-family: Avenir, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    margin-top: 60px;
}
</style>

<router-view> It's a functional Components , The view component to which the render path matches , Use here <router-view> According to the access path ( route ) Different displays of ( Rendering ) Corresponding components .

3.5 newly build vue Components

Delete default HelloWorld.vue, newly build Index.vue as well as Login.vue

 Insert picture description here

3.6 Add route

stay main.js New in the same directory router.js, The contents are as follows :

import Vue from "vue"
import VueRouter from "vue-router"
import Login from "@/components/Login"
import Index from "@/components/Index"

Vue.use(VueRouter)

const routes = [
    {
        path: '/',
        component: Login,
        props: true
    },
    {
        path:'/index/:val',
        name:'index',
        component: Index,
        props: true
    }
]

const router = new VueRouter({
    mode:'history',
    routes:routes
})

export default router

routes Represents a route , It contains two routes , One is Login Routing of components /, One is Index Routing of components /index/:val, Of the latter :val It's a placeholder , Used to pass parameters .router Means router ,mode You can choose hash or history

  • hash Will use URL Of hash To simulate a complete one URL, When URL The page does not reload when changed
  • history It's just normal URL

router Medium routes Parameter declares the corresponding route , Finally, remember to put router Add to main.js in .

3.7 vue.config.js

stay package.json Created in the same level directory vue.config.js, The contents are as follows :

module.exports = {
    chainWebpack: config => {
        config.module
            .rule('vue')
            .use('vue-loader')
            .loader('vue-loader')
            .tap(options => {
                options.transformAssetUrls = {
                    img: 'src',
                    image: 'xlink:href',
                    'b-img': 'src',
                    'b-img-lazy': ['src', 'blank-src'],
                    'b-card': 'img-src',
                    'b-card-img': 'src',
                    'b-card-img-lazy': ['src', 'blank-src'],
                    'b-carousel-slide': 'img-src',
                    'b-embed': 'src'
                }
                return options
            })
    }
}

The main reason for using this profile is <b-img> Of src Properties cannot read images properly , After the configuration file is added, it can be read normally according to the path .

3.8 main.js

Add dependencies and routing :

import Vue from 'vue'
import App from './App.vue'

import {BootstrapVue, BootstrapVueIcons} from 'bootstrap-vue'
import router from "@/router";
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

Vue.use(BootstrapVue)
Vue.use(BootstrapVueIcons)
Vue.config.productionTip = false

new Vue({
    render: h => h(App),
    router
}).$mount('#app')

introduce BootstrapVue, And register the route to Vue In the example ( It's the last 2 That's ok , As the creation of Vue Instance parameters , It's important to pay attention to this , Otherwise, the routing function will not work properly ).

3.9 Login component

That is to say Login.vue, The contents are as follows :

<template>
    <div>
        <b-img src="../assets/logo.png"></b-img>
        <br>
        <b-container>
            <b-row>
                <b-col offset="3" cols="6">
                    <b-input-group size="lg">
                        <b-input-group-text> user name </b-input-group-text>
                        <b-form-input type="text" v-model="username"></b-form-input>
                    </b-input-group>
                </b-col>
            </b-row>
            <br>
            <b-row>
                <b-col offset="3" cols="6">
                    <b-input-group size="lg">
                        <b-input-group-text> password </b-input-group-text>
                        <b-form-input type="password" v-model="password"></b-form-input>
                    </b-input-group>
                </b-col>
            </b-row>
            <br>
            <b-row>
                <b-col offset="3" cols="6">
                    <b-button variant="success" @click="login">
                         One click registration / Sign in 
                    </b-button>
                </b-col>
            </b-row>
        </b-container>
    </div>
</template>

<script>
import axios from 'axios'
import router from "@/router"

export default {
    name: "Login.vue",
    data:function (){
        return{
            username:'',
            password:''
        }
    },
    methods:{
        login:function(){
            axios.post("http://localhost:8080/login",{
                username:this.username,
                password:this.password
            }).then(function (res){
                router.push({
                    name:"index",
                    params:{
                        val:res.data.code === 1
                    }
                })
            })
        }
    }
}
</script>

<style scoped>

</style>

Grid system layout is adopted <b-row>+<b-col>, The other components will not be mentioned , Most of the components are described on the official website ( Sure Poke it here ), Send request using axios, Parameters are wrapped in the request body , Attention needs to be paid to the back end (@RequestBody, In the request header, please use @RequestParm) Corresponding .

In addition, we should pay attention to the cross domain problem , The cross domain problem here is left to the back end :

@CrossOrigin("http://localhost:8081")

( In the local test, the back end runs in 8080 port , And the front end runs in 8081 port )

After sending the request, use the route to jump , I'm carrying res.data.code Parameters , among res.data It's the data in the response , hinder code It's back-end custom data , return 1 Indicates successful registration , return 2 Indicates successful login .

3.10 Homepage component

The home page simply shows the successful login or registration :

<template>
    <div>
        <b-img src="../assets/logo.png"></b-img>
        <b-container>
            <b-row align-h="center">
                <b-col>
                    <b-jumbotron header=" Registered successfully " lead=" welcome " v-if="val"></b-jumbotron>
                    <b-jumbotron header=" Login successful " lead=" welcome " v-else></b-jumbotron>
                </b-col>
            </b-row>
        </b-container>
    </div>
</template>

<script>
export default {
    name: "Index.vue",
    props:['val']
}
</script>

<style scoped>

</style>

props Express val Are parameters from other components , And regard it as in v-if Parameters for conditional rendering in .

So the front end is ready . Let's start with the back end .

4 Back end

4.1 Create a project

use Kotlin+Gradle+MyBatisPlus structure , The new project is as follows :

 Insert picture description here

 Insert picture description here

 Insert picture description here

4.2 rely on

introduce MyBatis Plus Rely on it :

implementation("com.baomidou:mybatis-plus-boot-starter:3.4.0")

4.3 Data sheet

create database if not exists test;
use test;
drop table if exists user;
create table user(
    id int auto_increment primary key ,
    username varchar(30) default '',
    password varchar(30) default ''
)

4.4 The configuration file

Database user name + password +url

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: 123456

4.5 New package

Create the following six packages , Respectively represents the configuration class 、 Control layer 、 Persistence layer 、 Entity class 、 Response class 、 The business layer .

 Insert picture description here

4.6 Entity class

package com.example.demo.entity

class User(var username:String,var password:String)

4.7 Persistence layer

package com.example.demo.dao

import com.baomidou.mybatisplus.core.mapper.BaseMapper
import com.example.demo.entity.User
import org.apache.ibatis.annotations.Mapper
import org.apache.ibatis.annotations.Select

@Mapper
interface DemoMapper :BaseMapper<User>{
    @Select("select * from user where username=#{username} and password = #{password}")
    fun selectByUsernameAndPassword(username:String,password:String):List<User>
}

@Mapper Said to Mapper Interface generates an implementation class , And there's no need to write xml The configuration file .@Select Represents the query sql sentence .

4.8 Response body

package com.example.demo.response

class DemoResponse
{
    var data = Any()
    var code = 0
    var message = ""
}
package com.example.demo.response

class DemoResponseBuilder {
    private var response = DemoResponse()

    fun data(t:Any): DemoResponseBuilder
    {
        response.data = t
        return this
    }
    fun code(t:Int): DemoResponseBuilder
    {
        response.code = t
        return this
    }
    fun message(t:String): DemoResponseBuilder
    {
        response.message = t
        return this
    }
    fun build() = response
}

Here the response body is divided into :

  • Response code
  • Response body data
  • Other information

Agree with the front end . Generate the response body through a Builder Class generation .

4.9 The business layer

package com.example.demo.service

import com.demo.response.DemoResponse
import com.demo.response.DemoResponseBuilder
import com.example.demo.dao.DemoMapper
import com.example.demo.entity.User
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
@Transactional
class DemoService
{
    @Autowired
    lateinit var mapper: DemoMapper

    fun login(username:String, password:String): DemoResponse
    {
        val result = mapper.selectByUsernameAndPassword(username,password).size
        if(result == 0)
            mapper.insert(User(username,password))
        return DemoResponseBuilder().code(if(result == 0) 1 else 2).message("").data(true).build()
    }
}

@Service Mark as business layer ,@Transactional Indicates that transaction management has been added , If the persistence layer operation fails, it will be rolled back .@Autowired It means automatic injection , stay Java
You can use it directly @Autowired, And in the Kotlin Required in lateinit var.

4.10 Control layer

package com.example.demo.controller

import com.demo.response.DemoResponse
import com.example.demo.entity.User
import com.example.demo.service.DemoService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/")
@CrossOrigin("http://localhost:8081")
class DemoController {
    @Autowired
    lateinit var service: DemoService

    @PostMapping("login")
    fun login(@RequestBody user: User):DemoResponse
    {
        return service.login(user.username, user.password)
    }
}

The main thing is to add a cross domain processing @CrossOrigin, When developing, please correspond to the port of the front end .

4.11 Configuration class

package com.example.demo.config

import org.mybatis.spring.annotation.MapperScan
import org.springframework.context.annotation.Configuration

@Configuration
@MapperScan("com.example.demo.dao")
class MyBatisConfig

@MapperScan It means scanning under the corresponding package @Mapper.

4.12 test

package com.example.demo

import com.example.demo.service.DemoService
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest

@SpringBootTest
class DemoApplicationTests {

    @Autowired
    lateinit var service: DemoService

    @Test
    fun contextLoads() {
        println(service.login("123", "456"))
    }

}

After the test is passed, the back-end is finished .

5 Total test

Run the back end first ,Kotlin Unlike Java, The startup configuration can be configured automatically when the project is generated , You need to run the startup class manually main

 Insert picture description here

Then run the front end :

npm run serve

If you don't want to use the command line, you can use the graphical interface to configure :

 Insert picture description here

Open according to the console output localhost:8081

 Insert picture description here

 Insert picture description here

Just type in your username and password , Create if it does not exist , Log in if you exist :

 Insert picture description here

 Insert picture description here

At the same time of registration, the back-end database will generate a record :

 Insert picture description here

Re entering the same user name and password will show successful login :

 Insert picture description here

This formally completes a simple front-end and back-end separation login Demo.

5 Source code

This article is a platform of operation tools such as blog group sending one article and multiple sending OpenWrite Release

版权声明
本文为[She Ling]所创,转载请带上原文链接,感谢

Scroll to Top