Springboot + Vue + Nginx 前后端分离部署,登陆权限认证超详细

本文介绍了使用SpringBoot和Vue实现前后端分离的用户登录权限认证过程,包括SpringBoot的配置、Vue的配置、Nginx的部署以及页面展示。重点在于SpringBoot的拦截器和token验证,以及Vue的axios设置和路由拦截。最后通过Nginx部署项目,实现了前后端的分离和通信。
摘要由CSDN通过智能技术生成

前后端分离部署+登陆权限认证

初次使用vue,使用过程趟了不少坑。创建项目,安装vue等都自行百度吧。



前言

实现功能:
1、用户登录及token验证;
2、在未登录时跳转到登录页面 ;
3、通过nginx实现前后端分离部署。


一、SpringBoot

1.配置文件

我这里使用的是properties,平平无奇,注意mapper/ *.xml 中间有个空格,别忘了删了。我这里路径有/luck,请求时注意在端口号后面加上/luck。例:http://localhost:8080/luck/api/login。

server.port=8887
server.servlet.context-path=/luck
server.tomcat.connection-timeout=60000
server.tomcat.accept-count=1000
server.tomcat.max-connections=10000
server.tomcat.max-threads=800
server.tomcat.min-spare-threads=100
server.connection-timeout=60000

# mapper 扫描路径
mybatis.mapper-locations=classpath:mapper/ *.xml 
# 本地数据库
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/lucky?serverTimezone=UTC&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
pom.xml
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>luck</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>luck Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.7.RELEASE</version>
  </parent>

  <dependencies>
<!--    <dependency>-->
<!--      <groupId>junit</groupId>-->
<!--      <artifactId>junit</artifactId>-->
<!--      <version>4.11</version>-->
<!--      <scope>test</scope>-->
<!--    </dependency>-->

    <!--thymeleaf模板引擎配置-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.38</version>
    </dependency>

    <dependency>
      <groupId>net.sf.json-lib</groupId>
      <artifactId>json-lib</artifactId>
      <version>2.4</version>
      <classifier>JDK15</classifier>
    </dependency>
    <!-- mysql -->
    <dependency>
     <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>6.0.6</version>
    </dependency>
    <!-- mybatis -->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>1.3.2</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>2.0.7.RELEASE</version>
    </dependency>
    <!-- tomcat-jdbc -->

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.5</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.0.11.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.0.11.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-compress</artifactId>
      <version>1.14</version>
    </dependency>
    <dependency>
      <groupId>org.dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>2.0.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.17</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
    </dependency>

<!--      token-->
      <dependency>
          <groupId>com.auth0</groupId>
          <artifactId>java-jwt</artifactId>
          <version>3.9.0</version>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-configuration-processor</artifactId>
          <optional>true</optional>
      </dependency>

      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
      </dependency>
  </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.luck.Application</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.1</version>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>
        </plugins>

        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
    </build>

</project>

2.Controller - Service - Mapper

咱们做的用户登录权限认证,直接写个LoginController。
UserBean实体类有个username,password行了
Service Mapper 自己写吧。
GResponse 给大家贴上代码了

package com.luck.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.luck.entity.UserBean;
import com.luck.respnse.GResponse;
import com.luck.service.LoginService;
import com.luck.util.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;

/******************************************
 * @Descripttion :
 * @Author :jlz
 * @Date :Created in 2020/12/14 14:00 
 * @Version 1.0
 ******************************************/

@RestController
@RequestMapping("/api")
public class LoginController {

    @Autowired
    LoginService loginService;
    
    @RequestMapping(value = "/login")
    public GResponse login(@RequestBody UserBean user, HttpServletRequest request) throws JsonProcessingException {

        System.out.println("username : "+user.getUsername());
        System.out.println("password : "+user.getPassword());
        UserBean u1 = loginService.login(user);
        if (u1 == null) {
            return GResponse.failure("用户名或密码错误!");
        } else {

            String token= TokenUtil.sign(user);
            HashMap<String,Object> hs=new HashMap<>();
            hs.put("token","token"+user.getUsername()+user.getPassword());

            return GResponse.success(u1,token);
        }
    }
}

GResponse

package com.luck.respnse;

public class GResponse {
    private boolean status; //状态
    private String message; //信息
    private int code;       //编码
    private Object data;    //数据
    private String token;

    public boolean getStatus() {
        return status;
    }

    public GResponse setStatus(boolean status) {
        this.status = status;
        return this;
    }

    public String getMessage() {
        return message;
    }

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

    public String getToken() {
        return token;
    }

    public GResponse setToken(String token) {
        this.token = token;
        return this;
    }

