优秀的编程知识分享平台

网站首页 > 技术文章 正文

Vue + SpringBoot 项目实战(三):我的助手之前后端联调

nanyue 2025-01-11 15:54:43 技术文章 2 ℃

在前面两篇文章中,已经对这个项目进行了基本的介绍。接下来就进一步完善这个项目。后来觉得每篇文章的标题不能清晰表达含义,然后对文章的标题都进行了统一了修改。同时,这篇文章的篇幅较长、涉及的知识点比较多。希望各位小伙伴可以耐心看完,一定能够有所收获!

下面废话不多说,直接肝!

后端项目创建

选择使用 Spring Initializr,配置好右侧的内容之后,点击创建。


现在SpringBoot创建时,基本上都是3.x版本。可以先行创建一个项目,然后在pom.xml文件中进行调整为2.x版本。下面介绍完成之后,会附上详细的 pom.xml 文件。

完善后端项目

后端项目运行

在浏览器打开 localhost:8843发现是这样子,到这里,后端项目也创建好了。之所以报错,那是因为我们还没有进行页面的开发。

前端与后端项目的协同调试

知识点补充:

1.前后端分离项目通信

前后端分离的意思是,前后端通过Restful API 传递JSON数据进行交流。

2.对于前端项目是如何运行的?

这个是我搜集的一些资料,我不是专业的前端,不能误导大家。下面进行一些分享,仅供参考。要是有小伙伴能补充说明,更好。在开发阶段,前面有提到,我们是使用 Vue UI 进行创建的项目,使用Vue UI 图形化 创建的项目,在开发阶段通常会使用Vue CLI提供的开发服务器,该服务器基于 webpack-dev-server 实现,可以提供热重载和实时更新等功能。这个开发服务器是基于Node.js构建的,但它仅用于开发阶段,生产环境通常不会使用它。所以,在开发阶段,它是基于Node.js服务器运行的。也就是说,我创建的项目是运行在Node.js服务器上的,感觉这样说也没毛病。

3.对于后端项目是如何运行的?

对于后端项目,在SpringBoot项目中,会内置一个服务器Tomcat,当项目运行成功之后,可以在上面的截图中,看到一个8843 端口,这个就是Tomcat服务器为我们提供的一个端口号。

4.前后端项目通信

在前后端项目通信时,通常使用HTTP协议进行。具体来说,前端项目会向后端发送HTTP请求,后端接收到请求之后,并将处理结果以HTTP响应的形式返回给前端。这种通信方式是基于请求-响应模式的。即前端发起请求,后端响应请求。现在的话,只说这一个就行。

在Vue项目中,常用的HTTP请求库包括AxiosFetch API等。在这里,我们使用 Axios来进行发送请求。

5.前端项目结构

上面这个图,可以作为一个参考。其中下面的一个链接,是找到的相关资料。链接如下:「链接」

前端页面开发

LoginIn.vue

首先我们开发登录页面组件,右键 src\components 文件夹,新建一个文件夹 LoginManager 然后在该文件夹下,右键该文件夹,New -> Vue Component,新建一个文件命名为 Login,如果没有 Vue Component 这个选项,可以选择新建一个 File,命名为 Login.vue 即可。目录结构及代码如下:

<template>
  <div>
      用户名:<input type="text" v-model="loginForm.username" placeholder="请输入用户名"/>
      <br><br>
      密码: <input type="password" v-model="loginForm.password" placeholder="请输入密码"/>
      <br><br>
      <button v-on:click="login">登录</button>
  </div>
</template>

<script>

  export default {
    name: 'LoginIn',
    data () {
      return {
        loginForm: {
          username: '',
          password: ''
        },
        responseResult: []
      }
    },
    methods: {
      login () {
        this.$axios
          .post('/login', {
            username: this.loginForm.username,
            password: this.loginForm.password
          })
          .then(successResponse => {
            if (successResponse.data.code === 200) {
              this.$router.replace({path: '/index'})
            }
          })
          .catch(failResponse => {
          })
      }
    }
  }
</script>

