一、前后端交互架构概览
二、spring boot 后端接口实现
2.1 基础rest控制器
@restcontroller @requestmapping("/api/users") @crossorigin // 处理跨域,生产环境应配置具体域名 public class usercontroller { @autowired private userservice userservice; // 获取用户列表 @getmapping public responseentity<list<userdto>> getusers( @requestparam(required = false) string name) { list<userdto> users = userservice.findusers(name); return responseentity.ok(users); } // 获取单个用户 @getmapping("/{id}") public responseentity<userdto> getuser(@pathvariable long id) { userdto user = userservice.getuserbyid(id); return responseentity.ok(user); } // 创建用户 @postmapping public responseentity<userdto> createuser( @valid @requestbody usercreaterequest request) { userdto newuser = userservice.createuser(request); return responseentity.status(httpstatus.created).body(newuser); } // 更新用户 @putmapping("/{id}") public responseentity<userdto> updateuser( @pathvariable long id, @valid @requestbody userupdaterequest request) { userdto updateduser = userservice.updateuser(id, request); return responseentity.ok(updateduser); } // 删除用户 @deletemapping("/{id}") public responseentity<void> deleteuser(@pathvariable long id) { userservice.deleteuser(id); return responseentity.nocontent().build(); } }
2.2 dto设计示例
用户创建请求dto:
@data public class usercreaterequest { @notblank(message = "用户名不能为空") @size(max = 50, message = "用户名最长50个字符") private string username; @notblank(message = "密码不能为空") @size(min = 6, max = 20, message = "密码长度6-20位") private string password; @email(message = "邮箱格式不正确") private string email; @pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") private string phone; }
用户响应dto:
@data @jsoninclude(jsoninclude.include.non_null) public class userdto { private long id; private string username; private string email; private string phone; @jsonformat(pattern = "yyyy-mm-dd hh:mm:ss") private localdatetime createtime; }
2.3 全局异常处理
@restcontrolleradvice public class globalexceptionhandler { // 处理验证异常 @exceptionhandler(methodargumentnotvalidexception.class) public responseentity<errorresponse> handlevalidationexception( methodargumentnotvalidexception ex) { list<string> errors = ex.getbindingresult() .getfielderrors() .stream() .map(error -> error.getfield() + ": " + error.getdefaultmessage()) .collect(collectors.tolist()); errorresponse response = new errorresponse( "validation_failed", "参数验证失败", errors); return responseentity.badrequest().body(response); } // 处理业务异常 @exceptionhandler(businessexception.class) public responseentity<errorresponse> handlebusinessexception( businessexception ex) { errorresponse response = new errorresponse( ex.getcode(), ex.getmessage(), null); return responseentity.status(ex.getstatus()).body(response); } }
三、vue 前端接口调用
3.1 axios 封装
// src/utils/request.js import axios from 'axios' import { message } from 'element-ui' import store from '@/store' import router from '@/router' // 创建axios实例 const service = axios.create({ baseurl: process.env.vue_app_base_api, timeout: 10000 }) // 请求拦截器 service.interceptors.request.use( config => { // 添加token if (store.getters.token) { config.headers['authorization'] = 'bearer ' + store.getters.token } return config }, error => { return promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( response => { const res = response.data // 业务错误处理 if (res.code && res.code !== 200) { message({ message: res.message || 'error', type: 'error', duration: 5 * 1000 }) // 特定状态码处理 if (res.code === 401) { // 跳转登录 } return promise.reject(new error(res.message || 'error')) } else { return res } }, error => { // http错误处理 message({ message: error.message, type: 'error', duration: 5 * 1000 }) return promise.reject(error) } ) export default service
3.2 api模块化封装
// src/api/user.js import request from '@/utils/request' // 获取用户列表 export function getusers(params) { return request({ url: '/api/users', method: 'get', params }) } // 获取用户详情 export function getuser(id) { return request({ url: `/api/users/${id}`, method: 'get' }) } // 创建用户 export function createuser(data) { return request({ url: '/api/users', method: 'post', data }) } // 更新用户 export function updateuser(id, data) { return request({ url: `/api/users/${id}`, method: 'put', data }) } // 删除用户 export function deleteuser(id) { return request({ url: `/api/users/${id}`, method: 'delete' }) }
3.3 vue组件中调用示例
<template> <div> <el-table :data="userlist"> <!-- 表格内容 --> </el-table> <el-dialog :visible.sync="dialogvisible"> <el-form :model="userform" :rules="rules" ref="userform"> <!-- 表单内容 --> </el-form> </el-dialog> </div> </template> <script> import { getusers, createuser } from '@/api/user' export default { data() { return { userlist: [], dialogvisible: false, userform: { username: '', password: '', email: '', phone: '' }, rules: { username: [ { required: true, message: '请输入用户名', trigger: 'blur' }, { max: 50, message: '长度不超过50个字符', trigger: 'blur' } ], // 其他验证规则... } } }, created() { this.fetchusers() }, methods: { // 获取用户列表 async fetchusers() { try { const { data } = await getusers({ name: this.searchname }) this.userlist = data } catch (error) { console.error('获取用户列表失败:', error) } }, // 提交表单 submitform() { this.$refs.userform.validate(async valid => { if (valid) { try { await createuser(this.userform) this.$message.success('创建成功') this.dialogvisible = false this.fetchusers() // 刷新列表 } catch (error) { console.error('创建用户失败:', error) } } }) } } } </script>
四、接口交互关键点详解
4.1 请求参数传递方式
参数类型 | 前端传递方式 | 后端接收方式 |
---|---|---|
url路径参数 | /users/123 | @pathvariable long id |
url查询参数 | /users?name=john&age=20 | @requestparam string name |
请求体json参数 | {name:"john",age:20} | @requestbody userdto user |
表单参数 | formdata对象 | @modelattribute userform form |
请求头参数 | headers: {authorization: ...} | @requestheader string token |
4.2 跨域解决方案
spring boot 配置类:
@configuration public class corsconfig implements webmvcconfigurer { @override public void addcorsmappings(corsregistry registry) { registry.addmapping("/api/**") .allowedorigins("http://localhost:8080", "https://yourdomain.com") .allowedmethods("get", "post", "put", "delete", "options") .allowedheaders("*") .allowcredentials(true) .maxage(3600); } }
4.3 文件上传处理
后端接收:
@postmapping("/upload") public responseentity<string> uploadfile( @requestparam("file") multipartfile file) { if (file.isempty()) { throw new businessexception("文件不能为空"); } string filename = filestorageservice.storefile(file); return responseentity.ok(filename); }
前端上传:
// 使用formdata上传文件 const formdata = new formdata() formdata.append('file', file) uploadfile(formdata).then(response => { // 处理响应 })
五、接口安全增强
5.1 jwt认证实现
spring security配置:
@configuration @enablewebsecurity public class securityconfig extends websecurityconfigureradapter { @override protected void configure(httpsecurity http) throws exception { http.csrf().disable() .authorizerequests() .antmatchers("/api/auth/**").permitall() .anyrequest().authenticated() .and() .addfilter(new jwtauthenticationfilter(authenticationmanager())) .addfilter(new jwtauthorizationfilter(authenticationmanager())) .sessionmanagement() .sessioncreationpolicy(sessioncreationpolicy.stateless); } }
vue前端处理:
// 登录示例 login({ username, password }).then(response => { const { token } = response.data commit('set_token', token) localstorage.setitem('token', token) // 设置axios默认携带token axios.defaults.headers.common['authorization'] = `bearer ${token}` })
5.2 接口限流防护
@restcontroller @requestmapping("/api/products") public class productcontroller { @ratelimiter(value = 10, key = "'product_list'") // 10次/秒 @getmapping public list<product> listproducts() { return productservice.findall(); } }
六、接口文档生成
6.1 swagger集成
spring boot配置:
@configuration @enableswagger2 public class swaggerconfig { @bean public docket api() { return new docket(documentationtype.swagger_2) .select() .apis(requesthandlerselectors.basepackage("com.example.controller")) .paths(pathselectors.any()) .build() .apiinfo(apiinfo()); } private apiinfo apiinfo() { return new apiinfobuilder() .title("电商系统api文档") .description("前后端接口定义") .version("1.0") .build(); } }
6.2 接口注释示例
@api(tags = "用户管理") @restcontroller @requestmapping("/api/users") public class usercontroller { @apioperation("获取用户列表") @apiimplicitparams({ @apiimplicitparam(name = "name", value = "用户名", paramtype = "query") }) @getmapping public responseentity<list<userdto>> getusers(string name) { // ... } }
七、性能优化建议
7.1 接口缓存策略
@cacheable(value = "users", key = "#id") @getmapping("/{id}") public userdto getuser(@pathvariable long id) { return userservice.getuserbyid(id); }
7.2 分页查询优化
后端实现:
@getmapping public pageresult<userdto> getusers( @requestparam(defaultvalue = "1") int page, @requestparam(defaultvalue = "10") int size) { pageable pageable = pagerequest.of(page - 1, size); page<userdto> userpage = userservice.findusers(pageable); return new pageresult<>(userpage.getcontent(), userpage.gettotalelements()); }
前端调用:
getusers({ page: this.currentpage, size: this.pagesize }).then(response => { this.userlist = response.data.list this.total = response.data.total })
八、常见问题解决方案
8.1 日期时间处理
后端配置:
# application.yml spring: jackson: time-zone: gmt+8 date-format: yyyy-mm-dd hh:mm:ss
前端处理:
import moment from 'moment' // 格式化日期 moment(user.createtime).format('yyyy-mm-dd hh:mm:ss')
8.2 大数字精度丢失
后端处理:
@jsonserialize(using = tostringserializer.class) private long id;
8.3 接口版本管理
@restcontroller @requestmapping("/api/v1/users") public class usercontrollerv1 { // v1版本接口 } @restcontroller @requestmapping("/api/v2/users") public class usercontrollerv2 { // v2版本接口 }
通过以上方案,spring boot和vue可以实现高效、安全的前后端接口交互。实际开发中应根据项目需求选择合适的传参方式、安全策略和性能优化方案。
到此这篇关于springboot+vue 前后端接口交互的项目实践的文章就介绍到这了,更多相关springboot vue 前后端接口交互内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论