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

网站域名备案需要什么广州专业网站建设网页设计服务

网站域名备案需要什么,广州专业网站建设网页设计服务,来个网站你知道的2022年,ppt免费模板大全网站👋 大家好,我是 阿问学长!专注于分享优质开源项目解析、毕业设计项目指导支持、幼小初高的教辅资料推荐等,欢迎关注交流!🚀 20-SpringMVC RESTful API开发 📖 本文概述 本文是SSM框架系列Spr…

👋 大家好,我是 阿问学长!专注于分享优质开源项目解析、毕业设计项目指导支持、幼小初高教辅资料推荐等,欢迎关注交流!🚀

20-SpringMVC RESTful API开发

📖 本文概述

本文是SSM框架系列SpringMVC进阶篇的最后一篇,将深入探讨如何使用SpringMVC开发RESTful API。通过详细的代码示例和最佳实践,帮助读者掌握现代Web API开发的核心技能。

🎯 学习目标

  • 深入理解RESTful架构风格和设计原则
  • 掌握SpringMVC RESTful API开发技巧
  • 学会处理JSON数据和内容协商
  • 了解API版本控制和文档生成
  • 掌握RESTful API的测试方法

1. RESTful架构概述

1.1 REST基本概念

/*** RESTful架构概述*/
public class RESTfulOverview {/*** REST (Representational State Transfer) 是一种架构风格,* 它定义了一组约束条件和原则,用于创建Web服务。* * REST的核心原则:* * 1. 统一接口 (Uniform Interface)*    - 资源标识:每个资源都有唯一的URI*    - 资源操作:通过HTTP方法操作资源*    - 自描述消息:消息包含足够的信息来描述如何处理*    - 超媒体驱动:通过超链接发现可用操作* * 2. 无状态 (Stateless)*    - 每个请求都包含处理该请求所需的所有信息*    - 服务器不保存客户端状态* * 3. 可缓存 (Cacheable)*    - 响应数据可以被缓存以提高性能* * 4. 客户端-服务器分离 (Client-Server)*    - 客户端和服务器独立演化* * 5. 分层系统 (Layered System)*    - 系统可以由多层组成,每层只知道相邻层* * 6. 按需代码 (Code on Demand) - 可选*    - 服务器可以向客户端发送可执行代码*//*** HTTP方法与CRUD操作的对应关系:* * GET    - 读取 (Read)* POST   - 创建 (Create)* PUT    - 更新 (Update) - 完整更新* PATCH  - 更新 (Update) - 部分更新* DELETE - 删除 (Delete)* HEAD   - 获取资源元数据* OPTIONS - 获取资源支持的操作*//*** RESTful URL设计原则:* * 1. 使用名词而不是动词*    ✅ GET /users/123*    ❌ GET /getUser/123* * 2. 使用复数形式*    ✅ GET /users*    ❌ GET /user* * 3. 使用层次结构表示关系*    ✅ GET /users/123/orders*    ❌ GET /getUserOrders/123* * 4. 使用查询参数进行过滤、排序、分页*    ✅ GET /users?status=active&page=1&size=10*    ❌ GET /users/active/page1/size10*/
}

1.2 HTTP状态码规范

