阿里云服务器ESC部署前后端分离项目完整流程

news2024/10/4 22:48:09

阿里云服务器ESC部署服务完整流程

  • 准备
    • 安装软件
    • 1.安装jdk
    • 2.安装tomcat
    • 3.安装mysql
  • 后端应用功能编写及部署
    • 编写一个简单的用户增删改查功能
      • 发布流程
  • 前端功能应用及部署
    • 搭建前端框架
      • 准备:已安装npm
    • 页面
      • user.vue
      • userForm.vue
    • 跨域问题
    • 安装nginx
    • 配置nginx
  • 源码

准备

1.已买阿里云服务器或其他云服务器,此处以阿里云服务器为例子
2.服务器连接工具Xshell
3.使用xshll连接云服务器

安装软件

1.安装jdk

安装jdk步骤参考阿里云esc服务器部署javaj web环境中的安装jdk步骤
在这里插入图片描述
具体安装步骤如下
1.查看yum源中JDK版本

yum list java*

2.使用yum安装JDK1.8.0

yum -y install java-1.8.0-openjdk*

3.检查是否安装成功

java -version

出现以下内容,说明安装成功

[root@iZuspq7vnxm**** ~]# java -version
openjdk version "1.8.0_342"
OpenJDK Runtime Environment (build 1.8.0_342-b07)
OpenJDK 64-Bit Server VM (build 25.342-b07, mixed mode)

4.配置环境变量
a.查看JDK安装的路径

find /usr/lib/jvm -name 'java-1.8.0-openjdk-1.8.0*'

回显信息如下

[root@test000****~]# find /usr/lib/jvm -name 'java-1.8.0-openjdk-1.8.0*'
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.342.b07-1.el7_9.x86_64

b.打开配置文件

vim /etc/profile

c.在配置文件末尾,按i进入编辑模式
d. 添加以下信息。

     说明:JAVA_HOME值为当前JDK安装的路径。

java_home的值与安装的jdk路径保持一致。

JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.342.b07-1.el7_9.x86_64
PATH=$PATH:$JAVA_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME CLASSPATH PATH

e. 按下Esc键,输入:wq并回车以保存并关闭文件。

 f. 运行以下命令,立即生效环境变量。
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

2.安装tomcat

安装tomcat步骤参考阿里云esc服务器部署javaj web环境中的tomcat安装步骤
在这里插入图片描述

1.下载tomcat安装包

wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.88/bin/apache-tomcat-8.5.88.tar.gz  --no-check-certificate 
tar -zxvf apache-tomcat-8.5.88.tar.gz

2.当前目录会有一个tomcat压缩包
在这里插入图片描述
3.解压

tar -zxvf apache-tomcat-8.5.88.tar.gz

4.移动tomcat目录并改名为tomcat

sudo mv apache-tomcat-8.5.88 /usr/local/tomcat

5.新建普通用户。
原因:为保证系统安全性,建议创建一般用户来运行Tomcat。
例如,本示例中创建一般用户www

useradd www

6.将文件的所属用户设置为www

chown -R www.www /usr/local/tomcat/

在/usr/local/tomcat/目录下:

   · bin:存放Tomcat的一些脚本文件,包含启动和关闭Tomcat服务脚本。

   · conf:存放Tomcat服务器的各种全局配置文件,其中最重要的是server.xml和web.xml。

   · webapps:Tomcat的主要Web发布目录,默认情况下把Web应用文件放于此目录。

   · logs:存放Tomcat执行时的日志文件。

7.配置server.xml文件。
a,切换到/usr/local/tomcat/conf/目录

cd /usr/local/tomcat/conf/

b.重命名server.xml文件

mv server.xml server.xml_bk
mv server.xml server.xml_bk

c.新建一个server.xml文件
1)创建并打开server.xml文件

vi server.xml

2)按下i键,添加以下内容

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8006" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
<Listener className="org.apache.catalina.core.AprLifecycleListener"/>
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
 type="org.apache.catalina.UserDatabase"
 description="User database that can be updated and saved"
 factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
 pathname="conf/tomcat-users.xml"/>
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080"
 protocol="HTTP/1.1"
 connectionTimeout="20000"
 redirectPort="8443"
 maxThreads="1000"
 minSpareThreads="20"
 acceptCount="1000"
 maxHttpHeaderSize="65536"
 debug="0"
 disableUploadTimeout="true"
 useBodyEncodingForURI="true"
 enableLookups="false"
 URIEncoding="UTF-8"/>
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
  resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="/data/wwwroot/default" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/data/wwwroot/default" debug="0" reloadable="false" crossContext="true"/>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

