first commit
This commit is contained in:
708
ARCHITECTURE.md
Normal file
708
ARCHITECTURE.md
Normal file
@@ -0,0 +1,708 @@
|
||||
# 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<User> 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<User> 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<T>`
|
||||
|
||||
**使用示例**:
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/api/products")
|
||||
public class ProductController {
|
||||
|
||||
// 成功响应 - 返回数据
|
||||
@GetMapping("/{id}")
|
||||
public ApiResponse<Product> getProduct(@PathVariable Long id) {
|
||||
Product product = productService.findById(id);
|
||||
return ApiResponse.success("查询成功", product);
|
||||
}
|
||||
|
||||
// 成功响应 - 无数据
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResponse<Void> deleteProduct(@PathVariable Long id) {
|
||||
productService.deleteById(id);
|
||||
return ApiResponse.success("删除成功");
|
||||
}
|
||||
|
||||
// 分页查询响应
|
||||
@GetMapping
|
||||
public ApiResponse<PageResult<Product>> getProducts(
|
||||
@RequestParam(defaultValue = "1") int page,
|
||||
@RequestParam(defaultValue = "10") int size) {
|
||||
PageResult<Product> result = productService.findByPage(page, size);
|
||||
return ApiResponse.success("查询成功", result);
|
||||
}
|
||||
|
||||
// 错误响应
|
||||
@PostMapping
|
||||
public ApiResponse<Product> 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<T>`
|
||||
|
||||
**使用示例**:
|
||||
```java
|
||||
@Service
|
||||
public class ProductService {
|
||||
|
||||
@Autowired
|
||||
private ProductMapper productMapper;
|
||||
|
||||
public PageResult<Product> findByPage(int page, int size) {
|
||||
// 使用MyBatis-Plus分页
|
||||
Page<Product> pageParam = new Page<>(page, size);
|
||||
Page<Product> result = productMapper.selectPage(pageParam, null);
|
||||
|
||||
return PageResult.<Product>builder()
|
||||
.records(result.getRecords())
|
||||
.total(result.getTotal())
|
||||
.current(result.getCurrent())
|
||||
.size(result.getSize())
|
||||
.pages(result.getPages())
|
||||
.build();
|
||||
}
|
||||
|
||||
// 带条件的分页查询
|
||||
public PageResult<Product> findByCondition(ProductQueryRequest request) {
|
||||
Page<Product> pageParam = new Page<>(request.getPage(), request.getSize());
|
||||
|
||||
QueryWrapper<Product> 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<Product> 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<UserDTO> convertToDTOList(List<User> 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<Order> 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<Order> 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<Product> findExpensiveProducts() {
|
||||
// 如果这个方法执行超过5秒,会自动记录警告日志
|
||||
return productMapper.selectExpensiveProducts();
|
||||
}
|
||||
|
||||
public void batchUpdateProducts(List<Product> products) {
|
||||
// 批量操作可能耗时较长,会被监控
|
||||
for (Product product : products) {
|
||||
productMapper.updateById(product);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Repository
|
||||
public interface ProductMapper extends BaseMapper<Product> {
|
||||
|
||||
// 复杂查询可能耗时较长,会被监控
|
||||
@Select("SELECT * FROM products WHERE price > 1000 ORDER BY price DESC")
|
||||
List<Product> 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<T>`, `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<Product> {
|
||||
|
||||
// 自定义查询方法
|
||||
@Select("SELECT * FROM products WHERE category_id = #{categoryId} AND status = 1")
|
||||
List<Product> 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<ProductVO> 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<Product> findByCondition(String name, BigDecimal minPrice, Integer status) {
|
||||
QueryWrapper<Product> 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<Product> findByPage(int page, int size, String keyword) {
|
||||
Page<Product> pageParam = new Page<>(page, size);
|
||||
|
||||
QueryWrapper<Product> 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<Product> result = productMapper.selectPage(pageParam, queryWrapper);
|
||||
return PageResult.fromPage(result);
|
||||
}
|
||||
|
||||
// 批量操作
|
||||
public void batchInsert(List<Product> 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<UserInfo> result = ApiResponse.success("登录成功", getUserInfo(authentication));
|
||||
response.getWriter().write(JSON.toJSONString(result));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 用户认证Controller
|
||||
@RestController
|
||||
@RequestMapping("/api/auth")
|
||||
public class AuthController {
|
||||
|
||||
@PostMapping("/login")
|
||||
public ApiResponse<UserInfo> 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<Void> logout(HttpServletRequest request) {
|
||||
SecurityContextHolder.clearContext();
|
||||
request.getSession().invalidate();
|
||||
return ApiResponse.success("退出成功");
|
||||
}
|
||||
|
||||
@GetMapping("/current")
|
||||
public ApiResponse<UserInfo> 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<Product> 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<Product> 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<PageResult<Product>> 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<Product> 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<YourEntity> {
|
||||
// 自定义查询方法
|
||||
}
|
||||
```
|
||||
|
||||
### 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
|
||||
```
|
||||
|
||||
这个架构模板提供了完整的企业级应用基础设施,您可以在此基础上快速开发各种类型的业务应用!
|
||||
Reference in New Issue
Block a user