    public int getCode() {
        return code;
    }

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

    public Object getData() {
        return data;
    }

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

    public static GResponse success() {
        ;
        return new GResponse().setStatus(true).setMessage("").setCode(60000).setData(null);
    }

    public static GResponse success(Object data) {
        return new GResponse().setStatus(true).setMessage("").setCode(60000).setData(data);
    }

    public static GResponse success(Object data, Object tag0) {
        return new GResponse().setStatus(true).setMessage("").setCode(60000).setData(data);
    }

    public static GResponse success(Object data,String token) {
        return new GResponse().setStatus(true).setMessage("").setCode(60000).setData(data).setToken(token);
    }

    public static GResponse failure(String message, int code, Object data) {
        return new GResponse().setStatus(false).setMessage(message).setCode(code).setData(data);
    }

    public static GResponse failure(String message) {
        return new GResponse().setStatus(false).setMessage(message).setCode(1).setData(null);
    }

    public static GResponse failure(int code) {
        return new GResponse().setStatus(false).setMessage("failure").setCode(code).setData(null);
    }

    public static GResponse failure(int code, String message) {
        return new GResponse().setStatus(false).setMessage(message).setCode(code).setData(null);
    }
}

3.拦截器 + token签名

在这里插入图片描述

WebConfiguration配置类,包含拦截,跨域处理,白名单

package com.luck.config;

import com.luck.interceptor.TokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.web.servlet.config.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    private TokenInterceptor tokenInterceptor;
    //构造方法
    public WebConfiguration(TokenInterceptor tokenInterceptor){
        this.tokenInterceptor = tokenInterceptor;
    }

    //跨域
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true)
                .allowedHeaders("*")
                .allowedMethods("*")
                .allowedOrigins("*");
    }

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer){
        configurer.setTaskExecutor(new ConcurrentTaskExecutor(Executors.newFixedThreadPool(3)));
        configurer.setDefaultTimeout(30000);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry){
        List<String> excludePath = new ArrayList<>();
        //排除拦截
        excludePath.add("/api/login");   //登录
        excludePath.add("/api/register");//注册
        excludePath.add("/static/**");   //静态资源
        excludePath.add("/assets/**");   //静态资源

        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns(excludePath);
        WebMvcConfigurer.super.addInterceptors(registry);
    }
}
TokenInterceptor
package com.luck.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.luck.util.TokenUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class TokenInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception{
    	//有时一次请求,到拦截器会变成两次,第一次请求方式OPTIONS,直接返回200
        if(request.getMethod().equals("OPTIONS")){
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        response.setCharacterEncoding("utf-8");
        //获取请求头中的token
        String token = request.getHeader("Authorization");
        if(token != null){
            boolean result = TokenUtil.verify(token);
            if(result){
                System.out.println("通过拦截器");
                return true;
            }
        }
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try{
        	//token认证失败或token不存在
            JSONObject json = new JSONObject();
            json.put("msg","token verify fail");
            json.put("code","50000");
            response.getWriter().append(json.toJSONString());
            System.out.println("认证失败,未通过拦截器");
        }catch (Exception e){
            e.printStackTrace();
            response.sendError(500);
            return false;
        }
        return false;
    }
}
最后是TokenUtil ,加签验签
package com.luck.util;

import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.luck.entity.UserBean;
import com.auth0.jwt.JWT;
import java.util.Date;

public class TokenUtil {

    private static final long EXPIRE_TIME= 10*60*60*1000;
    private static final String TOKEN_SECRET="luck";  //密钥

    /**
     * 签名生成
     * @param user
     * @return
     */
    public static String sign(UserBean user){
        String token = null;
        try {
            Date expiresAt = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            token = JWT.create()
                    .withIssuer("auth0")
                    .withClaim("username", user.getUsername())
                    .withExpiresAt(expiresAt)
                    // 使用了HMAC256加密算法。
                    .sign(Algorithm.HMAC256(TOKEN_SECRET));
        } catch (Exception e){
            e.printStackTrace();
        }
        return token;
    }

    /**
     * 签名验证
     * @param token
     * @return
     */
    public static boolean verify(String token){
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
            DecodedJWT jwt = verifier.verify(token);
            System.out.println("认证通过:");
            System.out.println("username: " + jwt.getClaim("username").asString());
            System.out.println("过期时间:      " + jwt.getExpiresAt());
            return true;
        } catch (Exception e){
            return false;
        }
    }
}
到此springboot完事。

二、Vue

因为头一次用这玩意儿,小小的跳页困住我一天(因为vue版本),后来请教了一位小姐姐帮忙解决。反正vue我还是不会

1.配置文件

