MVC和三层架构在JavaWeb中的应用实例-CURD

MVC和三层架构在JavaWeb中的应用实例-CURD

一、MVC模式

MVC设计模式提供了一种按功能对软件进行模块划分的方法。该模式将软件程序分为三个核心模块:模型(Model)、视图(View)和控制器(Controller)。

**模型(Model)**负责管理应用程序的业务数据、定义访问控制以及修改这些数据的业务规则。

**视图(View)**负责与用户进行交互,它从模型中获取数据向用户展示,同时也能将用户请求传递给控制器进行处理。

**控制器(Controller)**负责应用程序中处理用户交互的部分,它从视图中读取数据,控制用户输入,并向模型发送数据。
在这里插入图片描述

控制器(serlvlet)用来接收浏览器发送过来的请求,控制器调用模型(Model)来获取数据,比如从数据库查询数据;控制器获取到数据后再交由视图(JSP)进行数据展示。
在这里插入图片描述

二、三层架构

三层架构是将我们的项目按照业务逻辑分成了三个层面,分别是业务逻辑层、表现层、数据访问层。三层又分别对应着SSM框架中的Spring、SpringMVC、Mybatis。

数据访问层-dao:完成数据库的访问,对数据库进行CURD操作。

**业务逻辑层-service:**对业务逻辑进行封装,调用数据访问层中基本功能,形成复杂的业务逻辑功能。以用户注册为例,当要注册新用户时,首先会调用数据访问层的selectByName()方法查看用户是否存在,如果不存在再调用数据访问层的insert()方法进行注册(即将用户数据添加到数据库中)。

**表现层-controller:**与用户进行交互,接受用户发起的请求,封装业务实体,调用业务逻辑,响应页面给用户。

在这里插入图片描述

三、三层架构与MVC的关系

三层架构主要是为了符合“高内聚,低耦合”思想,把各个功能模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层。各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体。这种划分使得开发人员分工更明确,能够更专注于应用系统核心业务逻辑的分析、设计和开发,从而提高开发效率,有利于项目的更新和维护工作。

MVC模式,即模型(Model)、视图(View)和控制器(Controller),是一个广泛流行的软件设计模式。它的主要目的是实现Web系统的职能分工。Model层实现系统中的业务逻辑,View层负责将信息以图形用户界面的形式呈现给用户,而Controller层则负责确保Model和View的同步,处理用户输入并调用Model和View完成用户的需求。
在这里插入图片描述

三层架构主要是基于业务来分的,它关注于整个应用体系的层次结构,强调高内聚和低耦合,以提高开发效率和可维护性。

MVC模式则更多地关注于表现层,即如何更好地组织和展示用户界面和用户的交互,它并不直接涉及业务逻辑或数据访问,而是关注于如何将这两者有效地结合起来,提供一个良好的用户体验。

四、增删查改案例

需求:完成用户数据的增删改查。

1.项目搭建

在实际项目的开发中,用户信息是存放在数据库中的,管理员对用户信息进行管理的过程,无时无刻不涉及到增删改查操作。

  1. 创建一个javaWeb项目,添加响应的servlet,mysql、jstl的jar包。
<!--servlet-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>
<!--mysql-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>
<!--jstl-->
<dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
  1. 创建一个包domain,在包中新建一个用户实体类User类来映射数据表中的用户的属性;

  2. 创建一个包utils,在包中新建JDBCUtils工具类用于封装数据库的连接信息;

  3. 创建一个包dao,在包中新建UserDao类,在该类中编写对数据库进行增删改查的方法。

  4. 创建一个包service,在包中新建UserService类,在该类中编写对数据进行增删改查的业务方法。

  5. 创建一个包controller,在包中新建AddServlet,用于接收用户请求和调用service业务逻辑方法,实现数据控制和中转。
    在这里插入图片描述

2.实现原理
2.1添加数据

当用户点击useList.jsp页面的新增按钮时,会跳转到addUser.jsp页面。用户输入用户信息点击提交,浏览器就会发送一个请求到AddServlet,该请求会携带表单数据,在AddServlet中使用request.getParameter(“”)方法接受到表达数据,然后封装为用户对象,调用service层的添加方法,service层又调用dao层添加数据的方法,最后将数据存入数据库中。
在这里插入图片描述