/*** HTTP状态码使用规范*/
public class HTTPStatusCodes {/*** 2xx 成功状态码*/public static final int OK = 200;                    // 请求成功public static final int CREATED = 201;              // 资源创建成功public static final int ACCEPTED = 202;             // 请求已接受,正在处理public static final int NO_CONTENT = 204;           // 请求成功,无返回内容/*** 3xx 重定向状态码*/public static final int NOT_MODIFIED = 304;         // 资源未修改/*** 4xx 客户端错误状态码*/public static final int BAD_REQUEST = 400;          // 请求参数错误public static final int UNAUTHORIZED = 401;         // 未授权public static final int FORBIDDEN = 403;            // 禁止访问public static final int NOT_FOUND = 404;            // 资源不存在public static final int METHOD_NOT_ALLOWED = 405;   // 方法不允许public static final int CONFLICT = 409;             // 资源冲突public static final int UNPROCESSABLE_ENTITY = 422; // 请求格式正确但语义错误/*** 5xx 服务器错误状态码*/public static final int INTERNAL_SERVER_ERROR = 500; // 服务器内部错误public static final int NOT_IMPLEMENTED = 501;       // 功能未实现public static final int SERVICE_UNAVAILABLE = 503;   // 服务不可用/*** 状态码使用示例*/public void statusCodeExamples() {/** GET /users/123* 200 OK - 用户存在,返回用户信息* 404 Not Found - 用户不存在* * POST /users* 201 Created - 用户创建成功* 400 Bad Request - 请求参数错误* 409 Conflict - 用户已存在* * PUT /users/123* 200 OK - 更新成功,返回更新后的用户信息* 204 No Content - 更新成功,无返回内容* 404 Not Found - 用户不存在* * DELETE /users/123* 204 No Content - 删除成功* 404 Not Found - 用户不存在*/}
}

2. SpringMVC RESTful API开发

2.1 基础RESTful控制器

/*** 用户RESTful API控制器*/
@RestController
@RequestMapping("/api/v1/users")
@CrossOrigin(origins = "*", maxAge = 3600)
public class UserRestController {@Autowiredprivate UserService userService;/*** 获取所有用户 - 支持分页和过滤* GET /api/v1/users?page=1&size=10&status=active&keyword=john*/@GetMappingpublic ResponseEntity<ApiResponse<PageResult<UserDTO>>> getUsers(@RequestParam(defaultValue = "1") int page,@RequestParam(defaultValue = "10") int size,@RequestParam(required = false) String status,@RequestParam(required = false) String keyword,@RequestParam(defaultValue = "id") String sortBy,@RequestParam(defaultValue = "asc") String sortDir) {UserQueryParams params = UserQueryParams.builder().page(page).size(size).status(status).keyword(keyword).sortBy(sortBy).sortDir(sortDir).build();PageResult<UserDTO> result = userService.findUsers(params);return ResponseEntity.ok(ApiResponse.success(result));}/*** 根据ID获取用户* GET /api/v1/users/{id}*/@GetMapping("/{id}")public ResponseEntity<ApiResponse<UserDTO>> getUserById(@PathVariable Long id) {UserDTO user = userService.findById(id);if (user == null) {return ResponseEntity.notFound().build();}return ResponseEntity.ok(ApiResponse.success(user));}/*** 创建新用户* POST /api/v1/users*/@PostMappingpublic ResponseEntity<ApiResponse<UserDTO>> createUser(@Valid @RequestBody CreateUserRequest request,BindingResult bindingResult) {if (bindingResult.hasErrors()) {return ResponseEntity.badRequest().body(ApiResponse.error("参数验证失败", getValidationErrors(bindingResult)));}try {UserDTO createdUser = userService.createUser(request);URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(createdUser.getId()).toUri();return ResponseEntity.created(location).body(ApiResponse.success(createdUser));} catch (UserAlreadyExistsException e) {return ResponseEntity.status(HttpStatus.CONFLICT).body(ApiResponse.error("用户已存在", e.getMessage()));}}/*** 完整更新用户* PUT /api/v1/users/{id}*/@PutMapping("/{id}")public ResponseEntity<ApiResponse<UserDTO>> updateUser(@PathVariable Long id,@Valid @RequestBody UpdateUserRequest request,BindingResult bindingResult) {if (bindingResult.hasErrors()) {return ResponseEntity.badRequest().body(ApiResponse.error("参数验证失败", getValidationErrors(bindingResult)));}try {UserDTO updatedUser = userService.updateUser(id, request);return ResponseEntity.ok(ApiResponse.success(updatedUser));} catch (UserNotFoundException e) {return ResponseEntity.notFound().build();}}/*** 部分更新用户* PATCH /api/v1/users/{id}*/@PatchMapping("/{id}")public ResponseEntity<ApiResponse<UserDTO>> patchUser(@PathVariable Long id,@RequestBody Map<String, Object> updates) {try {UserDTO updatedUser = userService.patchUser(id, updates);return ResponseEntity.ok(ApiResponse.success(updatedUser));} catch (UserNotFoundException e) {return ResponseEntity.notFound().build();} catch (IllegalArgumentException e) {return ResponseEntity.badRequest().body(ApiResponse.error("无效的更新字段", e.getMessage()));}}/*** 删除用户* DELETE /api/v1/users/{id}*/@DeleteMapping("/{id}")public ResponseEntity<ApiResponse<Void>> deleteUser(@PathVariable Long id) {try {userService.deleteUser(id);return ResponseEntity.noContent().build();} catch (UserNotFoundException e) {return ResponseEntity.notFound().build();}}/*** 批量删除用户* DELETE /api/v1/users*/@DeleteMappingpublic ResponseEntity<ApiResponse<BatchOperationResult>> batchDeleteUsers(@RequestBody List<Long> userIds) {BatchOperationResult result = userService.batchDeleteUsers(userIds);return ResponseEntity.ok(ApiResponse.success(result));}/*** 获取用户的订单* GET /api/v1/users/{id}/orders*/@GetMapping("/{id}/orders")public ResponseEntity<ApiResponse<List<OrderDTO>>> getUserOrders(@PathVariable Long id,@RequestParam(defaultValue = "1") int page,@RequestParam(defaultValue = "10") int size) {try {PageResult<OrderDTO> orders = userService.getUserOrders(id, page, size);return ResponseEntity.ok(ApiResponse.success(orders.getData()));} catch (UserNotFoundException e) {return ResponseEntity.notFound().build();}}/*** 激活/禁用用户* PATCH /api/v1/users/{id}/status*/@PatchMapping("/{id}/status")public ResponseEntity<ApiResponse<UserDTO>> updateUserStatus(@PathVariable Long id,@RequestBody UpdateStatusRequest request) {try {UserDTO updatedUser = userService.updateUserStatus(id, request.getStatus());return ResponseEntity.ok(ApiResponse.success(updatedUser));} catch (UserNotFoundException e) {return ResponseEntity.notFound().build();}}/*** 重置用户密码* POST /api/v1/users/{id}/reset-password*/@PostMapping("/{id}/reset-password")public ResponseEntity<ApiResponse<Void>> resetPassword(@PathVariable Long id) {try {userService.resetPassword(id);return ResponseEntity.ok(ApiResponse.success(null, "密码重置成功"));} catch (UserNotFoundException e) {return ResponseEntity.notFound().build();}}/*** 获取验证错误信息*/private Map<String, String> getValidationErrors(BindingResult bindingResult) {Map<String, String> errors = new HashMap<>();bindingResult.getFieldErrors().forEach(error -> errors.put(error.getField(), error.getDefaultMessage()));return errors;}
}

