image

微信截图_20241224112451

引言

在当今Web开发中,后端 Spring Boot 和前端Vue 通过前后端分离架构来结合,已经是一个成熟的主流技术栈了。

这种前后端分离的架构方式,目前广泛应用于约90%以上通过Java开发的Web应用中。

但是,对于为何弃用了之前服务端渲染页面的方式,而选择了前后端分离架构,现有大多数开发者和企业都是懵懵懂懂,甚至有些公司还觉得,之前一个人能干的项目,现在变成了两个人干,增加了成本和复杂度,降低了效益。

我们今天就来探讨一下

  1. 什么是服务端渲染页面?
  2. 传统服务端渲染页面的缺点。
  3. 什么是前端后端分离架构?
  4. 为什么选择前端后端分离架构?

什么是服务端渲染页面

在传统的服务端渲染页面中,通常采用模板引擎技术来渲染 HTML 页面,例如 JSP 和 Thymeleaf 等。它们的工作方式如下:

  1. JSP(JavaServer Pages)

    • JSP 是 Java 的一种服务器端技术,允许在 HTML 页面中嵌入 Java 代码。
    • 当客户端请求 JSP 页面时,Web 容器会编译并执行 JSP 中的 Java 代码,生成动态的 HTML 页面返回给客户端浏览器。
    • JSP 页面中的 Java 代码与 HTML 代码高度耦合,难以分离。
    • JSP 的编写和调试比较繁琐,代码可维护性较差。
  2. Thymeleaf

    • Thymeleaf 相较于JSP是一种相对现代的服务端 Java 模板引擎,用于 Web 和独立环境。
    • Thymeleaf 通过引入一套属性语言,使开发者在 HTML 文件中可以使用服务端数据。
    • Thymeleaf 提供了一组标签,使开发者在模板中可以执行基本的编程操作,如循环、判断等。
    • 相比 JSP,Thymeleaf 使用更加简洁、可维护性更强。

虽然两种模板语言不同,但是对于服务端最终输出和前端调用的方式大致相同。

示例代码

model.addAttribute()​ 是 Spring MVC 提供的用于服务器端模板渲染的数据绑定方法。通过该方法,开发者可以将数据模型注入到模板引擎(如 Thymeleaf、JSP)中,实现动态页面渲染。

后端编写接口(Spring Boot)


@RestController
public class UserController {

    @GetMapping("/users")
    public String listUsers(Model model) {
        // 准备模型数据
        List<User> users = Arrays.asList(
                new User(1, "Tom", 25),
                new User(2, "Jerry", 30),
                new User(3, "Spike", 28)
        );
        model.addAttribute("users", users);
      
        // 返回模板名称
        return "userlist";
    }
}

Thymeleaf 模板语言调用



<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>User List</title>
</head>
<body>
    <h1>User List</h1>
    <table>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Age</th>
        </tr>
        <tr th:each="user : ${users}">
            <td th:text="${user.id}"></td>
            <td th:text="${user.name}"></td>
            <td th:text="${user.age}"></td>
        </tr>
    </table>
</body>
</html>

在这个示例中,后端控制器准备了模型数据 users,并将其传递给 Thymeleaf 模板进行渲染。

Thymeleaf 通过 th:each 循环遍历 users 列表,并使用 th:text 属性将用户信息插入到 HTML 表格中。

可以看出,无论是 Thymeleaf 还是 JSP,它们的工作原理都是将后端准备的模型数据插入到模板中,生成动态 HTML 页面。

不同之处在于,Thymeleaf 使用了自定义属性,而 JSP 使用了标签库和 EL 表达式。

传统服务端渲染页面的缺点

1. 耦合度高,难以分离前后端代码

在服务端渲染页面中,模板语言的代码与后端业务逻辑代码高度耦合在一起。

前端开发人员需要了解后端语言和框架,后端开发人员也需要涉及前端代码知识,导致前后端分工不清晰,相当于两份工一个人干了,虽然整体看人员少,但是实际工时和两人基本无差,项目周期无法缩短,效率方面无法提升。

2. 制约前端技术发展

传统模板语言的功能有限,无法完全利用现代前端框架(Vue/React)的数据驱动视图、组件化等特性,极大的限制了前端技术的发展。

3. 页面渲染效率低下

服务端渲染页面需要经过模板引擎的渲染过程,对于数据频繁变动的场景(如单页面应用),页面的局部更新需要重新渲染整个页面,导致浪费服务器资源,降低了渲染效率。