3)按Esc键,输入:wq并回车以保存并关闭文件
8.设置JVM内存参数
a.创建并打开/usr/local/tomcat/bin/setenv.sh文件

vi /usr/local/tomcat/bin/setenv.sh

b. 按下i键,添加以下内容。

       指定JAVA_OPTS参数,用于设置JVM的内存信息以及编码格式。
JAVA_OPTS='-Djava.security.egd=file:/dev/./urandom -server -Xms256m -Xmx496m -Dfile.encoding=UTF-8'

c. 按下Esc键,输入:wq并回车以保存并关闭文件
9.设置Tomcat自启动脚本。
a. 运行以下命令,下载Tomcat自启动脚本。

        说明:该脚本来源于社区,仅供参考。阿里云对其可靠性以及操作可能带来的潜在影响,不做任何暗示或其他形式的承诺。如果您运行wget命令下载失败,您可以通过浏览器访问https://raw.githubusercontent.com/oneinstack/oneinstack/master/init.d/Tomcat-init直接获取脚本内容。
wget https://raw.githubusercontent.com/oneinstack/oneinstack/master/init.d/Tomcat-init

b.移动并重命名Tomcat-init

mv Tomcat-init /etc/init.d/tomcat

c.为/etc/init.d/tomcat添加可执行权限

chmod +x /etc/init.d/tomcat

d. 运行以下命令,设置启动脚本JAVA_HOME。

      重要:脚本中JDK的版本信息必须与您安装的JDK版本信息一致,否则Tomcat会启动失败。
sed -i 's@^export JAVA_HOME=.*@export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.342.b07-1.el7_9.x86_64@' /etc/init.d/tomcat                  

10.依次运行以下命令,设置Tomcat开机自启动。

chkconfig --add tomcat
chkconfig tomcat on

11.启动Tomcat

service tomcat start             

回显信息类似如下所示,表示启动Tomcat成功

[root@test000**** conf]# service tomcat start
Starting tomcat
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.342.b07-1.el7_9.x86_64
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.
Tomcat is running with pid: 11837            

3.安装mysql

参考阿里云esc服务搭建教程中的LAMP环境中的第3步
在这里插入图片描述
具体步骤如下:
1.下载安装mysql

wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm &&
yum -y install mysql57-community-release-el7-10.noarch.rpm &&
yum install -y mysql-community-server --nogpgcheck

2.启动mysql数据库

systemctl start mysqld.service

3.查看MySQL数据库初始密码

grep "password" /var/log/mysqld.log

4.登录数据库

mysql -uroot -p

5.修改MySQL默认密码

set global validate_password_policy=0;  #修改密码安全策略为低(只校验密码长度,至少8位)。
ALTER USER 'root'@'localhost' IDENTIFIED BY '12345678';

6.授予root用户远程管理权限


GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '12345678';

7.输入exit退出数据库

后端应用功能编写及部署

编写一个简单的用户增删改查功能

1.pom文件

<?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>user-service</artifactId>
    <version>1.0-SNAPSHOT</version>

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

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>

        <!--swagger-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.2</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.5.RELEASE</version>
            </plugin>
        </plugins>
    </build>
</project>

2.配置文件
注意:log配置是为了测试阶段有问题可以查看控制台打印的sql语句,正式发布可以去掉。

server:
  port: 12001
spring:
  application:
    name: test-user
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://120.78.64.120:3306/test?timeZone=Asia/Shanghai&characterEncoding=utf-8
    username: root
    password: Qfp11111(此处写自己的数据库密码)

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3.启动类

@SpringBootApplication
@EnableSwagger2
public class UserService {
    public static void main(String[] args) {
        SpringApplication.run(UserService.class,args);
    }
}

4.实体类

package com.test.user.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.util.Date;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-12-27 21:03
 */
