springboot+vue+nginx简单项目的开发和部署

工作不是很饱和的情况下,就有时间去研究一下技术上的东西,然后打算写一篇比较长的啰嗦的文章来记录一下

一、准备工作

首先要有一台云服务器(其他替代的能作为服务器的设备也行,最好是linux),然后我是提前配置好了java环境,OPENJDK或者ORACLEJDK都行,这两个的区别自行百度吧。

二、后端开发

新建一个springboot项目,然后可以用默认的起步依赖就行,我是多加了一个swagger的依赖

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

目录结构如下所示

下面是SwaggerConfig类的代码,不过不用也没有啥影响

package com.zxc.springtest001.config;

import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration//托管spring
@EnableSwagger2//开启swagger功能
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket( DocumentationType.SWAGGER_2 )
                // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
                .apiInfo( apiInfo() )
                // 设置哪些接口暴露给Swagger展示
                .select()
                // (第一种方式)扫描所有有注解的api,用这种方式更灵活
                .apis( RequestHandlerSelectors.withMethodAnnotation( ApiOperation.class ) )
                // (第二种方式)扫描指定包中的swagger注解
                //.apis(RequestHandlerSelectors.basePackage("com.zxc.springtest001.controller"))
                // (第三种方式)扫描所有
                //.apis(RequestHandlerSelectors.any())
                .paths( PathSelectors.any() )
                .build();
    }

    /**
     * 添加摘要信息
     */
    private ApiInfo apiInfo() {
        // 用ApiInfoBuilder进行定制
        return new ApiInfoBuilder()
                // 设置标题
                .title( "标题:应用API文档" )
                // 描述
                .description( "描述:向前端提供应用的ResultFul风格接口文档" )
                // 作者信息
                .contact( "zhx" )
                // 版本
                .version( "版本号:" + "V1.0.0" )
                .build();
    }
}

InterfaceUtils和ResultVo就是封装了一下返回值的结构,没啥好说的

package com.zxc.springtest001.utils;



import com.zxc.springtest001.enums.ResultEnum;
import com.zxc.springtest001.vo.ResultVo;


public class InterfaceUtil {
    public static ResultVo success() {
        return new ResultVo(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getInfo(), null);
    }

    public static ResultVo success(Object data) {
        return new ResultVo(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getInfo(), data);
    }

    public static ResultVo error(String info) {
        return new ResultVo(ResultEnum.SERVICE_ERROR.getCode(), info, null);
    }

    public static ResultVo error(ResultEnum resultEnum) {
        return new ResultVo(resultEnum.getCode(), resultEnum.getInfo(), null);
    }

    public static ResultVo error(ResultEnum resultEnum, String info) {
        return new ResultVo(resultEnum.getCode(), info, null);
    }

    public static ResultVo error(Integer code, String info) {
        return new ResultVo(code, info, null);
    }
}

 

package com.zxc.springtest001.vo;

import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel
public class ResultVo<T> {
    private Integer code;
    private String info;
    private T data;

}

 

主要逻辑就在Controller中,其实也是非常简单的两个方法,由于重点在部署,所以逻辑直接写在Controller中,但是实际开发中千万不要这样做

 

package com.zxc.springtest001.controller;

import com.zxc.springtest001.utils.InterfaceUtil;
import com.zxc.springtest001.vo.ResultVo;
import com.zxc.springtest001.vo.GetVo;
import com.zxc.springtest001.vo.TableList;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@CrossOrigin
@Api("测试方法controller")
public class TestController {
    @ApiOperation(value = "get方法请求")
    @GetMapping("/getList")
    public ResultVo getList(String param){
        if (param != null){
            GetVo getVo = new GetVo();
            getVo.setUserName("yiyuzz");
            return InterfaceUtil.success(getVo);
        }
        return InterfaceUtil.error("传入参数为空");
    }

    @ApiOperation(value = "post方法请求")
    @PostMapping("/postList")
    public ResultVo<List<TableList>> postList(){
        List<TableList> tableList = new ArrayList<>();
        tableList.add(new TableList("张三","男","呜呜呜呜呜"));
        tableList.add(new TableList("李四","女","啊啊啊啊啊"));
        tableList.add(new TableList("王五","男","嗷嗷嗷嗷嗷"));
        return InterfaceUtil.success(tableList);
    }
}

然后配置文件里面写一下端口就行了,后端就写完了

 

三、前端开发

前端对我这种菜鸟来说还是太生疏了点,o(╥﹏╥)o。

框架是用的Vue,所以要先搭好环境,然后编译器的话IDEA、WebStorm、VScode都行,我是直接用vue脚手架创建了一个项目,然后执行npm install命令加载依赖,npm run dev 启动项目

要做修改的地方主要有两个

一是页面上要有一个向后端发送get请求的操作,还有一个发送post请求的操作

