Spring的分层架构

各层之间的关系与数据流动
Controller层接收请求:
客户端发送HTTP请求到Controller层。
Controller处理请求参数,调用Service层进行业务处理。
Service层处理业务逻辑:
Service层接收来自Controller的请求,执行必要的业务逻辑。
调用DAO层或Mapper层进行数据访问操作。
DAO/Mapper层与数据库交互:
DAO层或Mapper层执行具体的SQL语句,与数据库进行交互。
将数据库结果映射为Java对象,返回给Service层。
Controller层构建响应:
Service层处理完成后,将结果返回给Controller。
Controller将结果封装为适当的响应格式(如JSON),发送回客户端

客户端请求

Controller层 (接收请求,参数验证)

Service层 (业务逻辑处理)

DAO/Mapper层 (数据访问,执行SQL)

数据库

DAO/Mapper层 (获取查询结果)

Service层 (处理结果)

Controller层 (构建响应)

客户端响应

  1. Controller 层
    职责:
    处理HTTP请求:接收来自客户端(如浏览器、移动应用等)的HTTP请求。
    参数验证与绑定:验证请求参数的有效性,并将请求数据绑定到相应的Java对象。
    调用服务层:将处理逻辑委托给Service层,进行具体的业务处理。
    响应构建:根据Service层的处理结果,构建并返回适当的HTTP响应(如JSON、XML等)
    @RestController
    @RequestMapping("/users")
    public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public ResponseEntity<UserDTO> getUserById(@PathVariable Long id) {
    UserDTO user = userService.getUserById(id);
    if (user != null) {
    return ResponseEntity.ok(user);
    } else {
    return ResponseEntity.notFound().build();
    }
    }

    @PostMapping
    public ResponseEntity<UserDTO> createUser(@RequestBody UserDTO userDTO) {
    UserDTO createdUser = userService.createUser(userDTO);
    return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
    }
    }

  2. Service 层(业务逻辑层)
    职责:
    业务逻辑处理:实现具体的业务规则和逻辑。
    事务管理:通常在这一层管理事务,确保数据的一致性和完整性。
    调用DAO/Mapper层:与数据访问层交互,进行数据的增删改查操作。
    @Service
    public class UserService {

    @Autowired
    private UserMapper userMapper;

    public UserDTO getUserById(Long id) {
    User user = userMapper.selectByPrimaryKey(id);
    if (user != null) {
    return convertToDTO(user);
    }
    return null;
    }

    public UserDTO createUser(UserDTO userDTO) {
    User user = convertToEntity(userDTO);
    userMapper.insert(user);
    return convertToDTO(user);
    }

    // 转换方法
    private UserDTO convertToDTO(User user) { /* ... / }
    private User convertToEntity(UserDTO userDTO) { /
    ... */ }
    }

  3. ServiceImpl 层(服务实现层)
    职责:
    具体实现业务逻辑:在某些架构中,Service 层仅定义接口,具体的实现放在ServiceImpl 层。
    扩展Service功能:可以在ServiceImpl 中添加额外的功能,如日志记录、性能监控等,而不影响Service接口的纯粹性。
    说明:在许多项目中,Service 层和ServiceImpl 层可能合并在一起,尤其是在使用Spring等框架时,通过注解直接在接口的实现类上标注@Service。然而,在一些复杂项目中,为了更好的代码组织和可维护性,会将接口和实现分离。
    // 接口
    public interface UserService {
    UserDTO getUserById(Long id);
    UserDTO createUser(UserDTO userDTO);
    }

// 实现类
@Service
public class UserServiceImpl implements UserService {

@Autowired
private UserMapper userMapper;

@Override
public UserDTO getUserById(Long id) {
    User user = userMapper.selectByPrimaryKey(id);
    if (user != null) {
        return convertToDTO(user);
    }
    return null;
}

@Override
public UserDTO createUser(UserDTO userDTO) {
    User user = convertToEntity(userDTO);
    userMapper.insert(user);
    return convertToDTO(user);
}

// 转换方法
private UserDTO convertToDTO(User user) { /* ... */ }
private User convertToEntity(UserDTO userDTO) { /* ... */ }

}

  1. DAO 层(数据访问对象层)
    职责:
    数据访问抽象:定义与数据库交互的接口,隐藏具体的实现细节。
    持久化操作:负责执行CRUD(创建、读取、更新、删除)操作。
    说明:
    在许多现代框架中,DAO层的实现通常由ORM(对象关系映射)工具如Hibernate、MyBatis等完成。因此,Mapper层常常被视为DAO层的一部分,特别是在使用MyBatis时。