@Data
@TableName("tb_user")
public class User {

    /**
     * 'id'
     */
    @TableId(type = IdType.AUTO)
    private Integer id;

    /**
     * ''用户名''
     */
    private String username;

    /**
     * '真实姓名'
     */
    private String realName;

    /**
     * '密码'
     */
    private String password;

    /**
     * '性别:0-男,1-女'
     */
    private String sex;

    /**
     * '生日'
     */
    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    private Date birthday;

    /**
     * '身份证号'
     */
    private String cardId;

    /**
     * '手机号'
     */
    private String phone;

}

5.分页插件(没有这个配置不分页)

package com.test.user.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 1
 */
@Configuration
public class MybatisConfig {

    /**
     * 添加分页插件
     * @return
     */
    @Bean
    public MybatisPlusInterceptor interceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

分页信息vo

package com.test.user.vo;

import lombok.Data;

import java.util.List;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2024-01-09 22:13
 */
@Data
public class PageResult<T> {
    /**
     * 总条数
     */
    private Long total;
    /**
     * 总页数
     */
    private Long totalPage;
    /**
     * 当前页数据
     */
    private List<T> items;

    public PageResult() {
    }

    public PageResult(Long total, List<T> items) {
        this.total = total;
        this.items = items;
    }

    public PageResult(Long total, Long totalPage, List<T> items) {
        this.total = total;
        this.totalPage = totalPage;
        this.items = items;
    }
}

6.接口

package com.test.user.controller;

import com.test.user.entity.User;
import com.test.user.service.UserService;
import com.test.user.vo.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-12-27 21:11
 */
@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("page")
    public ResponseEntity<PageResult<User>> page(
            @RequestParam(value = "pageIndex",defaultValue = "1")Integer pageIndex,
            @RequestParam(value = "pageSize",defaultValue = "5")Integer pageSize,
            @RequestParam(value = "username",required = false)String username
    ){
        PageResult<User> result = userService.selectPage(pageIndex, pageSize,username);
        return ResponseEntity.ok(result);
    }

    @GetMapping("getUserById")
    public User getUserById(Integer id){
        return userService.getById(id);
    }
    @PostMapping("save")
    public ResponseEntity save(@RequestBody User user){
        userService.saveOrUpdate(user);
        return ResponseEntity.ok("操作成功");
    }

    @DeleteMapping("delete")
    public ResponseEntity delete(Integer id){
        userService.removeById(id);
        return ResponseEntity.ok("操作成功");
    }
}


7.实现类

public interface UserService extends IService<User> {
    PageResult<User> selectPage(Integer pageIndex, Integer pageSize, String username);
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public PageResult<User> selectPage(Integer pageIndex, Integer pageSize,String username) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(username),User::getUsername,username);
        Page<User> userPage = userMapper.selectPage(new Page<>(pageIndex, pageSize), queryWrapper);
        return new PageResult<>(userPage.getTotal(),userPage.getPages(),userPage.getRecords());
    }
}

8.本地测试
启动程序,浏览器输入localhost:12001/doc.html,选择接口进行增删改查
在这里插入图片描述

9.功能测试无误,可以准备发布到云服务器。

发布流程

1.将项目打包获取jar包
idea右侧栏找到maven—>user-service—>package,左键双击,开始打包
在这里插入图片描述
控制台输出build success,说明打包成功,按照红色框的路径找到打包好的jar包
在这里插入图片描述
未指定打包路径时,会默认打包在该项目的target目录下
在这里插入图片描述
2.准备项目启动脚本
新建一个txt文件,后缀名改为.sh
添加内容如下

nohup java -jar user-service-1.0-SNAPSHOT.jar &

注意:可以现在txt文件中添加内容,再修改后缀。如果先修改后缀,则需要以记事本方式打开进行编辑。

3.上传文件到服务器
在服务器的输入rz,弹出文件选择框,将文件上传到云服务器
在这里插入图片描述
如果提示命令不存在
则需要输入命令

yum -y install lrzsz

上传成功后输入

ll

显示如下
在这里插入图片描述
4.运行应用
运行启动脚本
启动命令参考博客
Linux 下通过 java 命令启动 jar 包的几种常见方式

sh start.sh

