自我解读MVC三层架构原理

MVC简单原理

(1)在我们最开始学习编程,开始写代码的时候;往往写的代码较为的混乱,层次不清晰,从而造成了维护安全上的缺陷。这里就慢慢引出了框架的知识。能够是我们的代码变得层次清晰、分明,维护起来简单,使用安全。

(2)比较老的架构,适合新人学习的家口,便是我们的MVC三层架构。

(3)MVC(Model、View、Controller),

  • Model层:的包括范围比较广,包括了pojo(实体类层)和业务的处理层持久层(操作数据层);
  • View层:包括了类似于项目中的Jsp、Html页面进行数据展示层;
  • Controller层:接收用户的请求,交给业务层处理对应的代码,控制视图的跳转;

 例子解读:(登录校验例子)

 (1)前台页面(常见系统中的登录页面  用户名,密码的输入,并校验)

<%@ page contentType="text/html;charset=UTF-8" pageEncoding="GBK" language="java" %>
<html>
<head>
    <title>超市订单系统</title>
    <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css">
</head>
<body class="login_bg">
<%--在body里面划分section(部分)--%>
<section class="loginBox">
    <%--头部标签--%>
    <header class="loginHeader">
        <h1>超市订单管理系统</h1>
    </header>
        <section class="loginCont">
            <%--form表单--%>
            <form class="loginForm" action="${pageContext.request.contextPath}/login.do"  name="actionForm" id="actionForm"  method="post" >
                <%--登录状态盒子--%>
                <div class="info">${error}</div>
                <%--输入用户名盒子--%>
                <div class="inputbox">
                    <label for="userCode">用户名:</label>
                    <input type="text" class="input-text" id="userCode" name="userCode" placeholder="请输入用户名" required/>
                </div>
                <%--输入密码盒子--%>
                <div class="inputbox">
                    <label for="userPassword">密码:</label>
                    <input type="password" id="userPassword" name="userPassword" placeholder="请输入密码" required/>
                </div>
                <%--登录重置盒子--%>
                <div class="subBtn">
                    <input type="submit" value="登录"/>
                    <input type="reset" value="重置"/>
                </div>
            </form>
        </section>
</section>

</body>
</html>

(2)控制层

当前台页面输入用户名和密码后,这时控制层开始工作,将获取过来的用户名和密码交个Servlet进行校验,校验就是Model层中的业务处理层和持久层进行工作了;

这里需要说明一下,控制层提交登录数据的具体过程:首先当我们按校验规则输入用户名和密码之后,点击提交按钮,通过form表单中的action中的路径,到了web.xml中,在web.xml中找到对应的过滤器,通过过滤器,执行对应的Servlet,在Servlet拿到输入的数据,并在数据库中进行查找,进行比对;

代码如下:

(1)首先是对应的web.xml中的login.do过滤器

<!--注册登陆请求的Servlet-->
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>servlet.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login.do</url-pattern>
    </servlet-mapping>

(2)到了对应的Servlet类:LoginServlet.class

/**
 * @author ZEShart
 * @create 2021-07-29-21:31
 */
/**
 * 处理登录的请求
 * 控制层去调业务层的代码
* */
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /**
         * 获取用户名和密码
         * */
        String userCode=req.getParameter("userCode");
        String userPassword=req.getParameter("userPassword");

        //resp.getWriter().println(userCode+"------------"+userPassword);

        //和数据库中的密码进对比,调用业务层
        UserService userService=new UserServiceImpl();


        //这里已经把登录的人给查出来了
        User user=userService.userLogin(userCode,userPassword);


        if (user!=null){//表示查有此人
            //将用户的信息放到Session中
            req.getSession().setAttribute(Constants.USER_SESSION,user);
            //重定向到主页
            resp.sendRedirect("jsp/frame.jsp");
        }else{//表示查无此人
            //转发回登录页面,并提示用户名或密码错误
            req.setAttribute("error","用户名或密码错误");
            req.getRequestDispatcher("login.jsp").forward(req, resp);
        }
    }
}