Vue CLI 4.5
先给大家看看版本,自行百度。
package.json

{
  "name": "zlucky",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "axios": "^0.21.1",
    "core-js": "^3.6.5",
    "element-ui": "^2.4.5",
    "less-loader": "^10.0.1",
    "node-sass": "^4.14.1",
    "vue": "^2.6.11",
    "vue-router": "^3.2.0",
    "vuex": "^3.4.0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "^4.5.13",
    "@vue/cli-plugin-vuex": "^4.5.13",
    "@vue/cli-service": "~4.5.0",
    "axios": "^0.18.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "sass-loader": "^8.0.2",
    "vue-cli-plugin-axios": "0.0.4",
    "vue-cli-plugin-element": "^1.0.1",
    "vue-template-compiler": "^2.6.11"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

2.权限登录配置

与package.json同级创建vue.config.js

module.exports = {
	//打包输出
    outputDir:'dist',
    publicPath:"/",
    devServer:{
    //端口
        port: 80,
    //所有通过'api'调用的请求都会转发到'http://localhost:8887/'下面
        proxy:{
            '/api':{
                target :'http://localhost:8887/luck/api/',
                changeOrigin: true,
                //替换api,替换了个寂寞
                pathRewrite: {
                    "^/api": ""
                }
            }
        }
    }
}

接下来main.js与App.vue
axios router store element 这四个去百度找命令下。或者到项目目录cmd->vue ui 里面下

import Vue from 'vue'
import axios from  'axios'
import App from './App.vue'
import router from './router'
import store from './store'
import './plugins/element.js'

Vue.prototype.$axios = axios
Vue.config.productionTip = false

// 添加请求拦截器,在请求头中加token
axios.interceptors.request.use(
  config => {
    if (localStorage.getItem('Authorization')) {
      config.headers.Authorization = localStorage.getItem('Authorization');
    }

    return config;
  },
  error => {
    return Promise.reject(error);
  });

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

app.vue 里面router-view标签别忘了加,跳页就指他呢

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

<script>

export default {
  name: 'app',
  components: {
    
  }
}
</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和store
router/index.js里面的 mode: ‘history’ 去掉请求路径的#
beforeEach是判断请求的啥路径,/直接到登录页,其他的判断有没有token,没有的话去登录页

import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '../views/login/Login.vue'
import Home from '../views/home/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'login',
    component: Login
  },
  {
    path: '/home',
    name: 'home',
    component: Home
  }
]

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

router.beforeEach((to, from, next) => {
  // eslint-disable-next-line no-debugger
  if (to.path === '/') {
    next();
  } else {
    let token = localStorage.getItem('Authorization');
    if (token === null || token === '') {
      next('/');
    } else {
      next();
    }
  }
})

export default router

store将token存放Authorization中

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
      // 存储token
      Authorization: localStorage.getItem('Authorization') ? localStorage.getItem('Authorization') : ''
  },
  mutations: {
     // 修改token,并将token存入localStorage
     changeLogin (state, user) {
      state.Authorization = user.Authorization;
      localStorage.setItem('Authorization', user.Authorization);
    }
  },
  actions: {
  },
  modules: {
  }
})

最后登录页 axios

<template>
  <el-form :rules="rules" :model="loginForm" ref="loginFormRef" class="login-container" label-position="left"
           label-width="0px" v-loading="loading">
    <h3 class="login_title">系统登录</h3>
    <el-form-item prop="name">
      <el-input type="text" v-model="loginForm.name" auto-complete="off" placeholder="账号"></el-input>
    </el-form-item>
    <el-form-item prop="password">
      <el-input type="password" v-model="loginForm.password" auto-complete="off" placeholder="密码"></el-input>
    </el-form-item>
    <el-checkbox class="login_remember" v-model="checked" label-position="left">记住密码</el-checkbox>
    <el-form-item style="width: 100%">
      <el-button type="primary" @click.native.prevent="submitClick" style="width: 100%">登录</el-button>
    </el-form-item>
  </el-form>