在这里插入图片描述
因为我们没有指定日志文件,所以会默认将日志输入到nohup.out文件中
启动成功后可以查看是否成功

ps -ef |grep user-service

在这里插入图片描述
第一条记录说明启动成功
也可以查看日志
在这里插入图片描述

然后在浏览器输入云服务器公网地址+端口+doc.html
在这里插入图片描述
后端部署成功

前端功能应用及部署

搭建前端框架

准备:已安装npm

准备1:安装node.js
下载链接node.js
推荐下载LST版本
在这里插入图片描述
下载后自行安装
安装成功后,win+r,输入cmd,进入控制台查看版本

node -v

在这里插入图片描述
安装完成Node应该自带了NPM了,在控制台输入npm -v查看:在这里插入图片描述
npm默认的仓库地址是在国外网站,速度较慢,建议大家设置到淘宝镜像。但是切换镜像是比较麻烦的。推荐一款切换镜像的工具:nrm

我们首先安装nrm,这里-g代表全局安装

npm install nrm -g

在这里插入图片描述
然后通过nrm ls命令查看npm的仓库列表,带*的就是当前选中的镜像仓库:
在这里插入图片描述
通过nrm use taobao来指定要使用的镜像源:在这里插入图片描述
然后通过nrm test npm 来测试速度:
在这里插入图片描述
注意:

  • 安装完成请一定要重启下电脑!!!
  • 安装完成请一定要重启下电脑!!!
  • 安装完成请一定要重启下电脑!!!

1.新建一个空项目
在这里插入图片描述
2.空项目中新建模板
idea2020.1新建java web项目选择javaScript,给项目命令后完成
在这里插入图片描述
3.打开命令窗口
在这里插入图片描述
4.安装vue-cli

npm install -g vue-cli

a.用vue-cli命令,快速搭建一个webpack的项目:

vue init webpack

在这里插入图片描述
在这里插入图片描述
前面几项都走默认或yes

下面这些我们选no
在这里插入图片描述

最后,再选yes,使用 npm安装
在这里插入图片描述
在这里插入图片描述
安装好的项目结构:
在这里插入图片描述
5.本地测试运行
在命令窗口运行命令npm run dev 或者 npm start 都可以启动项目

npm run dev

运行完成
在这里插入图片描述
如果运行后提示如下,说明未安装依赖,运行npm 安装后再运行
在这里插入图片描述

点击链接后页面如下
在这里插入图片描述
ui页面参考网址
本博客使用vuetify地址:vuetify
vue2.0参考
vue2.0
注意:使用前先安装
在这里插入图片描述

vue3.0参考:
elementUI

页面

user.vue

<template>
  <v-card>
    <v-card-title>
      <v-btn @click="addUser" color="primary">新增用户</v-btn>
      <v-spacer/>
      <v-text-field
        append-icon="search"
        label="输入用户名搜索"
        single-line
        hide-details
        v-model="search"
      />
    </v-card-title>
    <v-divider/>
    <v-data-table
      :headers="headers"
      :items="userList"
      :pagination.sync="pagination"
      :total-items="totalUsers"
      :loading="loading"
      class="elevation-1"
    >
      <template slot="items" slot-scope="props">
        <td class="text-xs-center">{{ props.item.id }}</td>
        <td class="text-xs-center">{{ props.item.username }}</td>
        <td class="text-xs-center">{{ props.item.realName }}</td>
        <td class="text-xs-center">{{ props.item.birthday }}</td>
        <td class="text-xs-center">{{ props.item.sex===0 ? '男':'女' }}</td>
        <td class="text-xs-center">{{ props.item.cardId }}</td>
        <td class="text-xs-center">{{ props.item.phone }}</td>
        <td class="justify-center layout px-0">
          <v-btn icon @click="editUser(props.item)">
            <i class="el-icon-edit"/>
          </v-btn>
          <v-btn icon @click="deleteUser(props.item)">
            <i class="el-icon-delete"/>
          </v-btn>
        </td>
      </template>
      <template slot="expand" slot-scope="props">
        <v-card flat>
          <v-card-text>Peek-a-boo!</v-card-text>
        </v-card>
      </template>
      <template slot="no-data">
        <v-alert :value="true" color="info" icon="info">
          无数据
        </v-alert>
      </template>
      <template slot="pageText" slot-scope="props">{{props.itemsLength}},当前:{{ props.pageStart }} - {{ props.pageStop }}
      </template>
    </v-data-table>

    <v-dialog v-model="show" max-width="600" scrollable v-if="show">
      <v-card>
        <v-toolbar dark dense color="primary">
          <v-toolbar-title>{{isEdit ? '修改用户' : '新增用户'}}</v-toolbar-title>
          <v-spacer/>
          <v-btn icon @click="show = false">
            <v-icon>close</v-icon>
          </v-btn>
        </v-toolbar>
        <v-card-text class="px-5 py-2">
          <!-- 表单 -->
          <user-form :oldUser="oldUser" :isEdit="isEdit" @close="show = false" :reload="getDataFromApi"/>
        </v-card-text>
      </v-card>
    </v-dialog>
  </v-card>