(3)在Servlet中获取数据并校验

在获取完数据之后,在校验时,Model层中业务处理层与持久层开始工作:

Dao层(数据持久层)

操作数据库的方法封装:BaseDao.class

/**
 * @author ZEShart
 * @create 2021-07-17-16:36
 */
/*
* 操作数据库的公共类
* 读取数据库配置文件,获取数据库基本信息
* */
public class BaseDao {
    private static String user;
    private static String password;
    private static String url;
    private static String driver;
    /*
    * 静态代码块,类加载的时候就初始化了
    * */
    static{
        Properties properties=new Properties();
        /*
        * 通过类加载器读取对应的资源,把一个资源变成流
        * */
        InputStream is=BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
        try {
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        user=properties.getProperty("user");
        password=properties.getProperty("password");
        url=properties.getProperty("url");
        driver=properties.getProperty("driver");
    }

    /**
    * 获取数据库连接
    * */
    public static Connection getConnection(){
        Connection connection=null;
        try {
            Class.forName(driver);
            connection=DriverManager.getConnection(url,user,password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }
    /*
    * 编写公共查询类
    * */
    public static ResultSet execute(Connection connection, PreparedStatement pstm,ResultSet resultSet, String sql,Object[] params){
        //通过上面的连接数据库方法,连接数据库后得到statement对象
        try {
            //预编译的sql,在后面直接执行就可以了
            pstm=connection.prepareStatement(sql);
            //执行sql语句
            for (int i = 0; i < params.length; i++) {
                //setObject,占位符从1开始,但我们的数组是从0开始
                pstm.setObject(i+1,params[i]);
            }
            resultSet=pstm.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return  resultSet;
    }
    /*
    * 编写公共增删改公共类
    * */
    public static Integer execute(Connection connection, String sql,Object[] params, PreparedStatement pstm){
        //通过上面的连接数据库方法,连接数据库后得到statement对象
        int rows=0;
        try {
            pstm=connection.prepareStatement(sql);
            //执行sql语句
            for (int i = 0; i < params.length; i++) {
                //setObject,占位符从1开始,但我们的数组是从0开始
                pstm.setObject(i+1,params[i]);
            }
            rows=pstm.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  rows;
    }
    /*
    * 关闭资源
    * */
    public static boolean closeResource(Connection connection,PreparedStatement pstm,ResultSet resultSet){
        boolean flag=true;
        if (connection!=null){
            try {
                connection.close();
                //GC回收
                connection=null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag=false;
            }
        }
        if (pstm!=null){
            try {
                pstm.close();
                //GC回收
                pstm=null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag=false;
            }
        }
        if (resultSet!=null){
            try {
                resultSet.close();
                //GC回收
                connection=null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag=false;
            }
        }
        return flag;
    }
}

Dao层中的接口(规定使用到的方法)

/**
* 接口就是一个规范
* */
public interface UserDao {
    //得到登录的用户,(通过用户名)
    public User getLoginUser(Connection connection, String userCode) throws SQLException;
}

实现接口中的方法:

public class UserDaoImpl implements UserDao {

    public User getLoginUser(Connection conn, String userCode) throws SQLException {
        PreparedStatement pstm=null;
        ResultSet rs=null;
        User user=null;
        /**
         * 调用BaseDao类里面的公共查询方法
        * */
        if(conn!=null){
            String sql="select * from smbms_user where userCode=?";
            Object[] params={userCode};
                rs=BaseDao.execute(conn,pstm,rs,sql,params);
                if (rs.next()){
                    user=new User();
                    user.setId(rs.getInt("id"));
                    user.setUserCode(rs.getString("userCode"));
                    user.setUserName(rs.getString("userName"));
                    user.setUserPassword(rs.getString("userPassword"));
                    user.setUserSex(rs.getInt("userSex"));
                    user.setUserBirth(rs.getDate("userBirth"));
                    user.setUserPhone(rs.getString("userPhone"));
                    user.setUserAddress(rs.getString("userAddress"));
                    user.setUserRole(rs.getInt("userRole"));
                    user.setCreateBy(rs.getInt("createBy"));
                    user.setCreateDate(rs.getTimestamp("createDate"));
                    user.setModifyBy(rs.getInt("modifyBy"));
                    user.setModifyDate(rs.getTimestamp("modifyDate"));
                }
                /**
                 * 遍历完成之后,要进行资源的关闭,这里我们一般不关闭connection,因为里面还有业务
                * */
                BaseDao.closeResource(null,pstm,rs);
        }
        return user;
    }
}

(4)为了项目的安全性

一般我们不直接通过前端直接连接dao层,让dao层来处理前端的数据,这样会造成系统的不安全,所以我们在前端和dao层之间家里了一层Service层。

service层接口:

/**
 * 业务层
* */
public interface UserService {

    /**
     * 作者:李东升
     * 功能:用户登录
    * */
    public User userLogin(String userCode, String password);

}

实现service接口:

**
 * @author ZEShart
 * @create 2021-07-29-21:00
 */
public class UserServiceImpl implements UserService {
    /**
     * 业务层都会调用dao层,所以我们要引入Dao层
     * 在学习微服务的时候,我们可以直接通过注解实现引入,这里得通过构造方法引入
    * */
    private UserDao userDao;
    public UserServiceImpl(){
        userDao= new UserDaoImpl();
    }
    public User userLogin(String userCode, String password) {
        Connection connection;
        User user=null;
        connection= BaseDao.getConnection();
        //通过业务层调用对应的具体的数据库操作
        try {
            user=userDao.getLoginUser(connection,userCode);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            BaseDao.closeResource(connection,null,null);
        }
        return user;
    }
}

综上,就是我自己简单理解的MVC三层架构(随笔记)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在刚刚步入“多层结构”Web应用程序开发的时候,我阅读过几篇关于“asp.net三层结构开发”的文章。但其多半都是对PetShop3.0和Duwamish7的局部剖析或者是学习笔记。对“三层结构”通体分析的学术文章几乎没有。 2005年2月11日,Bincess BBS彬月论坛开始试运行。不久之后,我写了一篇题目为《浅谈“三层结构”原理与用意》的文章。旧版文章以彬月论坛程序中的部分代码举例,通过全局视角阐述了什么是“三层结构”的开发模式?为什么要这样做?怎样做?……而在这篇文章的新作中,配合这篇文章我写了7个程序实例(TraceLWord1~TraceLWord7留言板)以帮助读者理解“三层结构”应用程序。这些程序示例可以在随带的CodePackage目录中找到——   对于那些有丰富经验的Web应用程序开发人员,他们认为文章写的通俗易懂,很值得一读。可是对于asp.net初学者,特别是没有任何开发经验的人,文章阅读起来就感到非常困难,不知文章所云。甚至有些读者对“三层结构”的认识更模糊了……   关于“多层结构”开发模式,存在这样一种争议:一部分学者认为“多层结构”与“面向对象的程序设计思想”有着非常紧密的联系。而另外一部分学者却认为二者之间并无直接联系。写作这篇文章并不是要终结这种争议,其行文目的是希望读者能够明白:在使用asp.net进行Web应用程序开发时,实现“多层结构”开发模式的方法、原理及用意。要顺利的阅读这篇文章,希望读者能对“面向对象的程序设计思想”有一定深度的认识,最好能懂一些“设计模式”的知识。如果你并不了解前面这些,那么这篇文章可能并不适合你现在阅读。不过,无论这篇文章面对的读者是谁,我都会尽量将文章写好。我希望这篇文章能成为学习“三层结构”设计思想的经典文章!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值