在当今Web开发中,后端 Spring Boot 和前端Vue 通过前后端分离架构来结合,已经是一个成熟的主流技术栈了。
这种前后端分离的架构方式,目前广泛应用于约90%以上通过Java开发的Web应用中。
但是,对于为何弃用了之前服务端渲染页面的方式,而选择了前后端分离架构,现有大多数开发者和企业都是懵懵懂懂,甚至有些公司还觉得,之前一个人能干的项目,现在变成了两个人干,增加了成本和复杂度,降低了效益。
我们今天就来探讨一下
在传统的服务端渲染页面中,通常采用模板引擎技术来渲染 HTML 页面,例如 JSP 和 Thymeleaf 等。它们的工作方式如下:
JSP(JavaServer Pages)
Thymeleaf
虽然两种模板语言不同,但是对于服务端最终输出和前端调用的方式大致相同。
model.addAttribute()
是 Spring MVC 提供的用于服务器端模板渲染的数据绑定方法。通过该方法,开发者可以将数据模型注入到模板引擎(如 Thymeleaf、JSP)中,实现动态页面渲染。
@RestController
public class UserController {
@GetMapping("/users")
public String listUsers(Model model) {
// 准备模型数据
List users = Arrays.asList(
new User(1, "Tom", 25),
new User(2, "Jerry", 30),
new User(3, "Spike", 28)
);
model.addAttribute("users", users);
// 返回模板名称
return "userlist";
}
}
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>User Listtitle>
head>
<body>
<h1>User Listh1>
<table>
<tr>
<th>IDth>
<th>Nameth>
<th>Ageth>
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 等网络通信协议进行数据交互的一种架构模式。
前端后端分离架构大致包含以下几个部分:
//实体
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 接口,用于返回用户列表数据。
<template>
<div>
<h1>User Listh1>
<table>
<tr>
<th>IDth>
<th>Nameth>
<th>Ageth>
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 请求,获取用户列表数据,并将其渲染到表格中。
通过这个示例,我们可以看到前后端分离架构的核心思想:
相比传统服务端渲染,前端后端分离架构能带来以下好处:
总的来说,前端后端分离架构有利于提高开发效率,改善用户体验,增强项目的扩展性和可维护性。
前后端分离架构是当下 Web 应用开发的主流架构模式,它将前端和后端的职责分离,使得前端专注于构建用户界面和交互,后端专注于处理业务逻辑和数据操作,前后端团队能够独立开展工作,同时确保最终系统的高效运行与易用性。
在当下大环境,项目利润率降低,周期越来越短,弃用模板语言使用前后端分离架构,不仅能给企业带来更快的项目响应时间,还能给使用的客户带来更好的体感效果,这是以前模板语言所不具备的。