</template>

<script>
  import UserForm from './UserForm'

  export default {
    name: "user",
    components: {
      UserForm
    },
    data() {
      return {
        search: '',// 过滤字段
        totalUsers: 0, // 总条数
        userList: [], // 当前页用户数据
        loading: true,
        pagination: {},// 分页信息
        headers: [// 表头
          {text: 'id', align: 'center', value: 'id'},
          {text: '用户名称', align: 'center', sortable: false, value: 'username'},
          {text: '真实姓名', align: 'center', sortable: false, value: 'realName'},
          {text: '生日', align: 'center', sortable: false, value: 'birthday'},
          {text: '性别', align: 'center', value: 'sex', sortable: false,},
          {text: '身份证号', align: 'center', value: 'cardId', sortable: false,},
          {text: '手机号', align: 'center', value: 'phone', sortable: false,},
          {text: '操作', align: 'center', value: 'id', sortable: false}
        ],
        show: false,// 是否弹出窗口
        oldUser: {}, // 用户信息
        isEdit: false // 判断是编辑还是新增
      }
    },
    watch: {
      pagination: {
        handler() {
          this.getDataFromApi();
        },
        deep: true
      },
      search: {
        handler() {
          this.getDataFromApi();
        }
      },
      show(val, oldVal) {
        // 表单关闭后重新加载数据
        if (oldVal) {
          this.getDataFromApi();
        }
      }
    },
    mounted() {
      this.getDataFromApi();
    },
    methods: {
      addUser() {
        this.user = {};
        this.isEdit = false;
        this.show = true;
      },
      editUser(item) {
        this.oldUser = item;
        this.isEdit = true;
        this.show = true;
      },
      deleteUser(item) {
        this.$message.confirm('此操作将永久删除该用户, 是否继续?').then(() => {
          // 发起删除请求
          this.$http.delete("/user/delete?id=" + item.id,)
            .then(() => {
              // 删除成功,重新加载数据
              this.$message.success("删除成功!");
              this.getDataFromApi();
            })
        }).catch(() => {
          this.$message.info("删除已取消!");
        });

      },
      getDataFromApi() {
        this.$http.get("/user/page", {
          params: {
            username: this.search, // 搜索条件
            pageIndex: this.pagination.page,// 当前页
            pageSize: this.pagination.rowsPerPage,// 每页大小
          }
        }).then(resp => { // 这里使用箭头函数
          this.userList = resp.data.items;
          this.totalUsers = resp.data.total;
          // 完成赋值后,把加载状态赋值为false
          this.loading = false;
        })
      }
    }
  }
</script>

<style scoped>

</style>

userForm.vue

<template>
  <v-form v-model="valid" ref="UserForm">
    <v-text-field
      label="用户名称"
      v-model="user.username"
      :rules="[v => !!v || '用户名称不能为空']"
      :counter="30"
      required
    />
    <v-text-field
      label="真实姓名"
      v-model="user.realName"
      :rules="[v => !!v || '真实姓名不能为空']"
      required
    />
    <v-text-field
      label="密码"
      v-model="user.password"
      :rules="[v => !!v || '密码不能为空']"
      required
    />
    <v-text-field
      label="生日"
      v-model="user.birthday"
      :rules="[v => !!v || '生日不能为空']"
      required
      type="date"
    />
    <v-text-field
      label="身份证号"
      v-model="user.cardId"
      :rules="[v => !!v || '身份证号不能为空']"
      required
    />
    <v-text-field
      label="手机号"
      v-model="user.phone"
      :rules="[v => !!v || '手机号不能为空']"
      required
    />
    <v-container fluid>
      <p>性别:</p>
      <v-radio-group v-model="user.sex" inline>
        <v-radio label="男" value=0></v-radio>
        <v-radio label="女" value=1></v-radio>
      </v-radio-group>
    </v-container>
    <v-layout class="my-4">
      <v-btn @click="submit" color="primary">提交</v-btn>
      <v-btn @click="clear" color="warning">重置</v-btn>
    </v-layout>
  </v-form>
