Java分层规范案例如何搭建

wen java案例 28

本文目录导读:

Java分层规范案例如何搭建

  1. 项目结构搭建
  2. 各层代码实现
  3. 配置说明
  4. 规范的调用流程

我来为你详细介绍Java分层规范的搭建方法,以一个实际案例来说明。

项目结构搭建

以一个简单的电商系统为例,展示Java分层架构:

ecommerce-app
├── src/main/java
│   └── com/ecommerce
│       ├── controller          # 控制器层
│       │   ├── UserController.java
│       │   └── OrderController.java
│       ├── service             # 服务层
│       │   ├── UserService.java
│       │   └── OrderService.java
│       ├── service/impl        # 服务实现
│       │   ├── UserServiceImpl.java
│       │   └── OrderServiceImpl.java
│       ├── repository          # 数据访问层
│       │   ├── UserRepository.java
│       │   └── OrderRepository.java
│       ├── entity              # 实体类
│       │   ├── User.java
│       │   └── Order.java
│       ├── dto                 # 数据传输对象
│       │   ├── UserDTO.java
│       │   └── OrderDTO.java
│       ├── vo                  # 视图对象
│       │   ├── UserVO.java
│       │   └── OrderVO.java
│       └── common              # 公共模块
│           ├── result          # 统一返回结果
│           │   └── Result.java
│           ├── exception       # 异常处理
│           │   └── GlobalExceptionHandler.java
│           └── config          # 配置类
│               └── WebConfig.java

各层代码实现

1 实体层(Entity)

// entity/User.java
@Data
@TableName("user")  // MyBatis-Plus注解
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String username;
    private String password;
    private String email;
    private String phone;
    private Integer status;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}

2 数据访问层(Repository)

// repository/UserRepository.java
@Repository
public interface UserRepository extends BaseMapper<User> {
    @Select("SELECT * FROM user WHERE username = #{username}")
    User findByUsername(String username);
    @Select("SELECT * FROM user WHERE email = #{email}")
    User findByEmail(String email);
}

3 DTO层(数据传输对象)

// dto/LoginDTO.java
@Data
public class LoginDTO {
    @NotBlank(message = "用户名不能为空")
    private String username;
    @NotBlank(message = "密码不能为空")
    private String password;
}
// dto/UserCreateDTO.java
@Data
public class UserCreateDTO {
    @NotBlank(message = "用户名不能为空")
    @Size(min = 3, max = 20, message = "用户名长度3-20个字符")
    private String username;
    @NotBlank(message = "密码不能为空")
    @Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{6,20}$", 
             message = "密码必须包含大小写字母和数字")
    private String password;
    @Email(message = "邮箱格式不正确")
    private String email;
    private String phone;
}

4 服务层(Service)

// service/impl/UserServiceImpl.java
@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private UserRepository userRepository;
    @Override
    public UserVO login(LoginDTO loginDTO) {
        // 业务逻辑处理
        User user = userRepository.findByUsername(loginDTO.getUsername());
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        // 密码校验
        if (!passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
            throw new BusinessException("密码错误");
        }
        // 转换为VO返回
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }
    @Override
    @Transactional
    public UserVO createUser(UserCreateDTO userCreateDTO) {
        // 检查用户名是否已存在
        User existUser = userRepository.findByUsername(userCreateDTO.getUsername());
        if (existUser != null) {
            throw new BusinessException("用户名已存在");
        }
        // DTO转Entity
        User user = new User();
        BeanUtils.copyProperties(userCreateDTO, user);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setStatus(1);
        // 保存
        userRepository.insert(user);
        // Entity转VO
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }
    @Override
    public PageResult<UserVO> getUserList(int page, int size) {
        Page<User> pageInfo = new Page<>(page, size);
        Page<User> userPage = userRepository.selectPage(pageInfo, null);
        List<UserVO> userVOs = userPage.getRecords().stream()
            .map(user -> {
                UserVO userVO = new UserVO();
                BeanUtils.copyProperties(user, userVO);
                return userVO;
            })
            .collect(Collectors.toList());
        return new PageResult<>(userVOs, userPage.getTotal(), page, size);
    }
}

5 控制器层(Controller)

// controller/UserController.java
@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {
    @Autowired
    private UserService userService;
    @PostMapping("/login")
    public Result<UserVO> login(@Valid @RequestBody LoginDTO loginDTO) {
        UserVO userVO = userService.login(loginDTO);
        return Result.success(userVO);
    }
    @PostMapping
    public Result<UserVO> createUser(@Valid @RequestBody UserCreateDTO userCreateDTO) {
        UserVO userVO = userService.createUser(userCreateDTO);
        return Result.success(userVO);
    }
    @GetMapping
    public Result<PageResult<UserVO>> getUserList(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size) {
        return Result.success(userService.getUserList(page, size));
    }
}

6 统一响应封装

// common/result/Result.java
@Data
public class Result<T> {
    private Integer code;
    private String message;
    private T data;
    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<>();
        result.setCode(200);
        result.setMessage("success");
        result.setData(data);
        return result;
    }
    public static <T> Result<T> error(Integer code, String message) {
        Result<T> result = new Result<>();
        result.setCode(code);
        result.setMessage(message);
        return result;
    }
}
// common/exception/BusinessException.java
public class BusinessException extends RuntimeException {
    private Integer code;
    public BusinessException(String message) {
        super(message);
        this.code = 500;
    }
    public BusinessException(Integer code, String message) {
        super(message);
        this.code = code;
    }
}

7 全局异常处理

// common/exception/GlobalExceptionHandler.java
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<Void> handleValidationException(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldErrors().stream()
            .map(FieldError::getDefaultMessage)
            .collect(Collectors.joining(", "));
        return Result.error(400, message);
    }
    @ExceptionHandler(BusinessException.class)
    public Result<Void> handleBusinessException(BusinessException e) {
        log.error("业务异常:{}", e.getMessage());
        return Result.error(e.getCode(), e.getMessage());
    }
    @ExceptionHandler(Exception.class)
    public Result<Void> handleException(Exception e) {
        log.error("系统异常:", e);
        return Result.error(500, "系统内部异常");
    }
}

配置说明

1 Maven依赖

<dependencies>
    <!-- Spring Boot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- MyBatis-Plus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.2</version>
    </dependency>
    <!-- 参数校验 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <!-- 工具类 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

2 配置文件

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/ecommerce?useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true

规范的调用流程

Controller(接收请求)→ DTO(数据校验)→ Service(业务逻辑)→ Repository(数据操作)
                ↓                     ↓
              VO(视图响应)     Entity(持久化对象)

这个分层架构的好处:

  • 解耦性:各层职责清晰,互相隔离
  • 可维护性:修改某一层不影响其他层
  • 可测试性:各层可以独立进行单元测试
  • 安全性:数据在上层进行校验和转换,避免直接暴露底层数据结构

抱歉,评论功能暂时关闭!