Spring Boot+Vue從零開始搭建系統(三):項目先後端分離_實現簡單登陸demo

前言

本文主要是想經過後端 Spring Boot 技術和前端 Vue 技術來簡單開發一個登陸demo,該demo以簡單、方便理解的方式來記錄先後端結合使用的過程,方便正式開發複雜項目時能提早總體理解流程,demo最終實現的效果以下圖:
css


DEMO功能描述

輸入http://localhost:8080回車瀏覽器自動跳轉到http://localhost:8080/login登陸頁面,登陸頁面包含頁面頭部、登陸信息頁面、頁面尾部。輸入用戶名、密碼點擊登陸功能實現效果以下:
1.輸入服務器不正確的用戶名密碼,如輸入用戶名wangjihong登陸,會在登陸驗證狀況文本框中顯示後端端驗證後的錯誤信息。
2.輸入正確的用戶名密碼,如輸入用戶名javalsj密碼123456登陸,則服務端驗證正確後前端頁面自動跳轉到首頁http://localhost:8080/index。html


DEMO技術棧描述

1.前端技術棧:前端

.編程語言:html五、js、css
.開發工具:Visual Studio Code
.開發框架:vue + axios
.包管理工具:npm
.打包工具:webpack

2.後端技術棧:vue

.編程語言:java
.開發工具:Eclipse
.開發框架:spring boot
.包管理工具:gradle構建工具下的maven資源庫
.打包工具:gradle

DEMO開發流程概要

1.前端開發流程html5

.安裝nodejs並初始化Vue項目。
.在已初始化的Vue項目中的開發頁面頭、頁面尾公共組件。
.開發登陸頁面組件。
.開發首頁頁面組件。
.支持跨域,請求路由,頁面路由開發。
.單獨運行Vue項目查看效果。

2.後端開發流程java

.安裝JDK10並配置好JAVA_HOME環境變量.
.初始化springboot項目。
.開發restful控制器。
.支持跨域。
.單獨運行後端springboot項目查看效果。

3.運行項目流程node

.使用webpack將Vue項目打包。
.將打包的Vue項目集成到springboot項目中。
.使用gradle將springboot打包成jar文件。
.使用jdk運行jar包來啓動demo項目服務,請訪問地址查看效果。

4.開發過程當中注意點webpack

.前端項目因爲啓用了eslint語法檢測,因此有時候多個空格或者少個空格或者少個空行,都會運行不起來前端項目,對應提示信息改下便可。
.前端發送請求的數據格式須要與後端接收請求數據對象格式要約定一致。
.在先後端未集成的時候須要跨域支持。

DEMO開發流程詳情

前端開發內容

結構預覽

圖片描述

安裝nodejs並初始化Vue項目

查看文章http://www.javashuo.com/article/p-yenfguyr-kh.html,按步驟操做便可。
使用axios前先執行cd W:\Workspaces\git_repositories\javalsj-blog-vue進入Vue項目目錄下,執行命令cnpm install axios安裝axios。ios


在已初始化的Vue項目中的開發頁面頭、頁面尾公共組件

BlogHeader.vue 頁面頭代碼:git

<template>
    <div>
        頁面頭部
    </div>
</template>

<script>
export default {
  name: 'BlogHeader'
}
</script>

BlogFooter.vue 頁面尾部代碼:

<template>
    <div>
        頁面尾部
    </div>
</template>

<script>
export default {
  name: 'BlogFooter'
}
</script>

開發登陸頁面組件

BlogLogin.vue 登陸頁面代碼:

<template>
  <div>
    <blog-header></blog-header>
    <hr/>
    <div>
      用戶名:<input type="text" v-model="loginInfoVo.username" placeholder="請輸入用戶名" />
      <br/>
      密碼:<input type="password" v-model="loginInfoVo.password" placeholder="請輸入密碼" />
      <br/>
      <button v-on:click="login">登陸</button>
      <br/>
      登陸驗證狀況:<textarea cols="30" rows="10" v-model="responseResult"></textarea>
    </div>
    <hr/>
    <blog-footer></blog-footer>
  </div>
</template>

<script>
import blogHeader from '@/components/common/BlogHeader.vue'
import blogFooter from '@/components/common/BlogFooter.vue'