2.2 请求和响应DTO

/*** 创建用户请求DTO*/
public class CreateUserRequest {@NotBlank(message = "用户名不能为空")@Size(min = 3, max = 50, message = "用户名长度必须在3-50个字符之间")@Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "用户名只能包含字母、数字和下划线")private String username;@NotBlank(message = "邮箱不能为空")@Email(message = "邮箱格式不正确")private String email;@NotBlank(message = "密码不能为空")@Size(min = 6, max = 20, message = "密码长度必须在6-20个字符之间")@Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d@$!%*?&]{6,}$", message = "密码必须包含至少一个大写字母、一个小写字母和一个数字")private String password;@NotBlank(message = "确认密码不能为空")private String confirmPassword;@NotNull(message = "年龄不能为空")@Min(value = 18, message = "年龄不能小于18岁")@Max(value = 100, message = "年龄不能大于100岁")private Integer age;@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")private String phone;@Size(max = 200, message = "个人简介不能超过200个字符")private String bio;// getter/setter.../*** 自定义验证:确认密码必须与密码一致*/@AssertTrue(message = "确认密码与密码不一致")public boolean isPasswordMatching() {return password != null && password.equals(confirmPassword);}
}/*** 更新用户请求DTO*/
public class UpdateUserRequest {@Size(min = 3, max = 50, message = "用户名长度必须在3-50个字符之间")@Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "用户名只能包含字母、数字和下划线")private String username;@Email(message = "邮箱格式不正确")private String email;@Min(value = 18, message = "年龄不能小于18岁")@Max(value = 100, message = "年龄不能大于100岁")private Integer age;@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")private String phone;@Size(max = 200, message = "个人简介不能超过200个字符")private String bio;// getter/setter...
}/*** 用户响应DTO*/
public class UserDTO {private Long id;private String username;private String email;private Integer age;private String phone;private String bio;private String status;private LocalDateTime createTime;private LocalDateTime updateTime;private LocalDateTime lastLoginTime;// 关联数据private List<RoleDTO> roles;private UserProfileDTO profile;// getter/setter...
}/*** 统一API响应格式*/
public class ApiResponse<T> {private boolean success;private String message;private T data;private Map<String, Object> meta;private long timestamp;public ApiResponse() {this.timestamp = System.currentTimeMillis();}public static <T> ApiResponse<T> success(T data) {ApiResponse<T> response = new ApiResponse<>();response.setSuccess(true);response.setMessage("操作成功");response.setData(data);return response;}public static <T> ApiResponse<T> success(T data, String message) {ApiResponse<T> response = new ApiResponse<>();response.setSuccess(true);response.setMessage(message);response.setData(data);return response;}public static <T> ApiResponse<T> error(String message) {ApiResponse<T> response = new ApiResponse<>();response.setSuccess(false);response.setMessage(message);return response;}public static <T> ApiResponse<T> error(String message, T data) {ApiResponse<T> response = new ApiResponse<>();response.setSuccess(false);response.setMessage(message);response.setData(data);return response;}// getter/setter...
}/*** 分页结果DTO*/
public class PageResult<T> {private List<T> data;private long total;private int page;private int size;private int totalPages;private boolean hasNext;private boolean hasPrevious;public PageResult(List<T> data, long total, int page, int size) {this.data = data;this.total = total;this.page = page;this.size = size;this.totalPages = (int) Math.ceil((double) total / size);this.hasNext = page < totalPages;this.hasPrevious = page > 1;}// getter/setter...
}/*** 批量操作结果DTO*/
public class BatchOperationResult {private int total;private int success;private int failed;private List<String> errors;public BatchOperationResult(int total, int success, int failed) {this.total = total;this.success = success;this.failed = failed;this.errors = new ArrayList<>();}// getter/setter...
}