@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;

@Override
public User selectByPrimaryKey(Long id) {
    // JDBC实现
}

@Override
public void insert(User user) {
    // JDBC实现
}

}

  1. Mapper 层
    职责:
    SQL映射:将Java方法与具体的SQL语句进行映射,通常通过XML配置文件或注解实现。
    数据映射:将数据库查询结果映射到Java对象(DTO或Entity)。
    说明:
    在使用MyBatis时,Mapper层通常取代传统的DAO层,负责具体的SQL执行和结果映射。

示例(使用MyBatis):
Mapper 接口:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.mapper.UserMapper">
<select id="selectByPrimaryKey" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>

<insert id="insert">
    INSERT INTO users (name, email) VALUES (#{name}, #{email})
</insert>
<!-- 其他SQL语句 -->

</mapper>
使用注解的Mapper接口:
@Mapper
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User selectByPrimaryKey(Long id);

@Insert("INSERT INTO users (name, email) VALUES (#{name}, #{email})")
void insert(User user);

}

在现代软件开发中,尤其是基于Java的企业级应用开发中,采用分层架构(Layered Architecture)有助于代码的组织、维护和扩展。常见的分层包括 Controller 层、Service 层、ServiceImpl 层、DAO 层、Mapper 层 和 Meta 层。下面详细介绍每一层的职责和作用:

  1. Controller 层(控制层)
    职责:
    处理用户请求:接收来自客户端(如浏览器、移动应用等)的HTTP请求。
    参数验证与绑定:验证请求参数的有效性,并将请求数据绑定到相应的Java对象(如DTO)。
    调用业务逻辑层:将处理逻辑委托给Service层,进行具体的业务处理。
    响应构建:根据Service层的处理结果,构建并返回适当的HTTP响应(如JSON、XML等)。
    异常处理:捕获并处理来自下层的异常,向客户端返回友好的错误信息。
    示例:
    java
    复制
    @RestController
    @RequestMapping("/users")
    public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public ResponseEntity<UserDTO> getUserById(@PathVariable Long id) {
    UserDTO user = userService.getUserById(id);
    if (user != null) {
    return ResponseEntity.ok(user);
    } else {
    return ResponseEntity.notFound().build();
    }
    }

    @PostMapping
    public ResponseEntity<UserDTO> createUser(@RequestBody UserDTO userDTO) {
    UserDTO createdUser = userService.createUser(userDTO);
    return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
    }
    }

  2. Service 层(服务层)
    职责:
    业务逻辑处理:实现具体的业务规则和逻辑,协调不同模块之间的交互。
    事务管理:通常在这一层管理事务,确保数据的一致性和完整性。
    调用数据访问层:与DAO层或Mapper层交互,进行数据的增删改查操作。
    提供接口:为Controller层提供清晰的业务接口,隐藏实现细节。
    示例:
    java
    复制
    @Service
    public class UserService {

    @Autowired
    private UserMapper userMapper;

    public UserDTO getUserById(Long id) {
    User user = userMapper.selectByPrimaryKey(id);
    if (user != null) {
    return convertToDTO(user);
    }
    return null;
    }

    public UserDTO createUser(UserDTO userDTO) {
    User user = convertToEntity(userDTO);
    userMapper.insert(user);
    return convertToDTO(user);
    }

    // 转换方法
    private UserDTO convertToDTO(User user) { /* ... / }
    private User convertToEntity(UserDTO userDTO) { /
    ... */ }
    }

  3. ServiceImpl 层(服务实现层)
    职责:
    具体实现业务逻辑:在某些架构中,Service 层仅定义接口,具体的实现放在ServiceImpl 层。
    扩展Service功能:可以在ServiceImpl 中添加额外的功能,如日志记录、性能监控等,而不影响Service接口的纯粹性。
    说明:
    在许多项目中,Service 层和ServiceImpl 层可能合并在一起,尤其是在使用Spring等框架时,通过注解直接在接口的实现类上标注@Service。然而,在一些复杂项目中,为了更好的代码组织和可维护性,会将接口和实现分离。

示例:
java
复制
// 接口
public interface UserService {
UserDTO getUserById(Long id);
UserDTO createUser(UserDTO userDTO);
}