export default {
  name: 'BlogLogin',
  // blogHeader、blogFooter組件給申明到components裏面而後在template裏面使用
  components: { blogHeader, blogFooter },
  data () {
    return {
      loginInfoVo: { username: '', password: '' },
      responseResult: []
    }
  },
  methods: {
    login () {
      this.$axios
        .post('/login', {
          username: this.loginInfoVo.username,
          password: this.loginInfoVo.password
        })
        .then(successResponse => {
          this.responseResult = JSON.stringify(successResponse.data)
          if (successResponse.data.code === 200) {
            this.$router.replace({path: '/index'})
          }
        })
        .catch(failResponse => {})
    }
  }
}
</script>

開發首頁頁面組件

BlogIndex.vue 首頁頁面代碼:

<template>
  <div>
    <blog-header></blog-header>
    <hr/>
    <div>
      這是首頁,嘻嘻嘻。
    </div>
    <hr/>
    <blog-footer></blog-footer>
  </div>
</template>

<script>
import blogHeader from '@/components/common/BlogHeader.vue'
import blogFooter from '@/components/common/BlogFooter.vue'

export default {
  name: 'BlogIndex',
  // blogHeader/blogFooter組件給申明到components裏面而後在template裏面使用
  components: { blogHeader, blogFooter }
}
</script>

支持跨域,請求路由,頁面路由開發

main.js 主入口代碼:

import Vue from 'vue'
import App from './App'
import router from './router'
// 引用axios,並設置基礎URL爲後端服務api地址
var axios = require('axios')
axios.defaults.baseURL = 'https://localhost:8443/api'
// 將API方法綁定到全局
Vue.prototype.$axios = axios
Vue.config.productionTip = false

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

router/index.js 頁面路由代碼:

import Vue from 'vue'
import Router from 'vue-router'
import BlogLogin from '@/components/manage/BlogLogin.vue'
import BlogIndex from '@/components/home/BlogIndex.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      redirect: '/login'
    },
    {
      path: '/index',
      name: 'BlogIndex',
      component: BlogIndex
    },
    {
      path: '/manage',
      redirect: '/login'
    },
    {
      path: '/login',
      name: 'BlogLogin',
      component: BlogLogin
    }
  ]
})

config/index.js 跨域支持代碼:
找到文件中的proxyTable位置修改成如下內容添加請求到後端的跨域支持。

// 路由接口代理配置
proxyTable: {
  '/api': {
    target: 'https://localhost:8443',
    changeOrigin: true,
    pathRewrite: {
        '^/api': ''
    }
  }
}

單獨運行Vue項目查看效果

訪問地址:http://localhost:8080看效果以下:
圖片描述


後端開發內容

結構預覽

圖片描述

安裝JDK10並配置好JAVA_HOME環境變量

這裏不介紹,網上搜一下相關文檔。

初始化SpringBoot項目

這裏也不作介紹,網上搜一下相關文檔。。

開發登陸控制器

1.開發請求映射對象代碼
VueLoginInfoVo.java :

package com.javalsj.blog.pojo.vo;

import javax.validation.constraints.NotNull;

/** 
 * @description Vue登陸頁面demo信息對象實體
 * @author WANGJIHONG
 * @date 2018年4月5日 下午10:57:53 
 * @Copyright 版權全部 (c) www.javalsj.com
 * @memo 備註信息
 */
public class VueLoginInfoVo {
    
    @NotNull(message="用戶名不容許爲空")
    private String username;
    
    @NotNull(message="密碼不容許爲空")
    private String password;

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

2.開發響應結果對象代碼
Result.java:

package com.javalsj.blog.result;

/**
 * @description 統一 API響應結果封裝
 * @author WANGJIHONG
 * @date 2018年3月13日 下午8:44:29
 * @Copyright 版權全部 (c) www.javalsj.com
 * @memo 控制Result權限,構建結果Result對象統一使用com.javalsj.blog.vo.ResultFactory工廠類來建立
 */
public class Result {
    /**
     * 響應狀態碼
     */
    private int code;
    /**
     * 響應提示信息
     */
    private String message;
    /**
     * 響應結果對象
     */
    private Object data;