3. 内容协商和数据转换

3.1 JSON配置

/*** JSON配置*/
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {/*** 配置消息转换器*/@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {// JSON转换器MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();jsonConverter.setObjectMapper(objectMapper());converters.add(jsonConverter);// XML转换器(可选)MappingJackson2XmlHttpMessageConverter xmlConverter = new MappingJackson2XmlHttpMessageConverter();converters.add(xmlConverter);// 字符串转换器StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);converters.add(stringConverter);}/*** 配置ObjectMapper*/@Bean@Primarypublic ObjectMapper objectMapper() {ObjectMapper mapper = new ObjectMapper();// 时间格式配置mapper.registerModule(new JavaTimeModule());mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));// 序列化配置mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);mapper.configure(SerializationFeature.INDENT_OUTPUT, true);// 反序列化配置mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);// 字段命名策略mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);// 空值处理mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);return mapper;}/*** 配置内容协商*/@Overridepublic void configureContentNegotiation(ContentNegotiationConfigurer configurer) {configurer.favorParameter(true).parameterName("format").ignoreAcceptHeader(false).useRegisteredExtensionsOnly(false).defaultContentType(MediaType.APPLICATION_JSON).mediaType("json", MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML);}/*** 配置CORS*/@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**").allowedOriginPatterns("*").allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS").allowedHeaders("*").allowCredentials(true).maxAge(3600);}
}

3.2 自定义序列化

/*** 自定义JSON序列化器*/
public class UserDTOSerializer extends JsonSerializer<UserDTO> {@Overridepublic void serialize(UserDTO user, JsonGenerator gen, SerializerProvider serializers) throws IOException {gen.writeStartObject();gen.writeNumberField("id", user.getId());gen.writeStringField("username", user.getUsername());gen.writeStringField("email", maskEmail(user.getEmail()));gen.writeNumberField("age", user.getAge());if (user.getPhone() != null) {gen.writeStringField("phone", maskPhone(user.getPhone()));}gen.writeStringField("status", user.getStatus());// 格式化时间if (user.getCreateTime() != null) {gen.writeStringField("create_time", user.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));}// 序列化关联对象if (user.getRoles() != null && !user.getRoles().isEmpty()) {gen.writeArrayFieldStart("roles");for (RoleDTO role : user.getRoles()) {gen.writeStartObject();gen.writeNumberField("id", role.getId());gen.writeStringField("name", role.getName());gen.writeEndObject();}gen.writeEndArray();}gen.writeEndObject();}private String maskEmail(String email) {if (email == null || !email.contains("@")) {return email;}String[] parts = email.split("@");String username = parts[0];if (username.length() <= 2) {return email;}return username.substring(0, 2) + "***@" + parts[1];}private String maskPhone(String phone) {if (phone == null || phone.length() != 11) {return phone;}return phone.substring(0, 3) + "****" + phone.substring(7);}
}/*** 自定义反序列化器*/
public class CreateUserRequestDeserializer extends JsonDeserializer<CreateUserRequest> {@Overridepublic CreateUserRequest deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {JsonNode node = p.getCodec().readTree(p);CreateUserRequest request = new CreateUserRequest();// 用户名处理:去除空格并转小写if (node.has("username")) {String username = node.get("username").asText().trim().toLowerCase();request.setUsername(username);}// 邮箱处理:去除空格并转小写if (node.has("email")) {String email = node.get("email").asText().trim().toLowerCase();request.setEmail(email);}// 密码处理if (node.has("password")) {request.setPassword(node.get("password").asText());}if (node.has("confirm_password")) {request.setConfirmPassword(node.get("confirm_password").asText());}// 年龄处理if (node.has("age")) {request.setAge(node.get("age").asInt());}// 手机号处理:去除空格和特殊字符if (node.has("phone")) {String phone = node.get("phone").asText().replaceAll("[^0-9]", "");request.setPhone(phone);}if (node.has("bio")) {request.setBio(node.get("bio").asText());}return request;}
}

4. 异常处理和错误响应

4.1 全局异常处理器

/*** 全局异常处理器*/
@RestControllerAdvice
public class GlobalExceptionHandler {private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);/*** 处理参数验证异常*/@ExceptionHandler(MethodArgumentNotValidException.class)public ResponseEntity<ApiResponse<Map<String, String>>> handleValidationException(MethodArgumentNotValidException ex) {Map<String, String> errors = new HashMap<>();ex.getBindingResult().getFieldErrors().forEach(error -> errors.put(error.getField(), error.getDefaultMessage()));logger.warn("参数验证失败: {}", errors);return ResponseEntity.badRequest().body(ApiResponse.error("参数验证失败", errors));}/*** 处理请求参数绑定异常*/@ExceptionHandler(BindException.class)public ResponseEntity<ApiResponse<Map<String, String>>> handleBindException(BindException ex) {Map<String, String> errors = new HashMap<>();ex.getFieldErrors().forEach(error -> errors.put(error.getField(), error.getDefaultMessage()));return ResponseEntity.badRequest().body(ApiResponse.error("请求参数错误", errors));}/*** 处理业务异常*/@ExceptionHandler(BusinessException.class)public ResponseEntity<ApiResponse<Void>> handleBusinessException(BusinessException ex) {logger.warn("业务异常: {}", ex.getMessage());return ResponseEntity.badRequest().body(ApiResponse.error(ex.getMessage()));}/*** 处理资源不存在异常*/@ExceptionHandler(ResourceNotFoundException.class)public ResponseEntity<ApiResponse<Void>> handleResourceNotFoundException(ResourceNotFoundException ex) {logger.warn("资源不存在: {}", ex.getMessage());return ResponseEntity.notFound().build();}/*** 处理权限异常*/@ExceptionHandler(AccessDeniedException.class)public ResponseEntity<ApiResponse<Void>> handleAccessDeniedException(AccessDeniedException ex) {logger.warn("访问被拒绝: {}", ex.getMessage());return ResponseEntity.status(HttpStatus.FORBIDDEN).body(ApiResponse.error("访问被拒绝"));}/*** 处理HTTP方法不支持异常*/@ExceptionHandler(HttpRequestMethodNotSupportedException.class)public ResponseEntity<ApiResponse<Void>> handleMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) {String message = String.format("不支持的HTTP方法: %s", ex.getMethod());return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body(ApiResponse.error(message));}/*** 处理媒体类型不支持异常*/@ExceptionHandler(HttpMediaTypeNotSupportedException.class)public ResponseEntity<ApiResponse<Void>> handleMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException ex) {String message = String.format("不支持的媒体类型: %s", ex.getContentType());return ResponseEntity.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).body(ApiResponse.error(message));}/*** 处理JSON解析异常*/@ExceptionHandler(HttpMessageNotReadableException.class)public ResponseEntity<ApiResponse<Void>> handleJsonParseException(HttpMessageNotReadableException ex) {logger.warn("JSON解析失败: {}", ex.getMessage());return ResponseEntity.badRequest().body(ApiResponse.error("请求体格式错误"));}/*** 处理类型转换异常*/@ExceptionHandler(TypeMismatchException.class)public ResponseEntity<ApiResponse<Void>> handleTypeMismatchException(TypeMismatchException ex) {String message = String.format("参数类型错误: %s", ex.getPropertyName());return ResponseEntity.badRequest().body(ApiResponse.error(message));}/*** 处理数据库约束异常*/@ExceptionHandler(DataIntegrityViolationException.class)public ResponseEntity<ApiResponse<Void>> handleDataIntegrityViolationException(DataIntegrityViolationException ex) {logger.error("数据完整性约束违反", ex);String message = "数据操作失败,请检查数据完整性";if (ex.getMessage().contains("Duplicate entry")) {message = "数据已存在,不能重复添加";}return ResponseEntity.status(HttpStatus.CONFLICT).body(ApiResponse.error(message));}/*** 处理系统异常*/@ExceptionHandler(Exception.class)public ResponseEntity<ApiResponse<Void>> handleException(Exception ex) {logger.error("系统异常", ex);return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ApiResponse.error("系统内部错误"));}
}/*** 自定义业务异常*/
public class BusinessException extends RuntimeException {private String code;public BusinessException(String message) {super(message);}public BusinessException(String code, String message) {super(message);this.code = code;}public BusinessException(String message, Throwable cause) {super(message, cause);}public String getCode() {return code;}
}/*** 资源不存在异常*/
public class ResourceNotFoundException extends RuntimeException {public ResourceNotFoundException(String message) {super(message);}public ResourceNotFoundException(String resource, Object id) {super(String.format("%s not found with id: %s", resource, id));}
}