二是要通过axios发送请求包,接收响应包,并且携带参数,这里也涉及到跨域请求的问题,后面细说

先附上一个目录结构吧,要修改或者新增的红色标注

main.js文件如下所示,elementui和axios先引入

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 axios from 'axios'
import VueAxios from 'vue-axios'

Vue.config.productionTip = false

Vue.use(ElementUI);

Vue.use(VueAxios,axios);

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  render: h => h(App)
})

新建一个组件,然后把根路由指过去

import Vue from 'vue'
import Router from 'vue-router'
import FirstPage from '@/components/FirstPage'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'FirstPage',
      component: FirstPage
    }
  ]
})

然后新建一个http.js文件设置axios的请求拦截和响应拦截,其实这个拦截器只是做了简单的错误处理,然后设置了一下默认的baseURL(这个是访问后端地址的基础),还有要注意的是import是从axios依赖中导入的,然后拦截器写完了之后用export导出,这是为了后面封装请求方法时能直接使用拦截器。

import axios from 'axios';

axios.defaults.timeout = 20000;
// 返回其他状态吗
axios.defaults.validateStatus = function (status) {
  return status >= 200 && status <= 500; // 默认的
};

// 跨域请求,允许保存cookie
axios.defaults.withCredentials = true;
//设置默认url
axios.defaults.baseURL = '/api';

axios.interceptors.request.use(
    (config) => {
      return config;
    },
    (error) => {
      return Promise.reject(error);
    }
  );
  // HTTPresponse拦截
  axios.interceptors.response.use(
    (res) => {
      const status = Number(res.status) || 200;
      // 如果是白名单类型放入catch自行处理
      if (status !== 200) {
        return Promise.reject(res);
      }
      return res.data;
    },
    (error) => {
      return Promise.reject(new Error(error));
    }
  );
  
  export default axios;

新建一个api.js封装请求方法,可以看到这里的axios是从http.js当中导入的,所以是直接带有拦截器的,然后封装了get和post方法(其实post方法里面的参数我没有用到,写不写都行),然后这里的url是一个相对url,完整的url是baseURL + url 这样,并且导出,让他们在项目其他组件可用

import axios from '../axios/http';


export const getList = (param) => {
    return axios({
      url: `/getList`,
      method: 'get',
      params: {
          param,
      }
    });
  };
  
  
  export const postList = (params) => {
    return axios({
      url: `/postList`,
      method: 'post',
      data:params
    });
  };

const api = {
    getList,
    postList,
}

export default api;

然后就是FIrstPage这个页面了,是真的丑,这里getList方法是传入了参数,然后当执行created函数的时候调用,而点击按钮的时候执行post请求

<template>
    <div align="left">
        <h1>程序首页</h1>
        <div >
            我是:{{userName}}<br>
        </div>
        <div align="center">
            <h3>正常的表单</h3>
            <br>
            <el-table class="table" :data="tableList" border >
                <el-table-column prop="name" label="姓名" width="100"></el-table-column>
                <el-table-column prop="sex" label="性别" width="100"></el-table-column>
                <el-table-column prop="information" label="简介" width="100"></el-table-column>
            </el-table>
            <br>
            <el-button @click="postList">获取表单数据</el-button>
        </div>
    </div>
</template>

<script>
import api from '../axios/api';
export default {
    name: 'first-page',
    data(){
        return {
            userName: '',
            flag: '1',
            tableList: [],
        }
    },
    created(){
        this.getList(this.flag);
    },
    mounted(){
        // this.getList('1');
    },
    methods: {
        getList(param){
            api.getList(param).then((res) => {
            // if (res.code === 0) {
                console.log('get请求返回成功')
                this.userName = res.data.userName;
            // }
            });
        },
        postList(params){
            api.postList(params).then((res) => {
                console.log('post请求返回成功')
                this.tableList = res.data;
            });
        }
    }
}
</script>
<style scoped>
.table {
    text-align: center;
    font-family: Arial, Helvetica, sans-serif;
    border-collapse: collapse;
    width: 301px;
}
</style>

比较关键的就是配置一个本地代理来解决跨域的问题,这个在服务器上可以由nginx来处理,因为我的脚手架版本是2.9.6,所以找到config文件夹下index.js文件,修改proxyTable中的值,之前bsseURL中的'/api'就是用的这里配置的,而这个字符串的意义就是允许跨域的方式(changeOrigin)请求http://localhost:8081(后端地址和端口),前端地址可以看到是http://localhost:8082

 

到此为止,已经可以在本地启动一下前后端,联调测试一下功能

四、安装Nginx

先到Nginx官网下载一个安装包,既然是linux系统,那就下个tar.gz

服务器我是买的腾讯云的,然后连接工具用的putty,文件传输工具用winscp

然后安装前的环境准备,借鉴于大神的文章https://www.cnblogs.com/lywJ/p/10710361.html

1.需要安装gcc环境