</template>

<script>
  import config from '@/config';
  export default {
    name: "user-form",
    props: {
      oldUser: Object,
      isEdit: {
        type: Boolean,
        default: false
      },
      show: {
        type: Boolean,
        default: true
      }
    },
    data() {
      return {
        baseUrl: config.api,
        valid:false,
        user: {
          username: "",
          realName: "",
          password: "",
          sex: 0,
          birthday: "",
          cardId: "",
          phone: "",
        },
      }
    },
    watch: {
      oldUser:{
        deep:true,
        immediate:true,
        handler(val){
         this.user = Object.deepCopy(val,this.user)
        }
      }
    },
    methods: {
      submit() {
        // 表单校验
        if (this.$refs.UserForm.validate()) {
          this.$http({
            method: 'post',
            url: '/user/save',
            data: this.user
          }).then(() => {
            // 关闭窗口
            this.$message.success("保存成功!");
            this.closeWindow();
          }).catch(() => {
            this.$message.error("保存失败!");
          });
        }
      },
      clear() {
        // 重置表单
        this.$refs.userForm.reset();
      },
      closeWindow(){
        this.$emit("close");
      }
    }
  }
</script>
<style scoped>

</style>

前端项目源码地址:博客web源码

跨域问题

页面请求接口报错
在这里插入图片描述
后端项目添加一个配置类

package com.test.user.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2024-01-10 20:24
 */
@Configuration
public class GlobalCorsConfig {

    @Bean
    public CorsFilter corsFilter(){
        //1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //1) 允许的域,不要写*,否则cookie就无法使用了--目前没有登录校验功能,不需要cookie,允许所有请求
        config.addAllowedOrigin("*");
        //2) 是否发送Cookie信息
        config.setAllowCredentials(true);
        //3) 允许的请求方式
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PATCH");
        // 4)允许的头信息
        config.addAllowedHeader("*");

        //2.添加映射路径,我们拦截一切请求
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);

        //3.返回新的CorsFilter.
        return new CorsFilter(configSource);
    }
}

6.打包到服务器
先打包

npm run build

打包后的文件在dist目录下
在这里插入图片描述
注意打包时将config.js文件中的访问IP改为公网IP
在这里插入图片描述
改为公网IP
在这里插入图片描述

把整个dist文件夹压缩成一个user-web.zip文件上传到服务器,
先切换到自己的目录

cd /root/myService/testUserWeb/

使用命令

rz

将压缩包传到服务器上
然后解压

unzip user-web.zip

此时需要nginx对路径做配置

安装nginx

参考博客:linux环境下载安装linux
如果不知道对应的版本,建议使用docker安装
参考博客
安装nginx docker
如果买了阿里云服务器,可以登录阿里云官网,在ecs实例页面,搭建微信小程序的第2步有安装nginx的步骤,可以按照步骤安装
在这里插入图片描述
本人是阿里云服务器,按照截图中的步骤安装。

配置nginx

切换到nginx目录下

cd /etc/nginx

备份配置文件

cp nginx.conf nginx.conf.bak

修改配置文件
a.进入编辑模式

vim nginx.conf

添加如下内容

server {
        listen       9001;
        server_name localhost;
	root  /root/myService/testUserWeb/user-web;
	location / {
	   try_files $uri $uri/ /index.html;
	}

	location /api {
	   proxy_pass http://127.0.0.1:12001;
	}

    }

注意:root后面是前端包的路径,需要跟前端包名保持一致
重启nginx

nginx -s reload

