MVC(Model-View-Controller)是一种软件设计模式,用于将应用程序分为主要的部分:模型(Model)、视图(View)和控制器(Controller)。这种架构有助于提高代码的可维护性和可扩展性。
定义:模型层负责数据的处理与存储,包括业务逻辑层的实现
作用:处理数据,如数据库查询、数据验证等
示例:在Java中,模型通常是由POJO(Plain Old Java Object)类和DAO(Data Access Object)类组成。
定义:视图层负责展示数据给用户,是用户界面的部分。
作用:接收用户的输入,并显示从模型层获取的数据。
示例:在web应用中,视图可以是JSP页面、HTML页面或Thymeleaf模板。
定义:视图层负责展示数据给用户,是用户界面的部分。
作用:接收用户的输入,并显示从模型层获取数据
示例:在Spring框架中,控制器通常是带有@Controller注解的类。
分离关注点:将业务逻辑、数据访问和用户界面分离,使得每个部分可以独立开发和测试。
提高可维护性:代码结构清晰,易于理解和维护
提高可扩展性:可以轻松地添加新的功能或修改现有功能,而不会影响其他部分。
常用框架:SpringMVC、Struts2
工作流程:
用户通过浏览器发送请求到服务器。
前端控制器(DispatcherServlet)接收到请求,根据请求信息调用相应的处理器映射器(HandlerMapping)。
处理器映射器找到对应的处理器(Controller)。
控制器调用模型层进行业务处理。
模型层处理完业务后返回数据给控制器。
控制器选择合适的视图进行渲染,并将数据传递给视图。
视图生成最终的HTML页面,返回给前端控制器。
前端控制器将响应返回给用户。
三层指的是Web层(界面层)、Service层(业务逻辑层)、Dao层(数据持久层)
Web层,界面层(例如:餐厅中的服务员)
只负责与前端进行交互,处理用户的请求,并将结果返回给用户。至于业务逻辑如何处理,Web层不关心。Servlet/Controller可以充当。
Service层,业务逻辑层 (例如:厨师)
只负责处理核心的业务逻辑,至于是谁发的请求,Service层不关心。它与Web层和Dao层进行交互,但不直接与前端或数据库交互。是系统架构中最重要的一层,Service层的设计是否灵活,通用,就决定了整个系统将来的可扩展性和组件事务可替换性。
Dao层(Data Access Object)层,数据持久层 (例如:采购员)
负责和数据库进行交互,提供数据的增删改查操作,不关心具体的业务功能,专注于数据的存储和检索。
采用自顶而下,自低向上的层次关系
Web层 接收来自前端的请求,调用 Service层 的方法来处理业务逻辑。
Service层 根据业务需求调用 Dao层 的方法来操作数据库。
Dao层 执行数据库操作,并将结果返回给 Service层。
Service层 将处理后的结果返回给 Web层,再由 Web层 将最终结果呈现给用户。
Spring框架广泛采用了MVC架构模式,通过注解来明确区分不同的层次,使得代码更加清晰和模块化。以下是Spring中MVC三层架构的具体实现:
注解:@Controller
作用:处理用户的请求,调用服务层进行业务处理,然后选择适当的视图进行响应。
示例:
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/users")
public String listUsers(Model model) {
List users = userService.getAllUsers();
model.addAttribute("users", users);
return "userList"; // 返回视图名称
}
}
注解:@Service
作用:处理业务逻辑,调用数据访问层进行数据操作。
示例:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List getAllUsers() {
return userRepository.findAll();
}
public User getUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
public void saveUser(User user) {
userRepository.save(user);
}
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
注解:@Repository
作用:负责与数据库交互,执行CRUD操作。
示例:
@Repository
public interface UserRepository extends JpaRepository {
// 可以添加自定义的查询方法
List findByUsername(String username);
}
用户请求:用户通过浏览器发送HTTP请求到服务器。
前端控制器:Spring的前端控制器DispatcherServlet
接收到请求。
处理器映射:DispatcherServlet
根据请求URL和配置的映射规则,找到对应的控制器方法。
控制器处理:控制器方法被调用,处理用户的请求。
调用服务层:控制器调用服务层的方法,进行业务逻辑处理。
调用数据访问层:服务层调用数据访问层的方法,进行数据操作。
返回数据:数据访问层返回数据给服务层,服务层处理完业务后返回数据给控制器。
选择视图:控制器选择合适的视图进行渲染,并将数据传递给视图。
视图渲染:视图生成最终的HTML页面。
响应用户:DispatcherServlet
将生成的HTML页面返回给用户。
分离关注点:每个层次都有明确的职责,使得代码更加清晰和模块化。
提高可维护性:各层之间松耦合,便于维护和扩展。
依赖注入:Spring的依赖注入机制使得对象的创建和管理更加方便,减少了硬编码。
Spring框架通过@Controller
、@Service
和@Repository
注解,清晰地划分了MVC三层架构的各个层次,使得开发人员能够更高效地构建和维护复杂的Web应用。
定义:POJO是指普通的Java对象,即没有继承任何特殊类或实现任何特殊接口的Java类。
特点:
纯粹的Java对象,不依赖于任何框架或库。
通常用于表示业务实体或数据模型。
包含属性和相关的getter/setter方法。
示例:
public class User {
private Long id;
private String username;
private String email;
// Getter 和 Setter 方法
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
定义:DAO是指数据访问对象,用于封装对数据库的操作。
特点:
提供一个抽象的接口,隐藏了具体的数据库访问细节。
通常包含CRUD(创建、读取、更新、删除)操作方法。
可以使用JDBC、ORM框架(如Hibernate、MyBatis)等技术实现。
示例:
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public List findAll() {
String sql = "SELECT * FROM users";
return jdbcTemplate.query(sql, new UserRowMapper());
}
@Override
public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new UserRowMapper());
}
@Override
public void save(User user) {
String sql = "INSERT INTO users (username, email) VALUES (?, ?)";
jdbcTemplate.update(sql, user.getUsername(), user.getEmail());
}
@Override
public void update(User user) {
String sql = "UPDATE users SET username = ?, email = ? WHERE id = ?";
jdbcTemplate.update(sql, user.getUsername(), user.getEmail(), user.getId());
}
@Override
public void delete(Long id) {
String sql = "DELETE FROM users WHERE id = ?";
jdbcTemplate.update(sql, id);
}
private static class UserRowMapper implements RowMapper {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getLong("id"));
user.setUsername(rs.getString("username"));
user.setEmail(rs.getString("email"));
return user;
}
}
}
POJO类:表示业务实体,通常用于数据传输和存储。
DAO类:负责对POJO类进行数据库操作,提供数据访问的接口。
假设有一个简单的用户管理系统,其中包含用户实体(User)和用户数据访问对象(UserDao):
public class User {
private Long id;
private String username;
private String email;
// Getter 和 Setter 方法
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public List findAll() {
String sql = "SELECT * FROM users";
return jdbcTemplate.query(sql, new UserRowMapper());
}
@Override
public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new UserRowMapper());
}
@Override
public void save(User user) {
String sql = "INSERT INTO users (username, email) VALUES (?, ?)";
jdbcTemplate.update(sql, user.getUsername(), user.getEmail());
}
@Override
public void update(User user) {
String sql = "UPDATE users SET username = ?, email = ? WHERE id = ?";
jdbcTemplate.update(sql, user.getUsername(), user.getEmail(), user.getId());
}
@Override
public void delete(Long id) {
String sql = "DELETE FROM users WHERE id = ?";
jdbcTemplate.update(sql, id);
}
private static class UserRowMapper implements RowMapper {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getLong("id"));
user.setUsername(rs.getString("username"));
user.setEmail(rs.getString("email"));
return user;
}
}
}
POJO类:用于表示业务实体,通常包含属性和相关的getter/setter方法。
DAO类:用于封装对数据库的操作,提供数据访问的接口。
两者结合:POJO类表示数据,DAO类负责数据的持久化操作,共同实现业务逻辑。