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三层架构(随笔记)