最后在浏览器输入公网ip+端口,显示页面,前后端分离项目发布成功。(功能验证步骤跳过)

在这里插入图片描述

源码

后端源码地址:testUser源码地址
前端源码地址:testUserWeb源码地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1412468.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Maya的ai功能有哪些?Maya Assist是什么?

Autodesk Maya是一款流行的 3D 建模软件&#xff0c;艺术家和设计师使用它来创建现实的世界和表面。该软件以其与各种工具开发人员的合作而闻名&#xff0c;它允许多个工具的无缝集成以改进功能。Autodesk 的 Maya 刚刚发布了 Maya Assist&#xff0c;在 3D 建模和动画领域树立…

架构篇12:架构设计流程-评估和选择备选方案

文章目录 架构设计第 3 步:评估和选择备选方案评估和选择备选方案实战小结上一篇我们聊了设计备选方案,在完成备选方案设计后,如何挑选出最终的方案也是一个很大的挑战,主要原因有: 每个方案都是可行的,如果方案不可行就根本不应该作为备选方案。没有哪个方案是完美的。例…

MES系统计划排产功能,助你提升生产效率

MES系统的排产功能是基于企业的生产需求与资源情况进行制定的。首先&#xff0c;需要明确生产计划的目标和要求&#xff0c;包括计划产量、交货期限、生产能力等。然后&#xff0c;根据企业的生产资源情况&#xff0c;包括人员、设备、原材料等&#xff0c;制定生成计划。在MES…

Java链表(1)

&#x1f435;本篇文章将对单链表进行讲解&#xff0c;模拟实现单链表中常见的方法 一、什么是链表 链表是一种逻辑结构上连续而物理结构上不一定连续的线性表&#xff0c;链表由一个一个节点组成&#xff1a; 每一个节点中都由数据域&#xff08;val&#xff09;和指针域&…

食品加工厂可视化视频AI智能监管方案,助力工厂数字化运营

一、背景与需求分析 随着科技的不断进步和人们对食品安全和质量的日益关注&#xff0c;食品智慧工厂的建设成为了食品行业的一个重要趋势。智能化的食品工厂可以利用先进的技术和自动化系统&#xff0c;提高生产效率、降低监管成本&#xff0c;并确保产品的质量和安全。 行业…

使用GtkSharp下载zip包过慢问题解决方案

背景 安装GtkSharp这个包准备使用C#进行跨平台窗体应用程序开发&#xff0c;运行时发现其需要从github上下载【https://github.com/GtkSharp/Dependencies/raw/master/gtk-3.24.24.zip】这个依赖包&#xff0c;不知道是被墙了还是咋的&#xff0c;下载超时导致运行失败。 解决…

泛型..

1.泛型 所谓泛型 在类定义处是一种类型参数(我们平常所见到的参数指的就是方法中的参数 他接收有外界传递来的值 然后在方法中进行使用) 在类内部的话 则充当一种占位符 并且还提高了代码的复用率 何以见得提高了代码的复用率 其实就是通过对比使用了泛型技术和没有使用泛型技…

VS2019下各种报错合集(持续更新)

VS2019下的各种报错处理(长期更新)&#xff0c;欢迎大家在评论区补充错误代码/描述 解决方案&#xff01;&#xff01;&#xff01; 1、printf 代码运行到printf函数打印不出来内容&#xff0c;打断点之后&#xff0c;f10走过去&#xff0c;程序直接运行起来了&#xff0c;而…