// 实现类
@Service
public class UserServiceImpl implements UserService {

@Autowired
private UserMapper userMapper;

@Override
public UserDTO getUserById(Long id) {
    User user = userMapper.selectByPrimaryKey(id);
    if (user != null) {
        return convertToDTO(user);
    }
    return null;
}

@Override
public UserDTO createUser(UserDTO userDTO) {
    User user = convertToEntity(userDTO);
    userMapper.insert(user);
    return convertToDTO(user);
}

// 转换方法
private UserDTO convertToDTO(User user) { /* ... */ }
private User convertToEntity(UserDTO userDTO) { /* ... */ }

}

  1. DAO 层(数据访问对象层)
    职责:
    数据访问抽象:定义与数据库交互的接口,隐藏具体的实现细节。
    持久化操作:负责执行CRUD(创建、读取、更新、删除)操作。
    说明:
    在许多现代框架中,DAO层的实现通常由ORM(对象关系映射)工具如Hibernate、MyBatis等完成。因此,Mapper层常常被视为DAO层的一部分,特别是在使用MyBatis时。

示例(传统DAO方式):
java
复制
public interface UserDao {
User selectByPrimaryKey(Long id);
void insert(User user);
// 其他CRUD方法
}

@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;

@Override
public User selectByPrimaryKey(Long id) {
    // JDBC实现
}

@Override
public void insert(User user) {
    // JDBC实现
}

}

  1. Mapper 层(映射层)
    职责:
    SQL映射:将Java方法与具体的SQL语句进行映射,通常通过XML配置文件或注解实现。
    数据映射:将数据库查询结果映射为Java对象(DTO或Entity)。
    说明:
    在使用MyBatis时,Mapper层通常取代传统的DAO层,负责具体的SQL执行和结果映射。Mapper接口定义了数据访问的方法,而具体的SQL语句可以通过XML文件或注解进行定义。

示例(使用MyBatis):
Mapper 接口:
java
复制
@Mapper
public interface UserMapper {
User selectByPrimaryKey(Long id);
void insert(User user);
// 其他CRUD方法
}
Mapper XML(可选,如果使用注解则不需要):
xml
复制
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.mapper.UserMapper">
<select id="selectByPrimaryKey" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>

<insert id="insert">
    INSERT INTO users (name, email) VALUES (#{name}, #{email})
</insert>
<!-- 其他SQL语句 -->

</mapper>
使用注解的Mapper接口:
java
复制
@Mapper
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User selectByPrimaryKey(Long id);

@Insert("INSERT INTO users (name, email) VALUES (#{name}, #{email})")
void insert(User user);

}

  1. Meta 层(元数据层)
    职责:
    元数据管理:处理与数据字典、配置信息、枚举类型等相关的操作。
    提供统一的数据访问:集中管理应用程序中的静态数据和配置信息,确保数据的一致性和可维护性。
    辅助功能:提供辅助功能,如数据校验、转换、国际化支持等。
    说明:
    Meta 层并不是所有项目都会明确划分的层次,但在一些复杂项目中,为了管理全局配置、枚举类型、数据字典等,可能会单独设立这一层。它通常为其他层提供支持,确保数据的统一管理和使用。

示例:
数据字典服务:
@Service
public class MetaDataService {

@Autowired
private MetaDataMapper metaDataMapper;

public Map<String, String> getConfigurations() {
    List<Config> configs = metaDataMapper.selectAllConfigs();
    return configs.stream()
                  .collect(Collectors.toMap(Config::getKey, Config::getValue));
}

public String getConfiguration(String key) {
    Config config = metaDataMapper.selectConfigByKey(key);
    return config != null ? config.getValue() : null;
}

}
枚举示例:
public enum UserStatus {
ACTIVE("A", "活跃"),
INACTIVE("I", "不活跃"),
DELETED("D", "已删除");
private String code;
private String description;

UserStatus(String code, String description) {
    this.code = code;
    this.description = description;
}
// Getter 方法
public static UserStatus fromCode(String code) {
    for (UserStatus status : values()) {
        if (status.getCode().equals(code)) {
            return status;
        }
    }
    throw new IllegalArgumentException("Unknown code: " + code);
}

}
各层之间的关系与数据流动

Controller 层接收请求:
客户端发送HTTP请求到Controller层。
Controller处理请求参数,调用Service层进行业务处理。

Service 层处理业务逻辑:
Service层接收来自Controller的请求,执行必要的业务逻辑。
调用DAO层或Mapper层进行数据访问操作。

Mapper/DAO 层与数据库交互:
Mapper层或DAO层执行具体的SQL语句,与数据库进行交互。
将数据库结果映射为Java对象,返回给Service层。

