开发者

SpringBoot+Vue 前后端接口交互的项目实践

目录
  • 一、前后端交互架构概览
  • 二、Spring Boot 后端接口实现
    • 2.1 基础REST控制器
    • 2.2 DTO设计示例
    • 2.3 全局异常处理
  • 三、vue 前端接口调用
    • 3.1 AxIOS 封装
    • 3.2 API模块化封装
    • 3.3 Vue组件中调用示例
  • 四、接口交互关键点详解
    • 4.1 请求参数传递方式
    • 4.2 跨域解决方案
    • 4.3 文件上传处理
  • 五、接口安全增强
    • 5.1 JWT认证实现
    • 5.2 接口限流防护
  • 六、接口文档生成
    • 6.1 Swagger集成
    • 6.2 接口注释示例
  • 七、性能优化建议
    • 7.1 接口缓存策略
    • 7.2 分页查询优化
  • 八、常见问题解决方案
    • 8.1 日期时间处理
    • 8.2 大数字精度丢失
    • 8.3 接口版本管理编程

一、前后端交互架构概览

SpringBoot+Vue 前后端接口交互的项目实践

二、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) {
        userandroidService.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 '@/route编程客栈r'

// 创建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")
                .allojswedHeaders("*")
                .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 前后端接口交互内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新开发

开发排行榜