4. 用户体验不佳

服务端渲染页面为了获取新数据,通常需要进行整页刷新,这会中断用户的操作,形成体感断层,影响用户体验。

5. 缺乏灵活性

在传统模式下,前端使用后端框架的模板语言,技术选型缺乏灵活性。

比如后端使用 Java,那前端就只能使用 JSP 或 Thymeleaf。

6. 可维护性和扩展性较差

由于前后端代码高度耦合,功能的扩展和迭代维护都较为困难。

什么是前端后端分离架构

前端后端分离架构是指前端(客户端)和后端(服务器端)分别独立开发,通过 HTTP/HTTPS 等网络通信协议进行数据交互的一种架构模式。

前端后端分离架构大致包含以下几个部分:

  1. 前端: 负责构建用户界面,处理用户交互,发送 HTTP 请求获取或提交数据。常用技术栈有 Vue、React、Angular 等。
  2. 后端: 负责处理业务逻辑,持久化数据,提供 API 接口供前端调用。常用技术栈有 Java(Spring Boot)、Node.js、Python(Django)等。
  3. API 接口: 前后端通过统一的 RESTful API 接口进行通信和数据交互。
  4. 数据库: 存储应用程序数据。

示例代码

后端代码

##实体
public class User {
    private Long id;
    private String name;
    private Integer age;
  
    // getter/setter/constructor
}

//controller层
@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping
    public List<User> listUsers() {
        List<User> users = Arrays.asList(
            new User(1L, "Tom", 25),
            new User(2L, "Jerry", 30),
            new User(3L, "Spike", 28)
        );
        return users;
    }
}

在这个示例中,后端提供了一个 /api/users​ 的 RESTful API 接口,用于返回用户列表数据。

前端 Vue 代码示例

<template>
  <div>
    <h1>User List</h1>
    <table>
      <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Age</th>
      </tr>
      <tr v-for="user in users" :key="user.id">
        <td>{{ user.id }}</td>
        <td>{{ user.name }}</td>
        <td>{{ user.age }}</td>
      </tr>
    </table>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  data() {
    return {
      users: []
    }
  },
  mounted() {
    axios.get('/api/users')
      .then(response => {
        this.users = response.data
      })
      .catch(error => {
        console.log(error)
      })
  }
}
</script>

在这个示例中,Vue 组件在 mounted​ 生命周期钩子中使用 axios​ 库向后端的 /api/users​ 接口发送 GET 请求,获取用户列表数据,并将其渲染到表格中。

通过这个示例,我们可以看到前后端分离架构的核心思想:

  • 后端提供 RESTful API 接口,负责处理业务逻辑和数据操作。
  • 前端通过 HTTP 请求调用后端提供的 API 接口,获取所需的数据。
  • 前端负责rendering页面,处理用户交互。

为什么选择前端后端分离架构?

相比传统服务端渲染,前端后端分离架构能带来以下好处:

  1. 开发效率高: 前后端分工明确,专业的工作由相应的人员来完成,两个人分工合作,有利于提高整体项目开发效率,降低周期。
  2. 用户体验好: 前端可通过 Axios 等技术实现页面无刷新更新数据,提升用户体验。
  3. 扩展性和维护性强: 代码低耦合,易于扩展和维护。
  4. 更好的复用性: 前后端分离后,前后端项目都可以方便地移植到其他项目中复用。
  5. 前后端技术选型灵活: 前后端分离后,前后端可以自由选择合适的技术栈,避免技术的单一束缚。
  6. 部署方便: 前后端代码分离后,前后端项目可单独部署。
  7. 适应移动互联网: 前端通过响应式设计或构建移动端应用,适应移动互联网时代。

总的来说,前端后端分离架构有利于提高开发效率,改善用户体验,增强项目的扩展性和可维护性。

总结

前后端分离架构是当下 Web 应用开发的主流架构模式,它将前端和后端的职责分离,使得前端专注于构建用户界面和交互,后端专注于处理业务逻辑和数据操作,前后端团队能够独立开展工作,同时确保最终系统的高效运行与易用性。

在当下大环境,项目利润率降低,周期越来越短,弃用模板语言使用前后端分离架构,不仅能给企业带来更快的项目响应时间,还能给使用的客户带来更好的体感效果,这是以前模板语言所不具备的。