Meta 层提供支持:
Meta层为其他层提供元数据、配置信息等支持,确保数据的一致性和可维护性

Controller 层构建响应:
Service层处理完成后,将结果返回给Controller。
Controller将结果封装为适当的响应格式(如JSON),发送回客户端

客户端请求

Controller层 (接收请求,参数验证)

Service层 (业务逻辑处理)

Mapper/DAO层 (数据访问,执行SQL)

数据库

Mapper/DAO层 (获取查询结果)

Service层 (处理结果)

Controller层 (构建响应)

客户端响应

DAO 层
抽象层次:更高层次的抽象,通常不涉及具体的SQL语句。它提供的是数据访问的方法接口,具体实现可以基于不同的技术(如JDBC、Hibernate等)。
关注点:业务逻辑与数据访问逻辑的分离,提供统一的数据访问接口。
Mapper 层
抽象层次:更接近底层实现,直接与SQL语句和数据库交互。它负责将SQL语句与Java方法对应起来,并处理结果集的映射。
关注点:具体的数据查询和映射,如何将数据库记录转换为Java对象。

  1. 使用场景与工具链
    DAO 层
    适用场景:
    需要高度定制化的数据访问逻辑。
    使用多种数据访问技术(如JDBC、Hibernate、JPA等)。
    需要更灵活的事务管理和连接管理。
    常用工具:
    JDBC
    Hibernate
    JPA
    Spring Data JPA
    Mapper 层
    适用场景:
    使用ORM框架(如MyBatis)进行数据访问。
    需要编写复杂的SQL语句或进行精细的查询优化。
    希望将SQL语句与Java代码分离,便于维护和管理。
    常用工具:
    MyBatis
    MyBatis-Plus(MyBatis的增强工具)
  2. 优缺点对比
    DAO 层
    优点:
    高度抽象:与具体实现解耦,便于更换底层数据访问技术。
    灵活性强:可以根据需要选择不同的数据访问方式(如JDBC、Hibernate等)。
    统一接口:为业务层提供一致的数据访问接口,简化调用。
    缺点:
    复杂性高:需要手动编写较多的代码,尤其是在使用JDBC时。
    维护成本高:数据访问逻辑分散在不同的实现类中,可能导致维护困难。
    Mapper 层
    优点:
    简洁明了:通过XML或注解直接定义SQL语句,便于编写和优化查询。
    与ORM框架集成良好:如MyBatis提供了强大的映射功能,简化了结果集的处理。
    易于维护:SQL语句集中管理,便于修改和调试。
    缺点:
    依赖特定框架:通常与特定的ORM框架(如MyBatis)紧密绑定,切换框架成本较高。
    学习曲线:需要掌握框架特定的配置和使用方式,如MyBatis的XML配置或注解用法。
  3. 在项目中的结合使用
    在实际项目中,DAO层和Mapper层并不是互斥的,而是可以根据需要结合使用。例如,可以在Service层之下同时存在DAO层和Mapper层,其中DAO层负责更高层次的数据访问接口,而Mapper层负责具体的SQL映射和执行。

Controller 层

Service 层

DAO 层(抽象接口)

Mapper 层(MyBatis Mapper 接口)

数据库

Service 层
定义:Service 层是业务逻辑层,负责处理应用程序的核心业务逻辑。它定义了业务操作的接口,为上层(如Controller层)提供统一的服务接口。
职责:封装业务逻辑,确保控制器(Controller)只负责请求的接收和响应的返回。
管理事务,确保数据的一致性和完整性。
协调不同的组件或模块,完成复杂的业务流程。
提供清晰、简洁的业务方法供其他层调用。

ServiceImpl 层
定义:ServiceImpl 层是 Service 层的具体实现部分,负责实现 Service 接口中定义的业务逻辑方法。它包含实际的业务处理代码,通常与数据访问层(如 DAO 层或 Mapper 层)交互,完成具体的数据操作。
职责:实现 Service 接口中声明的所有业务方法。
包含具体的业务规则和处理逻辑。
调用数据访问层进行数据的增删改查操作。
处理异常,确保系统的健壮性。

Controller 层

Service 层(接口)

ServiceImpl 层(实现)

DAO/Mapper 层

数据库

Controller 层:接收客户端请求,进行参数校验,调用 Service 层处理业务逻辑,并返回响应。
Service 层:定义业务接口,声明业务方法。
ServiceImpl 层:实现 Service 接口,编写具体的业务逻辑代码。
DAO/Mapper 层:负责与数据库交互,进行数据的持久化操作。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容