当前位置: 首页 > news >正文

Spring Boot Web开发篇:构建RESTful API

Spring Boot Web开发篇:构建RESTful API

在前面的文章中,我们学习了Spring Boot的基础知识、配置管理以及如何整合MyBatis进行数据访问操作。在实际的Web应用开发中,构建一套规范、易用的RESTful API是至关重要的。RESTful API不仅能够为前端应用提供数据支持,还能为移动端、第三方系统等提供统一的数据接口。

本文将详细介绍如何使用Spring Boot构建高质量的RESTful API,包括控制器设计、请求处理、参数验证、异常处理等关键内容。

RESTful API简介

REST(Representational State Transfer)是一种软件架构风格,它定义了一组约束和原则,用于创建Web服务。RESTful API遵循REST原则,具有以下特点:

  1. 无状态性:每个请求都包含处理该请求所需的全部信息,服务器不会保存客户端的状态信息。
  2. 统一接口:通过标准的HTTP方法(GET、POST、PUT、DELETE等)操作资源。
  3. 资源导向:将系统中的各种概念抽象为资源,每个资源都有唯一的标识符(URI)。
  4. 可缓存性:响应可以被标记为可缓存或不可缓存,以提高性能。
  5. 分层系统:客户端通常无法知道是否直接连接到终端服务器,还是通过中介连接。

创建Spring Boot Web项目

首先,我们需要创建一个支持Web开发的Spring Boot项目。在pom.xml中添加以下依赖:

4.0.0org.springframework.bootspring-boot-starter-parent2.7.0com.examplespringboot-restful-api1.0.0springboot-restful-apiSpring Boot构建RESTful API示例8org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-validationorg.springframework.bootspring-boot-starter-testtestorg.springframework.bootspring-boot-maven-plugin

设计统一响应结果

在构建RESTful API时,我们需要定义统一的响应格式,以便客户端能够正确解析响应结果。创建一个通用的结果封装类:

package com.example.common;import java.io.Serializable;public class Result implements Serializable {private static final long serialVersionUID = 1L;private int code;private String message;private T data;public Result() {}public Result(int code, String message, T data) {this.code = code;this.message = message;this.data = data;}public static  Result success(T data) {return new Result<>(200, "操作成功", data);}public static  Result success(String message, T data) {return new Result<>(200, message, data);}public static  Result error(String message) {return new Result<>(500, message, null);}public static  Result error(int code, String message) {return new Result<>(code, message, null);}// Getter和Setter方法public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}@Overridepublic String toString() {return "Result{" +"code=" + code +", message='" + message + ''' +", data=" + data +'}';}
}

创建实体类

以用户实体为例,创建User类:

package com.example.entity;import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Min;
import java.io.Serializable;
import java.time.LocalDateTime;public class User implements Serializable {private static final long serialVersionUID = 1L;private Long id;@NotBlank(message = "用户名不能为空")private String username;@NotBlank(message = "密码不能为空")private String password;@Email(message = "邮箱格式不正确")private String email;@Min(value = 0, message = "年龄不能小于0")private Integer age;private LocalDateTime createTime;private LocalDateTime updateTime;// 构造方法public User() {}public User(String username, String password, String email, Integer age) {this.username = username;this.password = password;this.email = email;this.age = age;this.createTime = LocalDateTime.now();this.updateTime = LocalDateTime.now();}// Getter和Setter方法public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public LocalDateTime getCreateTime() {return createTime;}public void setCreateTime(LocalDateTime createTime) {this.createTime = createTime;}public LocalDateTime getUpdateTime() {return updateTime;}public void setUpdateTime(LocalDateTime updateTime) {this.updateTime = updateTime;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + ''' +", password='" + password + ''' +", email='" + email + ''' +", age=" + age +", createTime=" + createTime +", updateTime=" + updateTime +'}';}
}

创建服务层

创建UserService接口和实现类:

package com.example.service;import com.example.entity.User;
import java.util.List;public interface UserService {User createUser(User user);User getUserById(Long id);List getAllUsers();User updateUser(Long id, User user);void deleteUser(Long id);List searchUsers(String keyword);
}
package com.example.service.impl;import com.example.entity.User;
import com.example.service.UserService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;@Service
public class UserServiceImpl implements UserService {// 使用内存存储模拟数据库private static final ConcurrentHashMap userMap = new ConcurrentHashMap<>();private static final AtomicLong idGenerator = new AtomicLong(1);@Overridepublic User createUser(User user) {Long id = idGenerator.getAndIncrement();user.setId(id);userMap.put(id, user);return user;}@Overridepublic User getUserById(Long id) {return userMap.get(id);}@Overridepublic List getAllUsers() {return new ArrayList<>(userMap.values());}@Overridepublic User updateUser(Long id, User user) {if (userMap.containsKey(id)) {user.setId(id);userMap.put(id, user);return user;}return null;}@Overridepublic void deleteUser(Long id) {userMap.remove(id);}@Overridepublic List searchUsers(String keyword) {return userMap.values().stream().filter(user -> user.getUsername().contains(keyword) || user.getEmail().contains(keyword)).collect(Collectors.toList());}
}

创建控制器

创建UserController来处理用户相关的RESTful API请求:

package com.example.controller;import com.example.common.Result;
import com.example.entity.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import java.util.List;@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {@Autowiredprivate UserService userService;/*** 创建用户*/@PostMappingpublic Result createUser(@Valid @RequestBody User user) {User createdUser = userService.createUser(user);return Result.success("用户创建成功", createdUser);}/*** 根据ID获取用户*/@GetMapping("/{id}")public Result getUserById(@Min(value = 1, message = "用户ID必须大于0") @PathVariable Long id) {User user = userService.getUserById(id);if (user == null) {return Result.error(404, "用户不存在");}return Result.success("查询成功", user);}/*** 获取所有用户*/@GetMappingpublic Result> getAllUsers() {List users = userService.getAllUsers();return Result.success("查询成功", users);}/*** 更新用户*/@PutMapping("/{id}")public Result updateUser(@Min(value = 1, message = "用户ID必须大于0") @PathVariable Long id,@Valid @RequestBody User user) {User updatedUser = userService.updateUser(id, user);if (updatedUser == null) {return Result.error(404, "用户不存在");}return Result.success("用户更新成功", updatedUser);}/*** 删除用户*/@DeleteMapping("/{id}")public Result deleteUser(@Min(value = 1, message = "用户ID必须大于0") @PathVariable Long id) {userService.deleteUser(id);return Result.success("用户删除成功");}/*** 搜索用户*/@GetMapping("/search")public Result> searchUsers(@RequestParam String keyword) {List users = userService.searchUsers(keyword);return Result.success("查询成功", users);}
}

全局异常处理

为了统一处理API中的异常,我们需要创建一个全局异常处理器:

package com.example.exception;import com.example.common.Result;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;@RestControllerAdvice
public class GlobalExceptionHandler {/*** 处理参数验证异常(@Validated注解在类上时触发)*/@ExceptionHandler(ConstraintViolationException.class)public Result handleConstraintViolationException(ConstraintViolationException e) {String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(", "));return Result.error(400, message);}/*** 处理参数验证异常(@Valid注解在方法参数上时触发)*/@ExceptionHandler(MethodArgumentNotValidException.class)public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {String message = e.getBindingResult().getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.joining(", "));return Result.error(400, message);}/*** 处理参数绑定异常*/@ExceptionHandler(BindException.class)public Result handleBindException(BindException e) {String message = e.getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.joining(", "));return Result.error(400, message);}/*** 处理自定义业务异常*/@ExceptionHandler(BusinessException.class)public Result handleBusinessException(BusinessException e) {return Result.error(e.getCode(), e.getMessage());}/*** 处理其他未捕获的异常*/@ExceptionHandler(Exception.class)public Result handleException(Exception e) {return Result.error(500, "系统内部错误:" + e.getMessage());}
}

创建自定义业务异常类:

package com.example.exception;public class BusinessException extends RuntimeException {private int code;private String message;public BusinessException(String message) {super(message);this.code = 500;this.message = message;}public BusinessException(int code, String message) {super(message);this.code = code;this.message = message;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}@Overridepublic String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}

配置类

创建一个配置类来配置应用的相关设置:

package com.example.config;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 WebConfig implements WebMvcConfigurer {/*** 配置跨域请求*/@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOriginPatterns("*").allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS").allowedHeaders("*").allowCredentials(true).maxAge(3600);}
}

主应用类

创建Spring Boot主应用类:

package com.example;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringBootRestfulApiApplication {public static void main(String[] args) {SpringApplication.run(SpringBootRestfulApiApplication.class, args);}
}