AppIndex.vue组件

右键 src\components 文件夹,新建一个文件夹 commonManager ,然后在commonManager 下新建一个 HomePage.vue ,即首页组件。

<template>
    <div>
        Welcom to AdminIndex
    </div>
</template>

<script>
</script>

<style>
</style>

前端项目相关配置

设置反向代理

修改 src\main.js 代码如下

import Vue from 'vue'
import App from './App'
import router from './router'
// 设置反向代理,前端请求默认发送到 http://localhost:8443/api
var axios = require('axios')
axios.defaults.baseURL = 'http://localhost:8843/api'
// 全局注册,之后可在其他组件中通过 this.$axios 发送数据
Vue.prototype.$axios = axios
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  router, // 将路由实例注入到根Vue 实例
  store, // 将status注入到根Vue 实例当中
  render: h => h(App)
}).$mount('#app')

在这里使用了一个模块叫做 axios,因此需要使用命令 npm install --save axios,以安装这个模块儿。

配置页面路由

修改 src\router\index.js 代码如下:

import Vue from 'vue'
import Router from 'vue-router'
// 导入刚才编写的组件
import AppIndex from '@/components/commonManager/HomePage'
import Login from '@/components/loginManager/LoginIn'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/login',
      name: 'Login',
      component: LoginIn
    },
    {
      path: '/index',
      name: 'AppIndex',
      component: HomePage
    }
  ]
})

运行项目

找到 README.md 中 的 命令行:npm run serve 。等待执行成功之后,然后打开一个浏览器网页,输入下面图片中的网址,注意地址是 http://自己的IP地址:8080/#/login ,中间有这个 # 是因为 Vue 的路由使用了 Hash 模式,是单页面应用的经典用法。可以在路由配置中选择使用 History 模式,但会引发一些问题,需要在后端作出处理,之后单独写一篇关于这个的文章。

运行成功之后,可以看到下图:

到这里,一个简易的前端登录功能就完成了。接下来是后端项目的开发。

后端项目结构

登录功能开发

当进行开发时,切记不可直接动手写代码,这个习惯不可取。因为这样写出来的代码,第一点是质量难以保证。第二点就是,当直接写时,自己的思维很容易被局限。有些细微的点考虑不到。正确的步骤如下:

第一步:进行需求分析。

需求:简单说,我要做一个登录功能。接下来就对它进行分析。首先要做的就是,我需要接收到前端传入的“用户名”、“密码”。接着,根据“用户名”、“密码”,去数据库进行匹配。最后。我把查询到的结果返回给前端。

第二步:在“演草纸”上写下操作步骤。

第一步分析之后,下面就进行“演算”。首先接收前端传入的“用户名”、“密码”。在后端,我们需要定义一个方法,能够让前端的请求找到对应的后端路径。接着要做的就是需要 定义一个“用户实体类”;接着,去数据库进行匹配,这意味着,我们需要编写一条sql,能够根据“用户名”、“密码”去数据库的用户表查找。这个我熟,打开Navicat,哐哐一顿编写。完事儿。最后,把查询到的结果返回给用户,从数据库查询的结果,无非两种,一种是存在该用户;一种是不存在该用户;

第三步:再动手写代码。

有了以上两个步骤之后,下面就进入到实际代码编写当中。按照已经写好的步骤,先定义一个用户实体类。

LoginController控制层

// 在工作中,尽量写上注释,虽然讨厌写,但是它确实在之后的工作中能够帮到我
/**
 * @ClassName LoginController
 * @Description 登录控制器类
 * @Author liuBaiHui
 * @Version 1.0
 */
@RestController
@RequestMapping("/api")
public class LoginController {

  @Autowired
  private LoginService loginService;

  /*
  * @description 登录接口
  * @param userVo:
  * @return: com.lbh.study.common.ResultVO<com.lbh.study.pojo.SysUser>
  * @author liuBaiHui
  */
  @PostMapping("/login")
  public ResultVO<SysUser>  userLogin(@RequestBody UserDto userDto){
      // 1.登录接口
      SysUser sysUser = loginService.userLogin(userDto);
      ResultVO<SysUser> success = ResultUtils.success(sysUser);
      return success;
  }
}