5. API版本控制

5.1 URL版本控制

/*** URL版本控制示例*/
@RestController
@RequestMapping("/api/v1/users")
public class UserV1Controller {@GetMapping("/{id}")public ResponseEntity<UserV1DTO> getUser(@PathVariable Long id) {// V1版本的用户信息,字段较少UserV1DTO user = userService.findUserV1(id);return ResponseEntity.ok(user);}
}@RestController
@RequestMapping("/api/v2/users")
public class UserV2Controller {@GetMapping("/{id}")public ResponseEntity<UserV2DTO> getUser(@PathVariable Long id) {// V2版本的用户信息,增加了新字段UserV2DTO user = userService.findUserV2(id);return ResponseEntity.ok(user);}
}

5.2 请求头版本控制

/*** 请求头版本控制*/
@RestController
@RequestMapping("/api/users")
public class UserVersionController {@GetMapping(value = "/{id}", headers = "API-Version=1")public ResponseEntity<UserV1DTO> getUserV1(@PathVariable Long id) {UserV1DTO user = userService.findUserV1(id);return ResponseEntity.ok(user);}@GetMapping(value = "/{id}", headers = "API-Version=2")public ResponseEntity<UserV2DTO> getUserV2(@PathVariable Long id) {UserV2DTO user = userService.findUserV2(id);return ResponseEntity.ok(user);}@GetMapping("/{id}")public ResponseEntity<UserV2DTO> getUserDefault(@PathVariable Long id) {// 默认使用最新版本UserV2DTO user = userService.findUserV2(id);return ResponseEntity.ok(user);}
}

5.3 参数版本控制

/*** 参数版本控制*/
@RestController
@RequestMapping("/api/users")
public class UserParamVersionController {@GetMapping(value = "/{id}", params = "version=1")public ResponseEntity<UserV1DTO> getUserV1(@PathVariable Long id) {UserV1DTO user = userService.findUserV1(id);return ResponseEntity.ok(user);}@GetMapping(value = "/{id}", params = "version=2")public ResponseEntity<UserV2DTO> getUserV2(@PathVariable Long id) {UserV2DTO user = userService.findUserV2(id);return ResponseEntity.ok(user);}
}

6. 小结

本文深入介绍了SpringMVC RESTful API开发:

  1. RESTful架构:REST原则、HTTP方法和状态码规范
  2. API开发:控制器设计、请求响应DTO、数据验证
  3. 内容协商:JSON配置、自定义序列化、消息转换
  4. 异常处理:全局异常处理器、错误响应格式
  5. 版本控制:URL、请求头、参数等版本控制方式

掌握RESTful API开发的关键点:

  • 遵循REST架构原则和设计规范
  • 合理设计API接口和数据结构
  • 实现完善的异常处理机制
  • 考虑API的版本控制和向后兼容
  • 注重API的安全性和性能优化

🔗 下一篇预告

下一篇文章将介绍SSM项目部署与优化,学习如何将SSM项目部署到生产环境并进行性能优化。


相关文章:

  • 上一篇:19-SpringMVC拦截器与异常处理
  • 下一篇:21-SSM框架整合配置详解
  • 返回目录
http://www.dtcms.com/a/481240.html

相关文章:

  • 最新大气房地产企业网站织梦模板深圳网站开发
  • 怎么做坑人网站开发游戏的公司
  • 网站运营一般做那些分析免费建站哪个好
  • 自助建立网站wordpress用html代码编辑器
  • wordpress字不能显示广州优化公司哪家好
  • 帝舵手表官方网站网站做支付按流量付费
  • 自己做本地视频网站家具在线设计平台
  • 网站域名查ip如何做跨境电商
  • 一号建站苏州关键词排名提升
  • 学商务网站建设的感想登封网络推广
  • 校园微网站建设方案电子图书网站建设
  • 网站app的意义wordpress福利博客
  • 惠州做棋牌网站建设多少钱户外广告
  • 网站建设费与无形资产微信公众号优秀文案
  • 免费手机建站平台建设和管理环保网站
  • 怎么做网站信息免费咨询医院
  • 接给别人做网站的活做茶歇的网站
  • 用hexo做网站网站别人帮做的要注意什么
  • 网站seo优化网站前端培训出来工资多少
  • 上海公司注册网seo综合查询国产
  • 推广项目网站网站设计步骤图片
  • 淄博网站推广优化有限责任公司属于什么法人
  • 移动网站 pc网站的区别免费wordpress移动主题
  • 惠山区住房和建设厅网站免费推广网站哪家好
  • 好的网站建站公司做网站软件j
  • 山东省济宁市嘉祥县建设局网站WordPress建站布置
  • 怎么管理网站西安效果图制作
  • 新网建立网站网站建设 自学 电子版 pdf下载
  • 深圳专业网站建设制作企业招聘信息发布平台
  • 不得不知道的网站门户网站制作全包