Linux下串口編程遇到的接收数据错误及原因(

近日在调试串口的时候发现&#xff0c;另一设备向我ARM板的串口发送0x0d&#xff0c;我接收之后变成了0x0a&#xff0c;这是问题一&#xff1b;另外当对方向我发送一串数据&#xff0c;如果其中有0x11&#xff0c;那么我总是漏收此数&#xff0c;这是问题二。 由于问题莫名其妙…

深度视觉目标跟踪进展综述-论文笔记

中科大学报上的一篇综述&#xff0c;总结得很详细&#xff0c;整理了相关笔记。 1 引言 目标跟踪旨在基于初始帧中指定的感兴趣目标( 一般用矩形框表示) &#xff0c;在后续帧中对该目标进行持续的定位。 基于深度学习的跟踪算法&#xff0c;采用的框架包括相关滤波器、分类…

【SVA断言_2023.01.24】

在RTL设计中&#xff0c;仿真时查看异常情况&#xff0c;异常出现时&#xff0c;断言会报警&#xff0c;断言占整个设计的比例应不少于30% assertion作用&#xff1a; 检查特定条件或事件序列的出现情况提供功能覆盖 断言失败的严重程度&#xff1a;$fatal&#xff08;中止仿…

Oracle RAC 集群的安装(保姆级教程)

文章目录 一、安装前的规划1、系统规划2、网络规划3、存储规划 二、主机配置1、Linux主机安装&#xff08;rac01&rac02&#xff09;2、配置yum源并安装依赖包&#xff08;rac01&rac02&#xff09;3、网络配置&#xff08;rac01&rac02&#xff09;4、存储配置&#…

FitSM与ITIL及ITSM的对比

FitSM 是一种轻量级 IT 服务管理&#xff08;ITSM&#xff09;标准&#xff0c;其所有材料都是免费提供的&#xff0c;旨在促进 IT 服务提供中的服务管理&#xff0c;包括联合场景。但是&#xff0c;FitSM 适合您的组织吗&#xff1f;了解 FitSM 的适用性涉及两个方面。首先需要…

阿里云PAI-DSW部署ChatGLM3过程记录

1、申请免费的阿里云 PAI-DSW 资源&#xff0c;这个比较基础不做介绍了 2、从第二步开始&#xff0c;我们介绍部署ChatGLM3过程&#xff1a;PAI-DSW 资源界面如下图&#xff1a;点击开启新终端 3、默认目录下面建一个test目录&#xff0c;如下图&#xff1a; 4、执行命令cd te…

TPCC-MySQL

简介 TPC-C是专门针对联机交易处理系统&#xff08;OLTP系统&#xff09;的规范&#xff0c;一般情况下我们也把这类系统称为业务处理系统。 Tpcc-mysql是percona基于TPC-C(下面简写成TPCC)衍生出来的产品&#xff0c;专用于MySQL基准测试。其源码放在launchpad上&#xff0c…

2023年NOC大赛(学而思赛道)创意编程Python初中组决赛真题

2023年NOC大赛&#xff08;学而思赛道&#xff09;创意编程Python初中组决赛真题 题目总数&#xff1a;7 总分数&#xff1a;100 编程题 第 1 题 问答题 二进制回文 编程实现: 输入一个正整数&#xff0c;判断它的二进制形式是否是回文数&#xff0c;如果是输出True…

Web开发5:第三方扩展与部署

在Web开发中&#xff0c;第三方扩展和部署是提高开发效率和功能扩展的重要手段。第三方扩展可以帮助我们快速集成常用功能和工具&#xff0c;而部署则是将我们的应用程序发布到生产环境中。本文将介绍第三方扩展的重要性、如何选择和使用常见的第三方扩展&#xff0c;并讨论应用…

code server安装使用教程

1. 安装 1.1. 下载code-server安装包 类似这种文件&#xff1a;code-server-3.10.2-linux-amd64.tar.gz 解压&#xff1a;tar -xvf code-server-3.10.2-linux-amd64.tar.gz 1.2 &#xff08;可选&#xff09;建立软连接 ln -s path/to/code-server-3.10.2-linux-amd64/bin…

力扣15、三数之和(中等)

1 题目描述 图1 题目描述 2 题目解读 在整数数组nums中&#xff0c;找出三元组&#xff0c;它们的和为0&#xff0c;要求返回所有和为0且不重复的三元组。这是两数之和的扩展题目&#xff0c;可以将三数之和问题。 3 解法一&#xff1a;排序 双指针 将整数数组排序之后&#…

阿里云快速搭建《幻兽帕鲁》服务器自建指南

如何自建幻兽帕鲁服务器&#xff1f;基于阿里云服务器搭建幻兽帕鲁palworld服务器教程来了&#xff0c;一看就懂系列。本文是利用OOS中幻兽帕鲁扩展程序来一键部署幻兽帕鲁服务器&#xff0c;阿里云百科aliyunbaike.com分享官方基于阿里云服务器快速创建幻兽帕鲁服务器教程&…