    Result(int code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

}

ResultCode:

package com.javalsj.blog.result;

/**
 * @description 響應碼枚舉,參考 HTTP狀態碼的語義
 * @author WANGJIHONG
 * @date 2018年3月13日 下午8:35:00
 * @Copyright 版權全部 (c) www.javalsj.com
 * @memo 無備註說明
 */
public enum ResultCode {
    /** 
     * 成功
     */ 
    SUCCESS(200),
    /** 
     * 失敗 
     */ 
    FAIL(400),
    
    /** 
     * 未認證(簽名錯誤)
     */ 
    UNAUTHORIZED(401),
    
    /** 
     * 接口不存在
     */ 
    NOT_FOUND(404),
    
    /** 
     * 服務器內部錯誤
     */ 
    INTERNAL_SERVER_ERROR(500);

    public int code;

    ResultCode(int code) {
        this.code = code;
    }
    
}

ResultFactory:

package com.javalsj.blog.result;

/**
 * @description 響應結果生成工廠類
 * @author WANGJIHONG
 * @date 2018年3月13日 下午8:36:58
 * @Copyright 版權全部 (c) www.javalsj.com
 * @memo 無備註說明
 */
public class ResultFactory {

    public static Result buildSuccessResult(Object data) {
        return buidResult(ResultCode.SUCCESS, "成功", data);
    }

    public static Result buildFailResult(String message) {
        return buidResult(ResultCode.FAIL, message, null);
    }

    public static Result buidResult(ResultCode resultCode, String message, Object data) {
        return buidResult(resultCode.code, message, data);
    }
    
    public static Result buidResult(int resultCode, String message, Object data) {
        return new Result(resultCode, message, data);
    }
}

3.開發登陸控制器,支持跨域。
LoginController 代碼:

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.javalsj.blog.pojo.vo.VueLoginInfoVo;
import com.javalsj.blog.result.Result;
import com.javalsj.blog.result.ResultFactory;

@Controller
public class LoginController {

    /**
     * 登陸控制器,先後端分離用的不一樣協議和端口,因此須要加入@CrossOrigin支持跨域。
     * 給VueLoginInfoVo對象加入@Valid註解,並在參數中加入BindingResult來獲取錯誤信息。
     * 在邏輯處理中咱們判斷BindingResult知否含有錯誤信息,若是有錯誤信息,則直接返回錯誤信息。
     */
    @CrossOrigin
    @RequestMapping(value = "/api/login", method = RequestMethod.POST, produces = "application/json; charset=UTF-8")
    @ResponseBody
    public Result login(@Valid @RequestBody VueLoginInfoVo loginInfoVo, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            String message = String.format("登錄失敗,詳細信息[%s]。", bindingResult.getFieldError().getDefaultMessage());
            return ResultFactory.buildFailResult(message);
        }
        if (!Objects.equals("javalsj", loginInfoVo.getUsername()) || !Objects.equals("123456", loginInfoVo.getPassword())) {
            String message = String.format("登錄失敗,詳細信息[用戶名、密碼信息不正確]。");
            return ResultFactory.buildFailResult(message);
        }
        return ResultFactory.buildSuccessResult("登錄成功。");
    }


}

4.單獨運行後端springboot項目
此處忽略,配置服務端口爲8443,支持https協議,可參考文章http://www.javashuo.com/article/p-xvnzcksh-ez.html


集成先後端代碼,運行完整項目流程

前端服務啓動、後端服務啓動,而後操做按前言的演示圖片內容操做便可,下面進行先後端代碼集成操做。

前端代碼打包

執行 cd W:\Workspaces\git_repositories\javalsj-blog-vue 進入項目目錄下,執行 npm run build命令進行打包,會自動生成打包後的dist目錄文件。如圖:
圖片描述


前端代碼集成到springboot項目中

把dist裏面全部文件都拷貝到springboot項目的resources/static目錄下,以下圖:
圖片描述
而後重啓springboot項目,瀏覽器訪問後臺服務地址:https://localhost:8443,會發現頁面顯示的就是vue開發的前端頁面,而後輸入用戶名密碼登陸正常。
圖片描述
圖片描述
經過上面步驟集成先後端完畢,而後把完整的項目打包成jar包後使用jdk命令運行完整項目便可。


總結

本文主要以一個簡單的登陸demo功能來演示前端開發、後端開發、先後端分離的完整集成和運行的過程,實際開發中比這會複雜的多,此文僅做了解流程使用。
圖片描述

相關文章
相關標籤/搜索