@RestController
@RequestMapping("/api/users")
@CrossOrigin // 处理跨域,生产环境应配置具体域名
public class UserController {
@Autowired
private UserService userService;
// 获取用户列表
@GetMapping
public ResponseEntity> getUsers(
@RequestParam(required = false) String name) {
List users = userService.findUsers(name);
return ResponseEntity.ok(users);
}
// 获取单个用户
@GetMapping("/{id}")
public ResponseEntity getUser(@PathVariable Long id) {
UserDTO user = userService.getUserById(id);
return ResponseEntity.ok(user);
}
// 创建用户
@PostMapping
public ResponseEntity createUser(
@Valid @RequestBody UserCreateRequest request) {
UserDTO newUser = userService.createUser(request);
return ResponseEntity.status(HttpStatus.CREATED).body(newUser);
}
// 更新用户
@PutMapping("/{id}")
public ResponseEntity updateUser(
@PathVariable Long id,
@Valid @RequestBody UserUpdateRequest request) {
UserDTO updatedUser = userService.updateUser(id, request);
return ResponseEntity.ok(updatedUser);
}
// 删除用户
@DeleteMapping("/{id}")
public ResponseEntity deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
}
用户创建请求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;
}
@RestControllerAdvice
public class GlobalExceptionHandler {
// 处理验证异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity handleValidationException(
MethodArgumentNotValidException ex) {
List 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 handleBusinessException(
BusinessException ex) {
ErrorResponse response = new ErrorResponse(
ex.getCode(),
ex.getMessage(),
null);
return ResponseEntity.status(ex.getStatus()).body(response);
}
}
// 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
// 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'
})
}
参数类型 | 前端传递方式 | 后端接收方式 |
---|---|---|
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 |
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);
}
}
后端接收:
@PostMapping("/upload")
public ResponseEntity 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 => {
// 处理响应
})
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}`
})
@RestController
@RequestMapping("/api/products")
public class ProductController {
@RateLimiter(value = 10, key = "'product_list'") // 10次/秒
@GetMapping
public List listProducts() {
return productService.findAll();
}
}
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();
}
}
@Api(tags = "用户管理")
@RestController
@RequestMapping("/api/users")
public class UserController {
@ApiOperation("获取用户列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "用户名", paramType = "query")
})
@GetMapping
public ResponseEntity> getUsers(String name) {
// ...
}
}
@Cacheable(value = "users", key = "#id")
@GetMapping("/{id}")
public UserDTO getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
后端实现:
@GetMapping
public PageResult getUsers(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
Pageable pageable = PageRequest.of(page - 1, size);
Page 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
})
后端配置:
# 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')
后端处理:
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@RestController
@RequestMapping("/api/v1/users")
public class UserControllerV1 {
// v1版本接口
}
@RestController
@RequestMapping("/api/v2/users")
public class UserControllerV2 {
// v2版本接口
}
通过以上方案,Spring Boot和Vue可以实现高效、安全的前后端接口交互。实际开发中应根据项目需求选择合适的传参方式、安全策略和性能优化方案。