# yum install gcc-c++

2.第三方的开发包

1 PERE

PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 perl 兼容的正则表达式库。

nginx的http模块使用pcre来解析正则表达式,所以需要在linux上安装pcre库。

注:pcre-devel是使用pcre开发的一个二次开发库。nginx也需要此库

# yum install -y pcre pcre-devel

2 zlib

zlib库提供了很多种压缩和解压缩的方式,nginx使用zlib对http包的内容进行gzip,所以需要在linux上安装zlib库。

# yum install -y zlib zlib-devel

3 openssl

OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,

并提供丰富的应用程序供测试或其它目的使用。

nginx不仅支持http协议,还支持https(即在ssl协议上传输http),所以需要在linux安装openssl库。

# yum -y install pcre  pcre-devel zlib  zlib-devel openssl openssl-devel

然后通过WinSCP工具把安装包上传到服务器,随便找个喜欢的文件夹放吧

用下面的命令将压缩包解压到/usr/local目录下

# tar -xvf nginx-1.14.0.tar.gz -C /usr/local

 

使用configure命令创建一个makeFile文件

./configure \
--prefix=/usr/local/nginx \
--pid-path=/usr/local/nginx/logs/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi \--with-http_stub_status_module \--with-http_ssl_module \--with-file-aio \--with-http_realip_module

请进入nginx-1.18.0目录下执行configure命令,然后和原文章相比,我修改了pid-path的路径,因为原文中这个路径会导致nginx重启报错

注意:启动nginx之前,上边将临时文件目录指定为/var/temp/nginx,

需要在/var下创建temp及nginx目

创建目录/var/temp/nginx/

# mkdir /var/temp/nginx -p

-p 表示级联创建的意思

 进入nginx-1.18.0里面执行make命令进行编译

 [root@VM-0-13-centos nginx-1.18.0]# make

 进入nginx-1.18.0里面执行make install 命令进行安装

 这里不需要再次执行安装路径,创建makefile文件的时候已经指定了。

[root@VM-0-13-centos nginx-1.18.0]# make install

 进入安装位置/usr/local/nginx查看目录结构

 

其中html是里面首页html文件。conf里面是配置文件。sbin里面只执行文件。我新建了logs文件用来存放日志,也是为了解决pid文件的问题

进入sbin目录,执行命令./nginx

[root@VM-0-13-centos sbin]# ./nginx

查看nginx是否启动

[root@VM-0-13-centos sbin]# ps -aux | grep nginx

ps命令用于报告当前系统的进程状态。

-a:显示所有终端机下执行的程序,除了阶段作业领导者之外。

a:显示现行终端机下的所有程序,包括其他用户的程序。

u:以用户为主的格式来显示程序状况。

x:显示所有程序,不以终端机来区分。

关闭nginx

[root@admin sbin]#  ./nginx -s stop

或者

[root@admin sbin]# ./nginx -s quit

 

刷新配置文件

[root@admin sbin]# ./nginx -s reload

 

关闭防火墙,开启远程访问

首先需要关闭防火墙:默认端口是80

方法一:永久开放80端口

/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT
/etc/rc.d/init.d/iptables save

方法二:临时关闭系统防火墙

# service iptables stop  

方法三:永久关闭修改配置开机不启动防火墙

# chkconfig iptables off 

如果成功启动了nginx,那可以在浏览器直接访问服务器地址测试一下,成功的话会有welcome to nginx页面

五、部署应用

首先是前端使用npm run build 打包,生成dist文件夹

 

后端使用maven install命令打包就可以,会在target目录下面生成一个可执行jar

 

把后台打好的包放到随便一个自己能找到的文件夹下面,要保证有java运行环境就行

把前端的dist文件夹下面的内容放到nginx的html目录下面,覆盖原有的index.html文件

然后就是要配置一下nginx的conf配置文件,这个是nginx起作用的关键,无论是当一个http服务器用,还是做负载均衡,或者是虚拟主机,配置文件都会起到非常关键的作用

这个文件有一些默认的配置,针对于当前项目,我们只需要修改server中的内容就可以了,listen监听80端口(前提是保证服务器的防火墙不会拦截80端口),server_name由于我没有申请域名,也不想改hosts文件,就直接用localhost服务器地址了

我们已经把前端vue项目部署到nginx的html文件夹下面了,所以root根路径就设置到html文件夹,首页就是vue的index.html

后台的访问需要配置代理,和我们在本地配置的思路一样,需要注意的是proxy_pass后面的地址是后端程序的访问地址和端口,记得地址最后一定要加  /  保证代理会起作用

配置好之后 我们重启nginx然后加载一下新的配置文件,然后检查一下nginx的进程

使用nohup java -jar xxx &命令启动后台程序

OK,现在来访问一下!

首页进入的时候通过getList方法获取到用户,然后点击按钮获取表单数据

 

 

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值