# Lane Carford 基础架构功能说明 ## 🏗️ 架构概述 这是一个基于 **Spring Boot 3.1.6** 和 **Java 21** 的纯净架构模板,提供了完整的企业级应用基础设施,可以快速开发各种类型的业务应用。 ## 📋 核心功能清单 ### 1. 🛡️ 全局异常处理 **功能描述**: 统一处理应用程序中的各种异常,提供一致的错误响应格式 **实现类**: `GlobalExceptionHandler` **支持的异常类型**: - 业务异常 (`BusinessException`) - 参数验证异常 (`MethodArgumentNotValidException`) - 文件上传大小超限异常 (`MaxUploadSizeExceededException`) - 数据库操作异常 (`DataAccessException`, `SQLException`) - HTTP方法不支持异常 (`HttpRequestMethodNotSupportedException`) - 404异常 (`NoHandlerFoundException`) - 运行时异常 (`RuntimeException`) - 其他通用异常 **使用示例**: ```java // 1. 创建自定义业务异常 @RestController @RequestMapping("/api/users") public class UserController { @PostMapping public ApiResponse createUser(@Valid @RequestBody CreateUserRequest request) { // 业务逻辑验证 if (userService.existsByEmail(request.getEmail())) { throw new BusinessException("USER_EXISTS", "用户邮箱已存在"); } User user = userService.createUser(request); return ApiResponse.success("用户创建成功", user); } @GetMapping("/{id}") public ApiResponse getUser(@PathVariable Long id) { User user = userService.findById(id); if (user == null) { throw new BusinessException("USER_NOT_FOUND", "用户不存在"); } return ApiResponse.success(user); } } // 2. 参数验证异常自动处理 public class CreateUserRequest { @NotBlank(message = "用户名不能为空") @Size(min = 2, max = 20, message = "用户名长度必须在2-20个字符之间") private String username; @NotBlank(message = "邮箱不能为空") @Email(message = "邮箱格式不正确") private String email; @NotNull(message = "年龄不能为空") @Min(value = 18, message = "年龄不能小于18岁") @Max(value = 100, message = "年龄不能大于100岁") private Integer age; } // 异常响应格式示例: { "success": false, "code": "VALIDATION_ERROR", "message": "参数验证失败", "timestamp": 1640995200000, "path": "/api/users", "errors": { "username": "用户名不能为空", "email": "邮箱格式不正确" } } ``` ### 2. 📤 统一API响应格式 **功能描述**: 提供标准化的API响应格式,确保前后端接口的一致性 **实现类**: `ApiResponse` **使用示例**: ```java @RestController @RequestMapping("/api/products") public class ProductController { // 成功响应 - 返回数据 @GetMapping("/{id}") public ApiResponse getProduct(@PathVariable Long id) { Product product = productService.findById(id); return ApiResponse.success("查询成功", product); } // 成功响应 - 无数据 @DeleteMapping("/{id}") public ApiResponse deleteProduct(@PathVariable Long id) { productService.deleteById(id); return ApiResponse.success("删除成功"); } // 分页查询响应 @GetMapping public ApiResponse> getProducts( @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int size) { PageResult result = productService.findByPage(page, size); return ApiResponse.success("查询成功", result); } // 错误响应 @PostMapping public ApiResponse createProduct(@Valid @RequestBody CreateProductRequest request) { if (productService.existsByName(request.getName())) { return ApiResponse.businessError("PRODUCT_EXISTS", "产品名称已存在"); } Product product = productService.create(request); return ApiResponse.success("创建成功", product); } } // 响应格式示例: { "success": true, "code": "SUCCESS", "message": "查询成功", "data": { "id": 1, "name": "产品名称", "price": 99.99 }, "timestamp": 1640995200000 } ``` ### 3. 📊 分页查询支持 **功能描述**: 提供标准化的分页查询结果封装 **实现类**: `PageResult` **使用示例**: ```java @Service public class ProductService { @Autowired private ProductMapper productMapper; public PageResult findByPage(int page, int size) { // 使用MyBatis-Plus分页 Page pageParam = new Page<>(page, size); Page result = productMapper.selectPage(pageParam, null); return PageResult.builder() .records(result.getRecords()) .total(result.getTotal()) .current(result.getCurrent()) .size(result.getSize()) .pages(result.getPages()) .build(); } // 带条件的分页查询 public PageResult findByCondition(ProductQueryRequest request) { Page pageParam = new Page<>(request.getPage(), request.getSize()); QueryWrapper queryWrapper = new QueryWrapper<>(); if (StringUtils.hasText(request.getName())) { queryWrapper.like("name", request.getName()); } if (request.getMinPrice() != null) { queryWrapper.ge("price", request.getMinPrice()); } if (request.getMaxPrice() != null) { queryWrapper.le("price", request.getMaxPrice()); } Page result = productMapper.selectPage(pageParam, queryWrapper); return PageResult.fromPage(result); } } ``` ### 4. 🔄 Bean转换工具 **功能描述**: 提供对象之间的转换功能,简化DTO和Entity之间的转换 **实现类**: `BeanUtil` **使用示例**: ```java @Service public class UserService { // 单个对象转换 public UserDTO convertToDTO(User user) { return BeanUtil.convert(user, UserDTO.class); } // 列表转换 public List convertToDTOList(List users) { return BeanUtil.convertList(users, UserDTO.class); } // 使用Supplier转换(适用于复杂对象) public UserDetailDTO convertToDetailDTO(User user) { return BeanUtil.convert(user, () -> { UserDetailDTO dto = new UserDetailDTO(); // 可以在这里设置默认值 dto.setStatus("ACTIVE"); return dto; }); } // 忽略null值的属性复制 public void updateUser(Long id, UpdateUserRequest request) { User existingUser = findById(id); // 只复制非null的属性,避免覆盖现有数据 BeanUtil.copyPropertiesIgnoreNull(request, existingUser); userMapper.updateById(existingUser); } } // 实体类示例 @Data @TableName("users") public class User extends BaseEntity { private String username; private String email; private String phone; private Integer age; private String avatar; } // DTO示例 @Data public class UserDTO { private Long id; private String username; private String email; private String phone; private Integer age; private String avatar; private LocalDateTime createdTime; } ``` ### 5. 📝 日志切面 **功能描述**: 自动记录Controller方法的调用日志,包括请求参数和响应结果 **实现类**: `LoggingAspect` **使用示例**: ```java // 无需额外配置,自动对所有Controller方法生效 @RestController @RequestMapping("/api/orders") public class OrderController { @PostMapping public ApiResponse createOrder(@RequestBody CreateOrderRequest request) { // 自动记录日志: // [INFO] 开始执行方法: OrderController.createOrder // [INFO] 请求参数: {"productId":1,"quantity":2,"address":"北京市朝阳区"} Order order = orderService.createOrder(request); // [INFO] 方法执行完成: OrderController.createOrder, 耗时: 150ms // [INFO] 响应结果: {"success":true,"data":{"id":1,"orderNo":"ORD20240101001"}} return ApiResponse.success("订单创建成功", order); } @GetMapping("/{id}") public ApiResponse getOrder(@PathVariable Long id) { // 自动记录日志,包括路径参数 Order order = orderService.findById(id); return ApiResponse.success(order); } } // 日志输出示例: // 2024-01-01 10:30:15.123 [http-nio-8080-exec-1] INFO c.a.l.aspect.LoggingAspect - 开始执行方法: OrderController.createOrder // 2024-01-01 10:30:15.124 [http-nio-8080-exec-1] INFO c.a.l.aspect.LoggingAspect - 请求参数: [{"productId":1,"quantity":2}] // 2024-01-01 10:30:15.275 [http-nio-8080-exec-1] INFO c.a.l.aspect.LoggingAspect - 方法执行完成: OrderController.createOrder, 耗时: 151ms // 2024-01-01 10:30:15.276 [http-nio-8080-exec-1] INFO c.a.l.aspect.LoggingAspect - 响应结果: {"success":true,"code":"SUCCESS"} ``` ### 6. ⚡ 性能监控切面 **功能描述**: 监控Controller、Service、Mapper层方法的执行性能,超过阈值时发出警告 **实现类**: `PerformanceAspect` **使用示例**: ```java // 无需额外配置,自动监控所有层的方法性能 @Service public class ProductService { @Autowired private ProductMapper productMapper; public List findExpensiveProducts() { // 如果这个方法执行超过5秒,会自动记录警告日志 return productMapper.selectExpensiveProducts(); } public void batchUpdateProducts(List products) { // 批量操作可能耗时较长,会被监控 for (Product product : products) { productMapper.updateById(product); } } } @Repository public interface ProductMapper extends BaseMapper { // 复杂查询可能耗时较长,会被监控 @Select("SELECT * FROM products WHERE price > 1000 ORDER BY price DESC") List selectExpensiveProducts(); } // 性能监控日志示例: // 2024-01-01 10:30:15.123 [http-nio-8080-exec-1] WARN c.a.l.aspect.PerformanceAspect - [性能警告] Service层方法执行缓慢: ProductService.findExpensiveProducts, 耗时: 6543ms (阈值: 5000ms) // 2024-01-01 10:30:15.124 [http-nio-8080-exec-1] INFO c.a.l.aspect.PerformanceAspect - [性能监控] Mapper层方法执行: ProductMapper.selectExpensiveProducts, 耗时: 234ms // 配置性能阈值 (application.properties): app.performance.warning.controller=5000 # Controller层警告阈值5秒 app.performance.warning.service=3000 # Service层警告阈值3秒 app.performance.warning.mapper=500 # Mapper层警告阈值500毫秒 ``` ### 7. 🗄️ MyBatis-Plus集成 **功能描述**: 提供强大的ORM功能,包括基础CRUD、分页查询、条件构造器等 **实现类**: `BaseMapper`, `BaseEntity` **使用示例**: ```java // 1. 实体类继承BaseEntity @Data @EqualsAndHashCode(callSuper = true) @TableName("products") public class Product extends BaseEntity { @TableField("name") private String name; @TableField("description") private String description; @TableField("price") private BigDecimal price; @TableField("category_id") private Long categoryId; @TableField("stock") private Integer stock; @TableField("status") private Integer status; // 0-下架, 1-上架 } // 2. Mapper接口继承BaseMapper @Repository public interface ProductMapper extends BaseMapper { // 自定义查询方法 @Select("SELECT * FROM products WHERE category_id = #{categoryId} AND status = 1") List findByCategoryAndActive(@Param("categoryId") Long categoryId); // 复杂查询 @Select("SELECT p.*, c.name as category_name FROM products p " + "LEFT JOIN categories c ON p.category_id = c.id " + "WHERE p.price BETWEEN #{minPrice} AND #{maxPrice}") List findByPriceRange(@Param("minPrice") BigDecimal minPrice, @Param("maxPrice") BigDecimal maxPrice); } // 3. Service层使用示例 @Service public class ProductService { @Autowired private ProductMapper productMapper; // 基础CRUD操作 public Product save(Product product) { productMapper.insert(product); // 自动填充创建时间 return product; } public Product findById(Long id) { return productMapper.selectById(id); } public void deleteById(Long id) { productMapper.deleteById(id); // 逻辑删除 } public Product update(Product product) { productMapper.updateById(product); // 自动更新修改时间 return product; } // 条件查询 public List findByCondition(String name, BigDecimal minPrice, Integer status) { QueryWrapper queryWrapper = new QueryWrapper<>(); if (StringUtils.hasText(name)) { queryWrapper.like("name", name); } if (minPrice != null) { queryWrapper.ge("price", minPrice); } if (status != null) { queryWrapper.eq("status", status); } return productMapper.selectList(queryWrapper); } // 分页查询 public PageResult findByPage(int page, int size, String keyword) { Page pageParam = new Page<>(page, size); QueryWrapper queryWrapper = new QueryWrapper<>(); if (StringUtils.hasText(keyword)) { queryWrapper.and(wrapper -> wrapper .like("name", keyword) .or() .like("description", keyword) ); } queryWrapper.eq("status", 1); // 只查询上架商品 queryWrapper.orderByDesc("created_time"); Page result = productMapper.selectPage(pageParam, queryWrapper); return PageResult.fromPage(result); } // 批量操作 public void batchInsert(List products) { // MyBatis-Plus会自动优化批量插入 for (Product product : products) { productMapper.insert(product); } } } ``` ### 9. 🔒 Spring Security集成 **功能描述**: 提供基础的安全配置,支持认证和授权 **配置类**: `SecurityConfig` **使用示例**: ```java // 当前配置允许所有请求访问,可以根据需要自定义安全规则 @Configuration @EnableWebSecurity public class CustomSecurityConfig { @Autowired private UserDetailsService userDetailsService; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(authz -> authz // 公开接口 .requestMatchers("/api/auth/**", "/api/public/**").permitAll() .requestMatchers("/actuator/**", "/api-docs/**", "/swagger-ui/**").permitAll() // 需要认证的接口 .requestMatchers("/api/admin/**").hasRole("ADMIN") .requestMatchers("/api/user/**").hasAnyRole("USER", "ADMIN") .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login") .loginProcessingUrl("/api/auth/login") .successHandler(authenticationSuccessHandler()) .failureHandler(authenticationFailureHandler()) ) .logout(logout -> logout .logoutUrl("/api/auth/logout") .logoutSuccessHandler(logoutSuccessHandler()) ) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .maximumSessions(1) .maxSessionsPreventsLogin(false) ); return http.build(); } // 认证成功处理器 @Bean public AuthenticationSuccessHandler authenticationSuccessHandler() { return (request, response, authentication) -> { response.setContentType("application/json;charset=UTF-8"); ApiResponse result = ApiResponse.success("登录成功", getUserInfo(authentication)); response.getWriter().write(JSON.toJSONString(result)); }; } } // 用户认证Controller @RestController @RequestMapping("/api/auth") public class AuthController { @PostMapping("/login") public ApiResponse login(@RequestBody LoginRequest request, HttpServletRequest httpRequest) { // Spring Security会自动处理认证 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); UserInfo userInfo = getUserInfo(authentication); return ApiResponse.success("登录成功", userInfo); } @PostMapping("/logout") public ApiResponse logout(HttpServletRequest request) { SecurityContextHolder.clearContext(); request.getSession().invalidate(); return ApiResponse.success("退出成功"); } @GetMapping("/current") public ApiResponse getCurrentUser() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null || !authentication.isAuthenticated()) { return ApiResponse.error("UNAUTHORIZED", "未登录"); } UserInfo userInfo = getUserInfo(authentication); return ApiResponse.success(userInfo); } } ``` ### 10. 📚 Swagger API文档 **功能描述**: 自动生成API文档,支持在线测试 **配置类**: `SwaggerConfig` **使用示例**: ```java // 在Controller中添加Swagger注解 @RestController @RequestMapping("/api/products") @Tag(name = "商品管理", description = "商品相关的API接口") public class ProductController { @Operation(summary = "创建商品", description = "创建一个新的商品") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "创建成功"), @ApiResponse(responseCode = "400", description = "参数错误"), @ApiResponse(responseCode = "500", description = "服务器错误") }) @PostMapping public ApiResponse createProduct( @Parameter(description = "商品信息", required = true) @Valid @RequestBody CreateProductRequest request) { Product product = productService.createProduct(request); return ApiResponse.success("创建成功", product); } @Operation(summary = "获取商品详情", description = "根据商品ID获取商品详细信息") @GetMapping("/{id}") public ApiResponse getProduct( @Parameter(description = "商品ID", required = true, example = "1") @PathVariable Long id) { Product product = productService.findById(id); return ApiResponse.success(product); } @Operation(summary = "商品列表查询", description = "分页查询商品列表,支持关键词搜索") @GetMapping public ApiResponse> getProducts( @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") int page, @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") int size, @Parameter(description = "搜索关键词") @RequestParam(required = false) String keyword) { PageResult result = productService.findByPage(page, size, keyword); return ApiResponse.success("查询成功", result); } } // DTO类添加Swagger注解 @Data @Schema(description = "创建商品请求") public class CreateProductRequest { @Schema(description = "商品名称", example = "iPhone 15 Pro", required = true) @NotBlank(message = "商品名称不能为空") private String name; @Schema(description = "商品描述", example = "最新款iPhone手机") private String description; @Schema(description = "商品价格", example = "8999.00", required = true) @NotNull(message = "商品价格不能为空") @DecimalMin(value = "0.01", message = "商品价格必须大于0") private BigDecimal price; @Schema(description = "商品分类ID", example = "1", required = true) @NotNull(message = "商品分类不能为空") private Long categoryId; @Schema(description = "库存数量", example = "100", required = true) @NotNull(message = "库存数量不能为空") @Min(value = 0, message = "库存数量不能为负数") private Integer stock; } // 访问Swagger UI: http://localhost:8080/swagger-ui.html // 访问API文档JSON: http://localhost:8080/api-docs ``` ## 🚀 快速开始 ### 1. 创建实体类 ```java @Data @EqualsAndHashCode(callSuper = true) @TableName("your_table") public class YourEntity extends BaseEntity { private String name; private String description; // 其他字段... } ``` ### 2. 创建Mapper接口 ```java @Repository public interface YourEntityMapper extends BaseMapper { // 自定义查询方法 } ``` ### 3. 创建Service类 ```java @Service public class YourEntityService { @Autowired private YourEntityMapper mapper; // 业务逻辑方法 } ``` ### 4. 创建Controller类 ```java @RestController @RequestMapping("/api/your-entity") public class YourEntityController { @Autowired private YourEntityService service; // API接口方法 } ``` ## 📝 配置说明 ### 数据库配置 ```properties # MySQL数据库连接 spring.datasource.url=jdbc:mysql://localhost:3306/your_database spring.datasource.username=your_username spring.datasource.password=your_password ``` ### 文件上传配置 ```properties # 文件上传大小限制 spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=50MB app.upload.dir=./uploads/ ``` ### 性能监控配置 ```properties # 性能警告阈值(毫秒) app.performance.warning.controller=5000 app.performance.warning.service=3000 app.performance.warning.mapper=500 ``` 这个架构模板提供了完整的企业级应用基础设施,您可以在此基础上快速开发各种类型的业务应用!