前后端分离介绍
不使用前后端分离开发存在那些问题?
传统的Java web开发中,例如使用静态模板、servlet + jsp等。以JSP为例,前端使用JSP开发,但是JSP并不是完全由后端开发者独立完成。其开发流程是先由前端人员写好HTML静态页面,之后由后端人员整合嵌入进JSP中。其中存在的问题是开发效率极低,当出现问题后,前端人员看不懂jsp代码,后端不懂前端的布局方式和代码,沟通成本很高,而且需要前端页面写好才能开始写后端代码。
使用前后端分离开发可解决上述问题
在前后端分离开发中,前端只需要独立编写客户端代码,后端也只需要独立编写服务端的代码提供数据接口即可,前端通过Ajax请求来访问后端的数据接口,后端将Model展示到view中即可。
前后端开发者只需要提前约定好接口文档(URL、参数、数据类型…),然后分别独立开发即可,前端可以通过假数据进行测试,完全不需要依赖于后端,后端可利用Postman、Swagger接口文档或浏览器进行测试,最后完成前后端集成即可,真正实现了前后端应用的解耦合,提升了开发效率
前后端分离技术将之前的单体应用拆分成前端应用 + 后端应用
前端应用:负责数据展示和用户交互
后端应用:负责提供数据处理接口
前端HTML 通过 Ajax 调用后端restful数据接口
通过下面两张图分别简单介绍单体应用和前后端分离应用
实现技术
目前主流的技术是使用Spring Boot + Vue进行开发
Spring Boot进行后端应用开发,Vue进行前端应用开发
前后端数据访问与展示
使用SpingBoot + Vue进行测试,SpringBoot创建项目,Vue创建项目
安装axios
在前端vue项目文件目录下以管理员身份打开cmd运行npm install --save axios
,运行后结果如下图所示
运行成功后全局引入axios,在vue前端项目中main.js文件插入代码
// 引入axios
import axios from 'axios';
// 挂载到vue原型链上
Vue.prototype.axios = axios;
axios安装好之后,在vue中编写代码请求后端数据
// 初始化操作,每个vue文件中的初始化函数
created(){
this.axios.get('http://localhost:8081/user/a').then(function(resp){
console.log(resp)
})
}
运行页面,打开浏览器的控制台,将报如下错误,这是因为没有解决跨域问题而报错
解决跨域问题
- 后端解决
新建java文件,编写如下代码
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class crossDominConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
-
前端解决
- 项目根目录下新建文件
vue.config.js
,并编写如下代码
module.exports = { devServer: { proxy: { '/api': { // /api表示拦截以/api开头的请求路径 target: 'http://localhost:8081', // 跨域的域名,一般指服务器地址 changeOrigin: true, // 是否开启跨域 pathRewrite:{ // 重写路径 '^/api':'' // 把/api变为空字符 } }, // 设置多个跨域代理 '/other':{ target: 'URL', changeOrigin: true, pathRewrite:{ '/other':'' } } } }
- 修改axios请求代码,将原先的服务器地址修改为 api
created(){ this.axios.get('api/user/a').then(function(resp){ console.log(resp) }) }
- 项目根目录下新建文件
请求数据并返回结果
<script>
export default{
name: "Display",
data(){
return{
msg: 'hello',
users:[ ]
}
},
// 初始化操作
created(){
const _this = this;
this.axios.get('http://localhost:8081/user/a').then(function(resp){
_this.users = resp.data;
})
// 第二种
const _this = this;
this.axios.get('api/ac',{params:{
username: _this.form.username,
password: _this.form.password,
code: _this.form.captcha,
}}).then(function(resp){
console.log(resp);
})
// 第三种
this.axios({
url: 'api/ac',
method: 'get',
params: this.form
}).then(function(resp){
console.log(resp)
}).catch(function(error){
onsole.log
})
}
}
</script>