API测试

启动应用后,可以使用以下API进行测试:

  1. 创建用户:
POST http://localhost:8080/api/users
Content-Type: application/json{"username": "张三","password": "123456","email": "zhangsan@example.com","age": 25
}
  1. 获取用户:
GET http://localhost:8080/api/users/1
  1. 获取所有用户:
GET http://localhost:8080/api/users
  1. 更新用户:
PUT http://localhost:8080/api/users/1
Content-Type: application/json{"username": "张三丰","password": "123456","email": "zhangsanfeng@example.com","age": 30
}
  1. 删除用户:
DELETE http://localhost:8080/api/users/1
  1. 搜索用户:
GET http://localhost:8080/api/users/search?keyword=张

RESTful API设计最佳实践

  1. 使用名词表示资源:URI应该使用名词而不是动词来表示资源,如/users而不是/getUsers。

  2. 使用HTTP方法表示操作

    • GET:查询资源
    • POST:创建资源
    • PUT:更新资源(全量更新)
    • PATCH:更新资源(部分更新)
    • DELETE:删除资源
  3. 合理使用HTTP状态码

    • 200 OK:请求成功
    • 201 Created:创建成功
    • 400 Bad Request:请求参数错误
    • 401 Unauthorized:未授权
    • 404 Not Found:资源不存在
    • 500 Internal Server Error:服务器内部错误
  4. 版本控制:在URI中包含API版本号,如/api/v1/users。

  5. 统一响应格式:所有API响应应该遵循统一的格式,便于客户端解析。

  6. 参数验证:对所有输入参数进行验证,防止非法数据进入系统。

  7. 异常处理:统一处理系统异常,避免敏感信息泄露。

  8. 文档化:提供详细的API文档,方便开发者使用。

总结

本文详细介绍了如何使用Spring Boot构建RESTful API,包括:

  1. RESTful API的基本概念和设计原则
  2. Spring Boot Web项目的创建和配置
  3. 统一响应结果的封装
  4. 实体类的设计和参数验证
  5. 服务层的实现
  6. 控制器层的开发
  7. 全局异常处理
  8. 跨域配置
  9. API测试方法
  10. RESTful API设计最佳实践

通过以上内容的学习和实践,我们可以构建出高质量、规范化的RESTful API,为前端应用和第三方系统提供稳定可靠的数据接口。在下一篇文章中,我们将介绍Spring Boot安全篇:集成Spring Security实现认证授权。

作者:CSDN博客助手
版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明。

http://www.dtcms.com/a/550260.html

相关文章:

  • 跨越时间的鸿沟:解构 Rust 异步编程中的生命周期挑战
  • 网站的建设及维护报告2018年网站建设发言
  • 珠海网站开发排名江苏南京今天的新消息
  • 免费模型网站信息公司网站建设方案 游戏
  • 北京做冷冻牛羊肉的网站平邑县住房和城乡建设局网站
  • 一条SQL如何实现insertOrUpdate
  • 结构优化过程可视化的两种方法
  • 做网站建站点seo的描述正确
  • 百度站长seo搭建网站需要学什么
  • 旅游网站 系统江阴百度推广公司
  • Spring Al学习9:模型上下文协议(MCP)
  • 浙江省大成建设集团有限公司网站wordpress 插件有后门
  • linux 网站开发网络营销员岗位的职责与要求
  • 网站首页置顶是怎么做电商系统服务好的商家
  • 做网站没有数据家庭网做网站
  • 陕西高速公路建设网站有专门做辩论的网站吗
  • 怎么登陆建设工程网站php网站开发要学什么软件
  • Visual Basic 数据打印
  • 算法学习 18
  • 【19】C语言多向分支Switch case语法详解
  • 上海网站建设高端创业平台app有哪些
  • 从近10年历年论文题目看系统分析师考试出题趋势
  • IDS车载入侵检测系统
  • 人工智能重塑金融数字化:从精准服务到生态革新的全景探索
  • 合肥seo网站优化上海排名优化推广工具
  • WebRTC项目架构详解
  • 个人网站一定要备案吗手机医疗网站建设
  • 公司网站建设计入什么费用网站建设中图片是什么
  • 西安企业自助建站系统私人定制音乐app软件
  • 哪个网站能帮助做试卷贵州软件制作