跳到主要内容Spring Boot + Vue 前后端接口交互全流程详解 | 极客日志Java大前端java
Spring Boot + Vue 前后端接口交互全流程详解
Spring Boot 与 Vue 的前后端接口交互流程。涵盖架构概览、REST 控制器实现、DTO 设计、全局异常处理;前端 Axios 封装、API 模块化及组件调用;参数传递方式、跨域配置、文件上传;JWT 认证、接口限流;Swagger 文档生成;以及缓存、分页等性能优化方案。提供完整代码示例与常见问题解决方案,助力高效安全开发。
JavaCoder25 浏览 一、前后端交互架构概览

二、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);
ResponseEntity.status(HttpStatus.CREATED).body(newUser);
}
ResponseEntity<UserDTO> {
userService.updateUser(id, request);
ResponseEntity.ok(updatedUser);
}
ResponseEntity<Void> {
userService.deleteUser(id);
ResponseEntity.noContent().build();
}
}
return
@PutMapping("/{id}")
public
updateUser
(@PathVariable Long id, @Valid @RequestBody UserUpdateRequest request)
UserDTO
updatedUser
=
return
@DeleteMapping("/{id}")
public
deleteUser
(@PathVariable Long id)
return
2.2 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;
}
@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 封装
import axios from 'axios'
import { Message } from 'element-ui'
import store from '@/store'
import router from '@/router'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 10000
})
service.interceptors.request.use(
config => {
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 => {
Message({ message: error.message, type: 'error', duration: 5 * 1000 })
return Promise.reject(error)
}
)
export default service
3.2 API 模块化封装
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 跨域解决方案
@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);
}
const formData = new FormData()
formData.append('file', file)
uploadFile(formData).then(response => {
})
五、接口安全增强
5.1 JWT 认证实现
@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);
}
}
login({ username, password }).then(response => {
const { token } = response.data
commit('SET_TOKEN', token)
localStorage.setItem('token', token)
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`
})
5.2 接口限流防护
@RestController
@RequestMapping("/api/products")
public class ProductController {
@RateLimiter(value = 10, key = "product_list")
@GetMapping
public List<Product> listProducts() {
return productService.findAll();
}
}
六、接口文档生成
6.1 Swagger 集成
@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 日期时间处理
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 {
}
@RestController
@RequestMapping("/api/v2/users")
public class UserControllerV2 {
}
通过以上方案,Spring Boot 和 Vue 可以实现高效、安全的前后端接口交互。实际开发中应根据项目需求选择合适的传参方式、安全策略和性能优化方案。
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online