SysUser实体类

// 这里使用了 lombok的一些功能,使用注解可以帮助我们快速创建 getter、setter、toString方法。
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@TableName("sys_user")
public class SysUser implements Serializable {
  // 主键ID
  private Integer id;
  // 用户名
  private String username;
  // 密码
  private String password;
  // 手机号
  private String phone;
  // 创建时间
  private LocalDateTime createTime;
  // 更新时间
  private LocalDateTime updateTime;
  // 正常、锁定标识 (0-正常;1:锁定)
  private String lockFlag;
  // 逻辑删除标识(0:显示; 1:隐藏)
  private String delFlag;
  // 昵称
  private String nickName;
  // 邮箱
  private String email;
  // 头像
  private String avatar;
}

UserDao

Data Access Object(数据访问对象,DAO)即用来操作数据库的对象。

@Mapper
public interface SysUserDao  {
    SysUser selectByObject(@Param("userDto") UserDto userDto);
}

UserDaoMapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lbh.study.dao.SysUserDao">


    <select id="selectByObject" resultType="com.lbh.study.pojo.SysUser">
        SELECT  *  FROM sys_user
        <where>
            <if test="userDto.username !=null and userDto.username !=''">
                username = #{userDto.username}
            </if>
            <if test="userDto.password !=null and userDto.password !=''">
                AND  password = #{userDto.password}
            </if>
        </where>
    </select>
</mapper>

LoginService

public interface LoginService  {
    SysUser userLogin(UserDto userDto);
}

LoginServiceImpl实现类

@Service
public class LoginServiceImpl  implements LoginService {

    @Autowired
    private SysUserDao sysUserDao;

    @Override
    public SysUser userLogin(UserDto userDto) {
        // 1.定义一个结果集对象
        SysUser sysUser = sysUserDao.selectByObject(userDto);
        return sysUser;
    }
}

通用结果类Result

@Data
public class ResultVO<T> implements Serializable {
  // 1.状态码
  private Integer code;
  // 2.内容
  private T data;
  // 3.消息
  private String message;
  // 4.描述
  private String description;
  // 5.有参构造方法
  public ResultVO(Integer code, T data, String message, String description){
    this.code =  code;
    this.data = data;
    this.message = message;
    this.description = description;
  }

  // 6.构造方法
  public ResultVO(Integer code, T data){
    this(code,data,"","");
  }

  public ResultVO(Integer code, T data, String message){
    this(code,data,message,"");
  }
}

以上就是一个功能开发的整个流程。介绍了从前端到后端整个开发流程。下面分别运行前端项目、后端项目。在前端输入用户、密码之后。在进行通信时,一般会报错,跨域报错,下面是如何通过后端解决跨域的。它也有其他的解决方法。

配置跨域

在前后端进行响应时,一般会遇到跨域问题。在这里,使用在后端进行配置,解决跨域请求。

在上面的 “后端项目架构” 当中,有一个 config 包,创建一个CorsConfig.java 类。代码如下:

@Configuration
public class CorsConfig {

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //1.允许任何来源
        corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*"));
        //2.允许任何请求头
        corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
        //3.允许任何方法
        corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
        //4.允许凭证
        corsConfiguration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        CorsFilter corsFilter = new CorsFilter(source);

        FilterRegistrationBean<CorsFilter> filterRegistrationBean = new FilterRegistrationBean<>(corsFilter);
       // 小于 SpringSecurity Filter的 Order(-100) 即可。这个地方后面再说原因。
      filterRegistrationBean.setOrder(-101);  

        return filterRegistrationBean;
    }
}

配置跨域之后,点击登录,分别看下前端和后端项目的响应结果。

后端项目查询数据库的sql打印

可以看到,它已经到了 index 首页。符合我们的预期。

到这里,整个前后端项目的流程就搭建完成了。篇幅较长。

Tags:

最近发表
标签列表