2.2查询数据

在这里插入图片描述

2.3修改数据-数据回显

在这里插入图片描述

2.4修改数据-修改

修改数据和添加数据复用一个Servlet,在接收数据时判断用户id是否存在,如果存在就表示该请求时修改,就调用修改的方法;如果不存在就是添加数据,就调用添加添加束的方法。

在这里插入图片描述

3.实现步骤-后台
3.1准备数据
-- 创建用户表
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user`  (
  `user_id` int(0) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `user_name` varchar(40) NOT NULL COMMENT '用户名',
  `user_cardNo` varchar(18)  NOT NULL COMMENT '身份证号',
  `user_gender` int(0) NULL COMMENT '性别',
  `user_birthday` date NULL DEFAULT NULL COMMENT '出生日期',
  `user_phone` varchar(11)  NOT NULL COMMENT '联系电话',
  `user_pwd` varchar(30) NOT NULL COMMENT '密码',
  PRIMARY KEY (`user_id`) ,
);
-- 添加数据
INSERT INTO `tb_user` VALUES (1, '肖遥', '5303000123', 1, '2024-03-27', '1383636437', '123');
INSERT INTO `tb_user` VALUES (2, '美杜莎', '5303000456', 0, '2024-03-20', '1383535468', '321');
INSERT INTO `tb_user` VALUES (3, '小医仙', '540400123', 0, '2024-03-13', '1388345670', '123');
INSERT INTO `tb_user` VALUES (4, '张三', '1233333', 1, '1970-01-01', '133333', '123');
3.2添加业务实体
public class User {
    private Integer userId;
    private String userName;
    private String userPwd;
    private String userPhone;
    private String userCardNo;
    private int userGender;
    private Date userBirthday;
    //省略getter、setter
}
3.3JDBCUtils
package com.kdf.utils;
import java.sql.*;
public class JDBCUtils {
    private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
    private static final String URL = "jdbc:mysql://localhost:3306/kdftest";
    private static final String NAME = "root";
    private static final String PASSWORD = "root";
    static {
        try {
            //加载驱动
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //获取连接
    public static Connection getCon(){
        Connection connection = null;
        try {
             connection = DriverManager.getConnection(URL, NAME, PASSWORD);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
    //释放资源
    public static void close(Connection con, PreparedStatement pst, ResultSet rs){
        try {
            if (con!=null){
                con.close();
            }
            if(pst!=null){
                pst.close();
            }
            if(rs!=null){
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

3.4编写dao层接口
public interface UserDao {
    //添加
    public int addUser(User user);
    //删除
    public int  delUser(int userId);
    //修改
    public int updateUser(User user);
    //查询
    public List<User> queryAll();
    //根据id查询
    public User queryById(int userId);
}
3.5编写service层接口
public interface UserService {
    //添加
    public boolean addUser(User user);
    //删除
    public boolean  delUser(int userId);
    //修改
    public boolean updateUser(User user);
    //查询
    public List<User> queryAll();
    //根据id查询
    public User queryById(int userId);
}
3.6实现dao层接口
package com.kdf.dao.impl;

import com.kdf.dao.UserDao;
import com.kdf.domain.User;
import com.kdf.utils.DateUtils;
import com.kdf.utils.JDBCUtils;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
//dao层实现类--访问数据库
public class UserDaoImpl implements UserDao {
    //定义连接对象
    private Connection con = null;
    //定义结果集
    private ResultSet rs = null;
    //定义预编译对象
    private PreparedStatement pst = null;
    /**
     *
     * @param user 传入user对象
     * @return 返回受影响的行,大于0表示添加成功
     */
    @Override
    public int addUser(User user) {
        int row = 0;
        //获取数据库连接
        con = JDBCUtils.getCon();
        //编写sql语句,主键自增长可以使用null填充,其余数据使用占位符填充
        String sql = "insert into tb_user values(null,?,?,?,?,?,?)";
        //预编译sql语句
        try {
            pst = con.prepareStatement(sql);
            //给占位符赋值
            pst.setString(1,user.getUserName());
            pst.setString(2,user.getUserCardNo());
            pst.setInt(3,user.getUserGender());
            //数据类型转换
            Date sqlDate = DateUtils.util2Sql(user.getUserBirthday());
            pst.setDate(4,sqlDate);
            pst.setString(5,user.getUserPhone());
            pst.setString(6,user.getUserPwd());
            //执行更新操作,返回受影响的行
            row = pst.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //释放资源
            JDBCUtils.close(con,pst,null);
        }
        //返回受影响的行
        return row;
    }

    @Override
    public int delUser(int userId) {
        int row = 0;
        //获取数据库连接
        con = JDBCUtils.getCon();
        //编写sql语句,主键自增长可以使用null填充,其余数据使用占位符填充
        String sql = "delete from tb_user where user_id = ?";
        //预编译sql语句
        try {
            pst = con.prepareStatement(sql);
            //给占位符赋值
            pst.setInt(1,userId);
            //执行更新操作,返回受影响的行
            row = pst.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //释放资源
            JDBCUtils.close(con,pst,null);
        }
        //返回受影响的行
        return row;
    }

    @Override
    public int updateUser(User user) {
        int row = 0;
        //获取数据库连接
        con = JDBCUtils.getCon();
        //编写sql语句,主键自增长可以使用null填充,其余数据使用占位符填充
        String sql = "update tb_user set user_name=?,user_cardno=?,user_gender=?,user_birthday=?,user_phone=? where user_id = ?";
        //预编译sql语句
        try {
            pst = con.prepareStatement(sql);
            //给占位符赋值
            pst.setString(1,user.getUserName());
            pst.setString(2,user.getUserCardNo());
            pst.setInt(3,user.getUserGender());
            //数据类型转换
            Date sqlDate = DateUtils.util2Sql(user.getUserBirthday());
            pst.setDate(4,sqlDate);
            pst.setString(5,user.getUserPhone());
            pst.setInt(6,user.getUserId());
            //执行更新操作,返回受影响的行
            row = pst.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //释放资源
            JDBCUtils.close(con,pst,null);
        }
        //返回受影响的行
        return row;
    }

    @Override
    public List<User> queryAll() {
        List<User> list = new ArrayList<>();
        //获取数据库连接
        con = JDBCUtils.getCon();
        //编写sql语句,主键自增长可以使用null填充,其余数据使用占位符填充
        String sql = "select * from tb_user";
        //预编译sql语句
        try {
            pst = con.prepareStatement(sql);
            //执行查询操作,返回结果集
            ResultSet rs = pst.executeQuery();
            while(rs.next()){
                //将结果集中的记录取出
                int user_id = rs.getInt("user_id");
                String user_name = rs.getString("user_name");
                String user_cardno = rs.getString("user_cardno");
                int user_gender = rs.getInt("user_gender");
                Date user_birthday = rs.getDate("user_birthday");
                String user_phone = rs.getString("user_phone");
                String user_pwd = rs.getString("user_pwd");
                //创建对象
                User user = new User();
                user.setUserId(user_id);
                user.setUserName(user_name);
                user.setUserBirthday(user_birthday);
                user.setUserCardNo(user_cardno);
                user.setUserGender(user_gender);
                user.setUserPwd(user_pwd);
                user.setUserPhone(user_phone);
                //将对象存入集合中
                list.add(user);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //释放资源
            JDBCUtils.close(con,pst,rs);
        }
        //返回集合
        return list;
    }

    @Override
    public User queryById(int userId) {
        //创建对象
        User user = new User();
        //获取数据库连接
        con = JDBCUtils.getCon();
        //编写sql语句,主键自增长可以使用null填充,其余数据使用占位符填充
        String sql = "select * from tb_user where user_id=?";
        //预编译sql语句
        try {
            pst = con.prepareStatement(sql);
            pst.setInt(1,userId);
            //执行查询操作,返回结果集
            ResultSet rs = pst.executeQuery();
            if (rs.next()){
                //将结果集中的记录取出
                int user_id = rs.getInt("user_id");
                String user_name = rs.getString("user_name");
                String user_cardno = rs.getString("user_cardno");
                int user_gender = rs.getInt("user_gender");
                Date user_birthday = rs.getDate("user_birthday");
                String user_phone = rs.getString("user_phone");
                String user_pwd = rs.getString("user_pwd");

                user.setUserId(user_id);
                user.setUserName(user_name);
                user.setUserBirthday(user_birthday);
                user.setUserCardNo(user_cardno);
                user.setUserGender(user_gender);
                user.setUserPwd(user_pwd);
                user.setUserPhone(user_phone);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //释放资源
            JDBCUtils.close(con,pst,rs);
        }
        //返回集合
        return user;
    }
}
3.7实现service接口
package com.kdf.service.impl;

import com.kdf.dao.UserDao;
import com.kdf.dao.impl.UserDaoImpl;
import com.kdf.domain.User;
import com.kdf.service.UserService;

import java.util.List;
//service接口实现类,调用dao层方法
public class UserServiceImpl implements UserService {
    //创建dao层对象 --多态
    private UserDao userDao= new UserDaoImpl();

    @Override
    public boolean addUser(User user) {
        return userDao.addUser(user)>0;
    }

    @Override
    public boolean delUser(int userId) {
        return userDao.delUser(userId)>0;
    }

    @Override
    public boolean updateUser(User user) {
        return userDao.updateUser(user)>0;
    }

    @Override
    public List<User> queryAll() {
        return userDao.queryAll();
    }

    @Override
    public User queryById(int userId) {
        return userDao.queryById(userId);
    }
}

3.8查询所有数据
package com.kdf.controller;

import com.kdf.domain.User;
import com.kdf.service.UserService;
import com.kdf.service.impl.UserServiceImpl;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.List;
//查询所有数据
@WebServlet(name = "FindAllServlet", value = "/findAll")
public class FindAllServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //调用查询所有的方法
        UserService userService = new UserServiceImpl();
        List<User> users = userService.queryAll();
        //将集合存入session会话中
        request.getSession().setAttribute("users",users);
        //重定向到数据展示页面 userList.jsp
        response.sendRedirect("userList.jsp");
    }
}

3.9添加|修改数据

添加和修改数据可以复用同一个servlet,判断用户id是否存在。

package com.kdf.controller;

import com.kdf.domain.User;
import com.kdf.service.UserService;
import com.kdf.service.impl.UserServiceImpl;
import com.kdf.utils.DateUtils;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Date;
//添加和修改数据可使用同一个servlet
@WebServlet(name = "UpdateServlet", value = "/UpdateServlet")
public class UpdateServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.设置字符编码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //2.接收表单数据
        String user_name = request.getParameter("user_name");
        String user_cardno = request.getParameter("user_cardno");
        String user_gender = request.getParameter("user_gender");
        String user_birthday = request.getParameter("user_birthday");
        String user_phone = request.getParameter("user_phone");
        String user_pwd = request.getParameter("user_pwd");
        String user_id = request.getParameter("user_id");
        //3.封装业务实体,传递数据
        User user = new User();
        user.setUserPhone(user_phone);
        user.setUserPwd(user_pwd);
        //将String类型转换为Int类型
        Integer gender = Integer.valueOf(user_gender);
        user.setUserGender(gender);
        user.setUserCardNo(user_cardno);
        user.setUserName(user_name);
        //将String类型转换为Date类型
        Date date = DateUtils.String2UtilDate(user_birthday);
        user.setUserBirthday(date);

        //调用业务层方法
        UserService us = new UserServiceImpl();
        boolean b = false;
        //如果id不等于null,就表示做的是修改操作,
        if(user_id!=null &&user_id!=""){
            user.setUserId(Integer.valueOf(user_id));
            b = us.updateUser(user);//修改
        }else{
           b =  us.addUser(user);
        }

        if(b){
            //修改成功转发到查询所有数据servlet
            request.getRequestDispatcher("/findAll").forward(request,response);
        }else {
            //添加失败重定向到添加页面
            response.getWriter().append("添加失败");
            response.sendRedirect("addUser.jsp");
        }
    }
}
3.10删除数据
package com.kdf.controller;
import com.kdf.service.impl.UserServiceImpl;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
//删除数据
@WebServlet(name = "DelServlet", value = "/delServlet")
public class DelServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置字符编码
        request.setCharacterEncoding("utf-8");
        //接收页面传递的id
        String id = request.getParameter("id");
        //调用删除方法
        UserServiceImpl userService = new UserServiceImpl();
        boolean b = userService.delUser(Integer.valueOf(id));
        if (b){
            //删除成功调用查询所有的servlet
            request.getRequestDispatcher("/findAll").forward(request,response);
        }
    }
}
3.11修改数据

修改数据时,先通过id查询到需要修改的对象,然后将对象传入修改页面显示,再进行修改,所以先调用findByIdServlet。

修改数据的Servlet参看3.9添加|修改数据

package com.kdf.controller;

import com.kdf.domain.User;
import com.kdf.service.impl.UserServiceImpl;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
//查询单个对象
@WebServlet(name = "FindByIdServlet", value = "/FindByIdServlet")
public class FindByIdServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置字符编码
        request.setCharacterEncoding("utf-8");
        //接收页面传递的id
        String id = request.getParameter("id");
        //调用删除方法
        UserServiceImpl userService = new UserServiceImpl();
        User user = userService.queryById(Integer.valueOf(id));
        //对象存session
        request.getSession().setAttribute("user",user);
        //重定向到修改页面
        response.sendRedirect("updateUser.jsp");
    }
}
4.实现步骤-页面
4.1userList.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>用户信息</title>
</head>
<body>
<input type="button" value="新增" id="add"><br>
<hr>
<table border="1" cellspacing="0" width="80%">
    <tr>
        <th>序号</th>
        <th>姓名</th>
        <th>省份证号</th>
        <th>性别</th>
        <th>生日</th>
        <th>电话</th>
        <th>操作</th>
    </tr>
    <c:forEach items="${users}" var="user" varStatus="status">
    <tr align="center">
        <td>${user.userId}</td>
        <td>${user.userName}</td>
        <td>${user.userCardNo}</td>
        <%--判断性别--%>
        <c:if test="${user.userGender == 1}">
            <td>男</td>
        </c:if>
        <c:if test="${user.userGender == 0}">
            <td>女</td>
        </c:if>
        <td>${user.userPhone}</td>
        <td><fmt:formatDate value="${user.userBirthday}"/></td>

        <td><a href="delServlet?id=${user.userId}">删除</a>
            <a href="FindByIdServlet?id=${user.userId}">修改</a>
        </td>
 </tr>
 </c:forEach>
</table>
<script>
	//点击添加按钮,跳转到addUser.jsp页面
    document.getElementById("add").οnclick=function (){
            location.href="addUser.jsp";
            }
            </script>

</body>
</html>
4.2addUser.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加用户</title>
</head>
<body>
<h3>添加用户</h3>
<form action="UpdateServlet" method="post">
    用户姓名:<input name="user_name" id="username"><br>
    用户密码:<input type="password" name="user_pwd"><br>
    身份证号:<input name="user_cardno"><br>
    用户性别:
    <input type="radio" name="user_gender" value="1"> 男
    <input type="radio" name="user_gender" value="0"> 女<br>
    用户生日:<input type="text" name="user_birthday"><br>
    用户电话:<input type="text" name="user_phone"><br>
    <input type="submit" value="提交">
</form>

</body>
</html>
4.3updateUser.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>修改用户</title>
</head>
<body>
<h3>修改用户</h3>
<form action="UpdateServlet" method="post">

    <%--隐藏域,提交id--%>
    <input type="hidden" name="user_id" value="${user.userId}">
    用户姓名:<input name="user_name" value="${user.userName}"><br>
    用户密码:<input type="hidden" name="user_pwd"value="${user.userPwd}">
    身份证号:<input name="user_cardno" value="${user.userCardNo}"><br>
    用户性别:
        <c:if test="${user.userGender==1}">
            <input type="radio" name="user_gender" value="1" checked> 男<br>
            <input type="radio" name="user_gender" value="0" > 女<br>
        </c:if>
        <c:if test="${user.userGender==0}">
            <input type="radio" name="user_gender" value="1" > 男<br>
            <input type="radio" name="user_gender" value="0" checked> 女<br>
        </c:if>

    用户生日:<input type="text" name="user_birthday" value="${user.userBirthday}">
    用户电话:<input type="text" name="user_phone" value="${user.userPhone}">
    <input type="submit" value="提交">
</form>
</body>
</html>

两岸猿声啼不住,轻舟已过万重山!

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值