</template>
<script>
import {mapMutations} from "vuex";

  export default{
    data(){
      return {
        rules: {
          name: [{required: true, message: '请输入用户名', trigger: 'blur'}],
          password: [{required: true, message: '请输入密码', trigger: 'blur'}]
        },
        checked: true,
        loginForm: {
          name: '',
          password: ''
        },
        loading: false
      }
    },
    methods: {
       ...mapMutations(['changeLogin']),
      submitClick() {

        this.$refs.loginFormRef.validate((valid) => {
            if(valid){
                var _this = this;
                this.loading = true;
                this.$axios({
                    url:'/api/login',
                    method:'post',
                    data:{
                          username:this.loginForm.name,
                          password:this.loginForm.password
                    }
                }).then(resp=> {
                    _this.loading = false;
                    var data = resp.data;
                     if (resp.status == 200) { // eslint-disable-next-line no-debugger
                        //成功
                        var code = data.code;
                        if (code == '60000') {
                         
                           _this.userToken = data.token;
                          // 将用户token保存到vuex中
                          _this.changeLogin({ Authorization: _this.userToken });
                          _this.$message("登陆成功");
                          //跳页
                          this.$router.push({path:'home'})

                        } else {
                          _this.$message(data.message);
                        }
                    } else {
                        //失败
                         _this.$message(data.message);
                    }
                });

            }else{
                  _this.$message('密码或用户名错误');

            }
        })
      }
    }
  }
</script>
<style>
  .login-container {
    border-radius: 15px;
    background-clip: padding-box;
    margin:  auto;
    width: 350px;
    padding: 35px 35px 15px 35px;
    background: #fff;
    border: 1px solid #eaeaea;
    box-shadow: 0 0 25px #cac6c6;
  }

  .login_title {
    margin: 0px auto 40px auto;
    text-align: center;
    color: #505458;
  }

  .login_remember {
    margin: 0px 0px 35px 0px;
    text-align: left;
  }
</style>

下面是Home.vue
这里的HelloWorld用的项目生成时自带的HelloWorld,这页有“退出登录”按钮直接清除token,用来验证是否可以未登录跳到登录页。

<template>
  <div class="home">
    <!-- <img alt="Vue logo" src="../../assets/logo.png"> -->
    <HelloWorld msg="Welcome to Your Vue.js App"/>

     <!-- <el-container>
      <el-button @click="exit">退出登录</el-button>
      <el-button @click="test">携带token的测试请求</el-button>
    </el-container> -->
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  name: 'Home',
  components: {
    HelloWorld
  },
  methods:{
    exit(){
      //退出登录,清空token
      localStorage.removeItem('Authorization');
      // this.$router.push('/');
    },
    test(){
      this.$axios({

        url:'/api/loginTest',
        method:'get',
       
      }).then(function(res){
        console.log("res",res);
      }).catch(function(err){
        console.log("err",err);
      })
    }
  }

}
</script>

到目前为止,SpringBoot Vue 已经写完了。

三、Nginx部署项目

1.项目打包

Springboot直接使用Mavan中的 package打成jar包,配置都在上面pom.xml中

Vue 使用vscode 终端-npm:build,打成dist静态资源文件 。(npm run build 看个人喜好)

2.nginx配置信息

上面我们说到,vue所有包含/api的请求都转换为http://localhost:8887/*/api,到nginx配置中,我又觉得转了个寂寞
nginxi配置路径+文件名:nginx/conf/nginx.conf

# worker_processes 值越大,可以支持的并发处理量也越多
# 工作进程:数目。根据硬件调整,通常等于CPU数量或者2倍于CPU
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

# events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接
# 表示每个 work process 支持的最大连接数为 1024
events {
    worker_connections  1024;
}


http {
    # http全局块
    # http全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;


	# 负载均衡地址
	upstream backend {
		server localhost:8887;
	}
	server {

	# 监听端口80,root 就是vue打好dist包的路径
		listen       80;
		server_name  localhost;
		client_max_body_size 10m;
		root   D:vueProject/zlucky/dist;
	 
	 # 在dist中找index.html
		location / {
			try_files $uri /index.html; # vue history模式必须的配置
			index index.html;
		}
	 
		# 禁止缓存index.html页面
		location /index.html {
			add_header Cache-Control "no-cache, no-store, must-revalidate";
		}
	 
		# 缓存静态文件
		location ^~ /static/ {
			add_header Cache-Control "public,max-age=31536000";
		}
	 
		# 与后端api的请求匹配api,所以我说vue转了个寂寞,这又匹配了,而且和vue配置的毫无相关
		location ^~ /api{
				proxy_pass http://localhost:8887/luck/api;
				proxy_set_header X-Real-IP $remote_addr;
				proxy_set_header Host $host;
				proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
				proxy_read_timeout 300;
				proxy_send_timeout 300;
		}
		
		error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
	}
	
}
我把打好的jar、dist以及 nginx 放在Windows server 服务器上。不用Linux,因为不会太多命令,也费劲。 nginx直接运行nginx.exe文件,再启动Spring boot,大功告成
java -jar 项目打成的jar包名.jar 

四、页面展示

在这里插入图片描述
在这里插入图片描述

总结

趟一次坑就会了。希望hxd们多多指点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值