一.架构选型
1.VM架构
VM架构通常指的是虚拟机(Virtual Machine)的架构。虚拟机是一种软件实现的计算机系统,它模拟了物理计算机的功能,允许在单一物理硬件上运行多个操作系统实例。虚拟机架构主要包括以下几个关键组件:
- 虚拟机监控器(Hypervisor):
类型1 Hypervisor:直接运行在物理硬件上,也称为裸机Hypervisor。例如,VMware ESXi、Microsoft Hyper-V、Xen。
类型2 Hypervisor:运行在宿主操作系统之上,例如VMware Workstation、Oracle VirtualBox。
- 虚拟机(VM):
- 每个虚拟机都包含一个完整的操作系统和应用程序,它们与物理硬件隔离,运行在虚拟化环境中。
- 虚拟硬件:
- 虚拟机通过虚拟硬件与物理硬件交互,包括虚拟CPU、虚拟内存、虚拟磁盘和虚拟网络接口等。
- 管理工具:
- 用于创建、配置、管理和监控虚拟机的工具,例如VMware vCenter、Microsoft System Center Virtual Machine Manager。
- 存储和网络虚拟化:
- 虚拟化技术还扩展到存储和网络资源,允许更灵活和高效地管理这些资源。
虚拟机架构的主要优势包括:
资源利用率:通过在一台物理服务器上运行多个虚拟机,可以更高效地利用硬件资源。
隔离性:每个虚拟机都是独立的,一个虚拟机的故障不会影响其他虚拟机。
灵活性:虚拟机可以轻松地迁移、复制和备份。
成本效益:减少了对物理硬件的需求,降低了硬件和维护成本。
虚拟机架构广泛应用于数据中心、云计算、开发和测试环境等场景。
2.MVC架构
MVC架构(Model-View-Controller)是一种广泛应用于软件工程中的设计模式,特别是在构建用户界面时。它将应用程序分为三个主要部分,以提高代码的组织性和可维护性。以下是MVC架构的详细介绍:
- Model(模型):
职责:负责管理应用程序的核心数据和业务逻辑。它直接与数据库或其他数据源交互,处理数据的获取、存储和更新。
特点:独立于用户界面,不直接与用户交互。
- View(视图):
职责:负责显示数据(模型)给用户,并接收用户的输入。视图通常是从模型获取数据的用户界面元素。
特点:不包含业务逻辑,只负责数据的展示和用户交互的呈现。
- Controller(控制器):
职责:作为模型和视图之间的中介,处理用户的输入并更新模型。控制器接收来自视图的用户操作,根据需要更新模型,并可能要求视图更新以反映模型的变化。
特点:包含应用程序的逻辑,决定如何处理用户输入和更新视图。
MVC架构的主要优势包括:
分离关注点:通过将应用程序的不同方面分离,使得代码更易于管理和维护。
可复用性:模型和控制器可以在不同的视图中复用,减少了代码重复。
并行开发:不同的开发者可以同时工作在模型、视图和控制器上,提高了开发效率。
易于测试:分离的组件使得单元测试和集成测试更加容易。
MVC架构广泛应用于Web开发框架中,如Ruby on Rails、ASP.NET MVC、Spring MVC等。它帮助开发者构建结构清晰、易于扩展和维护的应用程序。
![](https://i-blog.csdnimg.cn/direct/0bd433d9020747a08a322edaeb7cc2e5.png)
3.MVVC架构
MVVC架构(Model-View-ViewModel)是一种软件设计模式,它是MVC(Model-View-Controller)架构的一个变体,主要用于简化用户界面的开发,特别是在实现数据绑定和命令绑定的场景中。MVVC架构在WPF(Windows Presentation Foundation)、Silverlight以及一些现代Web框架如Knockout.js和Vue.js中得到了广泛应用。
MVVC架构的组成部分包括:
- Model(模型):
职责:代表应用程序的核心数据和业务逻辑。它通常包含数据访问层和业务规则,与MVC中的Model类似。
特点:独立于用户界面,不直接与用户交互。
- View(视图):
职责:定义应用程序的用户界面。它负责展示数据(来自ViewModel)给用户,并接收用户的输入。
特点:不包含业务逻辑,只负责数据的展示和用户交互的呈现。
- ViewModel(视图模型):
职责:作为视图和模型之间的桥梁,提供视图所需的数据和命令。ViewModel通常包含视图的状态和行为逻辑,它将模型的数据转换为视图可以轻松使用的形式。
特点:包含视图的逻辑,但不直接引用视图,实现了视图和模型的解耦。
MVVC架构的关键特性是数据绑定,它允许视图和ViewModel之间的自动同步。当ViewModel中的数据发生变化时,视图会自动更新,反之亦然。这种双向数据绑定机制减少了手动更新UI的代码量,提高了开发效率。
MVVC架构的主要优势包括:
分离关注点:清晰地分离了视图、视图逻辑和业务逻辑,使得代码更易于管理和维护。
可测试性:ViewModel不依赖于视图,使得单元测试更加容易。
可复用性:ViewModel可以在不同的视图中复用,减少了代码重复。
简化开发:数据绑定和命令绑定减少了样板代码,加快了开发速度。
MVVC架构特别适合于需要复杂用户交互和数据展示的应用程序,它通过提供一种结构化的方式来组织代码,帮助开发者构建响应迅速、易于维护的应用程序。
![](https://i-blog.csdnimg.cn/direct/7a24657abeb84c8cb357651395bb81d5.png)
二.项目架构
将分层思想转换为Java包
![](https://i-blog.csdnimg.cn/direct/dd3d447e5368413aab8043bddb4cfd4b.png)
1.创建项目
![](https://i-blog.csdnimg.cn/direct/113baf65a7e04032a18e1d6156af29ea.png)
![](https://i-blog.csdnimg.cn/direct/249f706f7e374b8089e31a5a305ca240.png)
![](https://i-blog.csdnimg.cn/direct/95e562cb35614b66b65f4604b0ce6d1b.png)
![](https://i-blog.csdnimg.cn/direct/0fe1170ce2014e6da5af3caa0f266d3e.png)
2.创建包("项目架构")
2.1 dao(数据操作的抽象:CRUD )
DAO(Data Access Object)是一种设计模式,用于抽象和封装对数据源的访问。它提供了一个接口,用于执行对数据库或其他持久化机制的操作,而不暴露底层数据访问的细节。DAO模式的主要目的是将业务逻辑与数据访问逻辑分离,从而提高代码的可维护性、可复用性和可测试性。
DAO模式通常包括以下几个组件:
- **DAO接口**:
定义了对数据源进行操作的方法,如创建、读取、更新和删除(CRUD)操作。
接口使得可以在不改变业务逻辑的情况下更换数据访问的实现。
- **DAO实现类**:
实现了DAO接口,包含具体的SQL语句或使用ORM(对象关系映射)框架来与数据库交互。
负责处理数据的持久化和检索。
- **数据传输对象(DTO)**:
用于在应用程序的不同层之间传输数据的简单对象。
通常只包含属性和getter/setter方法,不包含业务逻辑。
- **数据源**:
- 可以是关系型数据库、NoSQL数据库、文件系统或其他任何形式的数据存储。
DAO模式的主要优势包括:
**分离关注点**:业务逻辑不需要知道数据是如何持久化的,只需通过DAO接口与数据交互。
**易于维护**:数据访问逻辑集中在一个地方,便于管理和优化。
**提高可复用性**:DAO可以在不同的业务逻辑中复用,减少了代码重复。
**增强可测试性**:可以通过模拟DAO接口来测试业务逻辑,而不需要实际访问数据库。
在实际应用中,DAO模式常常与其他设计模式如服务层模式结合使用,以进一步分离业务逻辑和数据访问逻辑。此外,现代框架如Spring和Hibernate提供了对DAO模式的支持,简化了数据访问层的开发。
2.2 entity
开发Entity的主要目的是在软件系统中对现实世界的对象或概念进行抽象和建模,以便更好地管理和操 作数据。具体目的包括:
数据抽象与封装
抽象现实对象:Entity将现实世界的对象或概念抽象为代码中的数据结构,便于系统处理。
封装数据与行为:Entity封装了对象的属性和行为,确保数据的一致性和完整性。
数据持久化
与数据库映射:Entity通常与数据库表对应,简化数据存储与检索。
ORM支持:通过对象关系映射(ORM),Entity可以直接与数据库交互,减少手动SQL操作。
2.3 service(解决项目中的业务问题)
Service 的核心职责
- **封装业务逻辑**:
Service 层包含应用程序的核心业务逻辑,例如验证、计算、数据处理等。
它确保业务规则的一致性和可维护性。
- **协调数据访问**:
Service 层调用数据访问对象(DAO)或 Repository 来获取或存储数据。
它可以在多个 DAO 或 Entity 之间协调复杂的操作。
- **事务管理**:
Service 层通常负责管理事务(Transaction),确保多个操作在一个事务中执行。
在 Java EE 中,可以使用 `@Transactional` 注解来声明事务边界。
- **解耦表示层和数据访问层**:
- Service 层作为中间层,将表示层(如 Controller)与数据访问层(如 DAO)解耦,使代码更易于维护和测试。
- **提供可重用的服务**:
- Service 层的方法可以被多个表示层组件(如 Web 控制器、REST 端点)调用,实现逻辑的复用。
2.4 controller
数据的传输
前端到后台
后台到前端
2.5 vo
View Object: 视图对象,也需要展示的对象
2.6 dto
DTO(Data Transfer Object,数据传输对象)是一种设计模式,用于在不同层或组件之间传输数据。DTO 的主要目的是封装数据,减少网络调用次数,并简化数据交换的过程。它通常是一个简单的 Java 类,包含属性和对应的 getter/setter 方法,不包含任何业务逻辑。
DTO 的核心特点
- **数据封装**:
DTO 是一个纯粹的数据容器,用于封装一组相关的数据。
它通常只包含字段和访问这些字段的方法(getter/setter)。
- **减少网络调用**:
- 在分布式系统中,DTO 可以一次性传输大量数据,减少多次调用的开销。
- **解耦层与层之间的依赖**:
- DTO 用于在表示层(如前端)、服务层和持久层之间传递数据,避免直接暴露领域模型(Entity)。
- **简化数据格式**:
- DTO 可以根据需要调整数据的结构,例如过滤敏感信息、组合多个字段或转换数据格式。
- **无业务逻辑**:
- DTO 不包含任何业务逻辑,仅用于数据传输。
DTO 的使用场景
- **前后端数据交互**:
- 在 RESTful API 中,DTO 用于封装请求和响应的数据。
- **服务间通信**:
- 在微服务架构中,DTO 用于在不同服务之间传递数据。
- **数据脱敏**:
- DTO 可以隐藏敏感信息(如密码、身份证号),只暴露必要的数据。
- **数据聚合**:
- DTO 可以将多个 Entity 或数据源的数据组合成一个对象,简化数据传输。
2.7 exception
项目的异常处理类
2.8 util
工具类
![](https://i-blog.csdnimg.cn/direct/5f8ddf63e49a4fdfbe026b3249b27fb0.png)
顺序随意(数据库->controller)
三.数据库
![](https://i-blog.csdnimg.cn/direct/d01ea182c964466fba6ef940dd3b1949.png)
![](https://i-blog.csdnimg.cn/direct/738127d4dddd482095082968ae4e4659.png)
四.实体类(entity)
![](https://i-blog.csdnimg.cn/direct/d5ddf5cc086a4759b1de0086429faa5a.png)
lombok:自动生成set/get,toString(),构造器
java
@Data //set/get 无参构造方法
@AllArgsConstructor //全参构造器
@NoArgsConstructor //无参构造器
public class User {
private Integer id;
private String username;
private String password;
}
![](https://i-blog.csdnimg.cn/direct/0e0c3c704ac244198326f6e41f6de4b1.png)
五.数据访问层(Dao)
1.接口
![](https://i-blog.csdnimg.cn/direct/c38a9762c40348279178f53937b96be9.png)
java
/**
* 用户数据访问接口
*/
public interface IUserDao {
/**
* 添加数据
* @param user
*/
void save(User user);
/**
* 根据id删除
* @param id
*/
void deleteId(int id);
/**
* 修改数据
* 对象指定的id
* @param user
*/
void update(User user);
/**
* 返回所有数据
* @return 所有数据的集合
*/
List<User> findAll();
}
2.实现类
![](https://i-blog.csdnimg.cn/direct/dd7c44d9c1d24b2f958f029f07751391.png)
![](https://i-blog.csdnimg.cn/direct/d32ee9c86f204b3b92b9f1b73e4b1628.png)
java
/**
* UserDao的实现类
* @author 武鑫鑫
*/
public class UserDaoImpl implements IUserDao {
@Override
public void save(User user) {
JdbcUtil.connect();
String sql = "INSERT INTO user_tab(user_username,user_password) VALUES(?,?)";
JdbcUtil.preparedStatement(sql,user.getUsername(),user.getPassword());
JdbcUtil.executeUpdate();
JdbcUtil.close();
}
@Override
public void deleteId(int id) {
JdbcUtil.connect();
String sql = "DELETE FROM user_tab WHERE user_id = ?";
JdbcUtil.preparedStatement(sql,id);
JdbcUtil.executeUpdate();
JdbcUtil.close();
}
@Override
public void update(User user) {
JdbcUtil.connect();
String sql = "UPDATE user_tab SET user_password=? WHERE user_username=?";
JdbcUtil.preparedStatement(sql,user.getPassword(),user.getUsername());
JdbcUtil.executeUpdate();
JdbcUtil.close();
}
@Override
public List<User> findAll() {
List<User> list = new ArrayList<>();
JdbcUtil.connect();
String sql = "SELECT * FROM user_tab";
JdbcUtil.preparedStatement(sql);
ResultSet rs = JdbcUtil.executeQuery();
try {
while (rs.next()){
int id = rs.getInt("user_id");
String username = rs.getString("user_username");
String password = rs.getString("user_password");
User user = new User(id,username,password);
list.add(user);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
JdbcUtil.close();
return list;
}
}
六.DTO
模拟一个Result对象:职责将对象搬运到前端
1.Result
java
@Data
public class Result {
private int code;
private String msg;
private Object results;
private Date time;
/**
* 成功返回
* @param results
* @return
*/
public static Result success(Object results){
Result r = new Result();
r.setCode(ResultCode.SUCCESS.getCode());
r.setMsg(ResultCode.SUCCESS.getMsg());
r.setResults(results);
r.setTime(new Date());
return r;
}
/**
* 失败返回
* @return
*/
public static Result failed(){
Result r = new Result();
r.setCode(ResultCode.FAILED.getCode());
r.setMsg(ResultCode.FAILED.getMsg());
r.setTime(new Date());
return r;
}
}
2.ResultCode(枚举类)
java
/**
* 枚举类:[代码."原因"]
* 规范返回结果[代码,代码解析]
*/
@Getter
public enum ResultCode {
SUCCESS(200,"成功"),
FAILED(500,"失败");
private Integer code;
private String msg;
/**
* 构造器
*
* @param code
* @param msg
*/
private ResultCode(Integer code,String msg){
this.code = code;
this.msg = msg;
}
}
七.JdbcUtil
JDBC的简单封装工具类
1.引入依赖
html
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
2.jdbc五部曲
2.1 注册驱动
java
//只运行一次
static {
registry();
}
/**
* 1.注册驱动
*/
private static void registry(){
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
2.2 建立连接
java
/**
* 2.建立连接
*/
public static void connect(){
try {
conn = DriverManager.getConnection(URL,USERNAME,PASSWORD);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
2.3 预处理
执行SQL语句
java
/**
* 3.预处理SQL
* @param sql
* @param values
*/
public static void preparedStatement(String sql,Object... values){
try {
pst = conn.prepareStatement(sql);
for (int i=0;i<values.length;i++){
pst.setObject(i+1,values[i]);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
2.4 执行SQL
(1)执行增删改操作
java
/**
* 4.1执行增删改
*/
public static void executeUpdate(){
try {
pst.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
(2)执行查询操作
java
/**
* 4.2执行查询
* @return
*/
public static ResultSet executeQuery(){
try {
rs = pst.executeQuery();
} catch (SQLException e) {
throw new RuntimeException(e);
}
return rs;
}
2.5 关闭数据库连接
java
/**
* 5.关闭数据库的连接
*/
public static void close(){
try {
if(rs!=null){
rs.close();
}
if(pst!=null){
pst.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
![](https://i-blog.csdnimg.cn/direct/9d2e0f45384f43e8b06dd9c2e466bb25.png)
八.service
业务
![](https://i-blog.csdnimg.cn/direct/5fbcab7a37664733ba81b77575f915b8.png)
java
public interface IUserService {
/**
* 添加用户
* @param user
*/
void add(User user);
void updateUser(User user);
void removeById(int id);
List<User> findAll();
}
java
public class UserServiceImpl implements IUserService {
private IUserDao userDao;
public UserServiceImpl() {
this.userDao = new UserDaoImpl();
}
@Override
public void add(User user) {
userDao.save(user);
}
@Override
public void updateUser(User user) {
userDao.update(user);
}
@Override
public void removeById(int id) {
userDao.deleteId(id);
}
@Override
public List<User> findAll() {
return userDao.findAll();
}
}
九.单元测试
1.引入单元测试框架(JUnit)
html
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
2.测试用例
![](https://i-blog.csdnimg.cn/direct/a8f3e3fb1ea44b47909c5a434312f1c6.png)
![](https://i-blog.csdnimg.cn/direct/22a61e29f18646b2b795ab2cba386e19.png)
![](https://i-blog.csdnimg.cn/direct/b5c9fe1ef68a47e0a1c3697c263ac408.png)
java
public class UserServiceImplTest {
private IUserService ius;
@Before
public void init(){
ius = new UserServiceImpl();
}
@Test
public void add() {
User user = new User();
user.setUsername("wjx");
user.setPassword("888");
ius.add(user);
}
@Test
public void updateUser() {
User user = new User();
user.setUsername("wjx");
user.setPassword("666");
ius.updateUser(user);
}
@Test
public void removeById() {
ius.removeById(1);
}
@Test
public void findAll(){
List<User> all = ius.findAll();
Assert.assertEquals(1,all.size());
}
}