【Java开发中的MVC模式(初学者)】

一、需求:

利用html+java+mysql等技术手段,写一个demo,功能如下:根据准考号查找学生相关信息。
在查询页面中输入学生的考试号,及时查询到学生的姓名、班级、课程、成绩等信息。(该文主要讲述MVC模式,所以默认数据库只有一门课程一个成绩,利用第一范式构建数据库)

二、分析:

  1. 利用html+CSS来构建展示页面作为视图,包括:查询、查询结果页面等页面;
  2. 利用mysql构建数据库,学生(准考证号,姓名,班级,课程名,成绩);
  3. 利用java写主要了逻辑控制。
    因而,大家想必知道了,这其实就是一个javaWeb项目。

谈及JavaWeb项目,就不得不提到运用最为广泛的一种开发模式——MVC开发模式,今天我就给大家简单地整理一下。
在这里插入图片描述

2.1 MVC开发模式优点

1.提高JavaWeb开发的代码复用性,避免了重复性开发。
2.有效帮助开发人员实现业务开发中的事务管理。

2.2 MVC开发角色组成

2.2.1 V:View,视图层:将处理结果写入到相应包 JSP

(视图层)负责前台jsp页面的表示。此层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示

2.2.2 C:Controller,控制层

(控制层 )控制业务逻辑
Controller层负责具体的业务模块流程的控制,其实就是与前台互交,把前台传进来的参数进行处理,controller层主要调用Service层里面的接口控制具体的业务流程,控制的配置也需要在配置文件中进行。

  • 注:Controler负责请求转发,接受页面过来的参数,传给Service处理,接到返回值,再传给页面。

2.2.3 M:Model,事务模型层,完成业务处理

1.Dao层:主要与数据库进行交互;

2.Service层:调用dao层来完成业务的实现,负责管理所调用的dao层的事务管理。

Conroller层和Service层的区别是:Controlle层负责具体的业务模块流程的控制;Service层负责业务模块的逻辑应用设计

2.2.3.1 Dao层作用

Dao层叫数据访问层,属于一种比较底层,比较基础的操作,主要是做数据持久层的工作,主要与数据库进行交互。具体到对于某个表的增删改查,也就是说某个Dao一定是和数据库的某一张表一一对应的,其中封装了增删改查基本操作,建议Dao只做原子操作,增删改查。

  • 注:一般情况下,Dao层的数据源和数据库连接的参数都是在配置文件中进行配置的。在该项目中为了方便初学者了解整个项目具体流程,在dao文件写死数据库连接方式。
2.2.3.1.1 Dao优点

采用Dao层可以对数据库访问进行封装,避免进行重复性的数据库访问开发操作。同时也降低了维护的成本。

例如:张三给李四转账300元,那么需要进行的操作如下:

1.确认张三这个账户是否是存在的

2.确认李四这个账户是否是存在的

3.查询张三账户余额

4.查询李四账户余额

5.更新张三账户余额

6.更新李四账户余额

在这个例子中,就进行了多次的重复性的数据库访问,例如前两个操作,就是"select count (*) from account where name=?",这样会严重影响到我们的开发效率。

2.2.3.2.Service层的作用

Service层叫服务层,主要负责业务模块的逻辑应用设计。粗略的理解就是对一个或多个Dao进行的再次封装,封装成一个服务,所以这里也就不会是一个原子操作了,需要事物控制。和Dao层一样都是先设计放接口的类,再创建实现的类,然后在配置文件中进行配置其实现的关联。接下来就可以在Service层调用接口进行业务逻辑应用的处理。

  • 注:封装Service层的业务逻辑有利于业务逻辑的独立性和重复利用性。

1.封装的具体业务实现方法,来提高业务复用性

2.负责将参与本次业务实现的Dao层中事务进行管理

探讨Service层是否可有可无? 引用: link
“Service层最大的作用在于规范了代码的开发,实现了业务层与持久层的隔离开发,controller、service、dao每一层都应该有它的边界,来达到解耦的目的,方便代码的复用和扩展 ”

2.2.4 Entity,实体对象

对实体对象(也叫实体类)的众多理解:
A .就是属性类;
B. 一般的实体类对应一个数据表,其中的属性对应数据表中的字段。
好处:
1.对对象实体的封装,体现OO思想。
2.属性可以对字段定义和状态进行判断和过滤
3.把相关信息用一个实体类封装后,我们在程序中可以把实体类作为参数传递,更加方便。
C. 说白了就是为了让程序员在对数据库操作的时候不用写SQL语句
D. 就是一个数据库表生成一个类(这样做对数据库操作起来方便,编写代码较少,提高效率 可以使程序员专注逻辑关系 )
E. 实体类就是把对某一个表的操作全写在一个类中.
F. 在Java开发中经常要定义一些实体类,这些类的定义的好坏会直接影响,编写代码的质量和难易程度,以下是别人总结的一些经验: link
一、实体类的名字尽量和数据库的表的名字对应相同。
二、实体类应该实现java.io.Serializable接口。
三、实体类应该有个无参的构造方法。

三、实现:

3.1 View,视图层

3.1.1 查询入口: welcome.jsp

首先,写一个查询页面,根据准考证号来查询学生相关信息(由于篇幅所限,页面中的css和JavaScript代码省略了,有需要可以在附件中下载)

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>欢迎来到成绩查询系统</title>
</head>

<body>
<div class="myDiv">
    <form action="myQuery" method="post">
       <table class="myTable">
		   <tr class="SCname"><td colspan="2" ><div id="SCname_top"></div></td></tr>
		   <tr class="chaxun"><th colspan="2" >2022年学生成绩查询</th></tr>
		   
       <tr>
	       <td class="myTd myTdLast"> </td>
	       <td class="myTd myTdInp" > <br /> </td>
       </tr>
		   
       <tr class="kaoshenghao">
	       <td class="myTd myTd2"> 考生准考号:</td>
	       <td class="myTd myTd2 myTdInp ">
	       <input placeholder="请输入准考号" class="myTdInp" type="text" name="id" id="content" />
	       &nbsp;<span class="contentcount contentcount3">0</span><span class="contentcount3">/30</span><br />
	        </td>
       </tr>

		   <tr class="chazhao_top">
			   <td colspan="2" class="myTd_find"> 
				   <input type="submit" value="查询" class="button1"/>
			   </td>
		   </tr>
       </table>
       
        
    </form>
</div>
</body>
</html>

3.1.2 查询结果页面显示 result.jsp

写一个结果显示页面,根据准考证号查询,查询到的学生所有信息均在一个页面中显示(由于篇幅所限,页面中的css和JavaScript代码省略了,有需要可以在附件中下载)

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>成绩</title>
</head>
<body>


    
<div class="myDiv">
    <form action=welcome.jsp method="post">
       <table class="myTable">
		   <tr class="SCname"><td colspan="2" ><div id="SCname_top"></div></td></tr>
		   <tr class="chaxun"><th colspan="2" >2022年学生成绩查询</th></tr>
       <tr class="kaoshenghao">
	       <td class="myTd myTd2"> 考生准考号:</td>
	       <td class="myTd myTd2 myTdInp "><input class="myTdInp my_student" type="text" name="id" readonly="readonly" value="<%=request.getAttribute("testNum")%>"/> <br /> </td>
       </tr>
       <tr>
	       <td class="myTd myTdLast"> 考生姓名:</td>
	       <td class="myTd myTdInp" ><input class="myTdInp my_student" type="text" name="username" readonly="readonly"  value="<%=request.getAttribute("stuName")%>"/> <br /> </td>
       </tr>
       <tr>
	       <td class="myTd myTdLast"> 考生班级:</td>
	       <td class="myTd myTdInp" ><input class="myTdInp my_student" type="text" name="username"  readonly="readonly"  value="<%=request.getAttribute("stuClass")%>"/> <br /> </td>
       </tr>
       <tr>
	       <td class="myTd myTdLast">课 程:</td>
	       <td class="myTd myTdInp" ><input class="myTdInp my_student" type="text" name="username"  readonly="readonly"  value="<%=request.getAttribute("stuCourse")%>"/> <br /> </td>
       </tr>
              <tr>
	       <td class="myTd myTdLast"> 成 绩:</td>
	       <td class="myTd myTdInp" ><input class="myTdInp my_student" type="text" name="username"  readonly="readonly"  value="<%=request.getAttribute("stuMark")%>"/> <br /> </td>
       </tr>
		   <tr class="chazhao_top">
			   <td colspan="2" class="myTd_find"> 
				   <input type="submit" value="返回继续查询" class="button1"/>
			   </td>
		   </tr>
       </table>
       
        
    </form>
</div>
    
    
    
    
</body>
</html>

3.1.3 查询出错页面显示 noResult.jsp

此页面是一个容错页面,主要是找不到相关学生(无相关准考证或输入错误),再重新回到查询页面(由于篇幅所限,页面中的css和JavaScript代码省略了,有需要可以在附件中下载)

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>暂时找不到该同学</title>
</head>
<body>
    
<div class="myDiv">
    <form action=welcome.jsp method="post">
       <table class="myTable">
		   <tr class="SCname"><td colspan="2" ><div id="SCname_top"></div></td></tr>
		   <tr class="chaxun"><th colspan="2" >2022年学生成绩查询</th></tr>
	   <tr>
	       <td class="myTd myTdLast">  </td>
	       <td class="myTd myTdInp" ><br /> </td>
       </tr>
       <tr class="kaoshenghao">
	       <td class="myTd myTd2"> 考生准考号:</td>
	       <td class="myTd myTd2 myTdInp "><input class="myTdInp my_student" type="text" name="id" readonly="readonly" value="暂时找不到此人,请重新核对准考证号"/> <br /> </td>
       </tr>

       <tr>
	       <td class="myTd myTdLast"> 温馨提示:</td>
	       <td class="myTd myTdInp" ><input class="myTdInp my_student" type="text" name="username"  readonly="readonly"  value="可致电咨询:010-12345678"/> <br /> </td>
       </tr>
		   <tr class="chazhao_top">
			   <td colspan="2" class="myTd_find"> 
				   <input type="submit" value="返回继续查询" class="button1"/>
			   </td>
		   </tr>
       </table>
    </form>
</div>    
</body>
</html>

3.1.4 XML文件配置 web.xml

如果大家细心留意,就会发现在welcome.jsp中有一个表单

*** ** 里面的action的值,其实就在xml文件中做了关联的 **myQuery** 请看下面web.xml中的 和 **这两对标签,其实就关联了jsp页面和java类的跳转关系了** * 注:micro.controller.FindByNum是一个类,Controller控制层的一个类
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app id="WebApp_ID">
		<display-name>StudentFindByNum</display-name>
	<servlet>
        <servlet-name>Query</servlet-name>
        <servlet-class>micro.controller.FindByNum</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Query</servlet-name>
        <url-pattern>/myQuery</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>Welcome.jsp</welcome-file>
		<welcome-file>Welcome.do</welcome-file>
		<welcome-file>welcome.html</welcome-file>
    </welcome-file-list>
</web-app>

3.2 数据库准备:

数据库创建:(直接用Navicat软件创建就可以了,Navicat使用: link
在这里插入图片描述

3.3 Entity,实体对象 Student.java

对java实体类的理解:
A .就是属性类
B. 一般的实体类对应一个数据表,其中的属性对应数据表中的字段。

  • 在本项目中 :学生(准考证号,姓名,班级,课程名,成绩)
  • 留意上图的数据库对应 studentfindbynum (testNum, stuName, stuClass, stuCourse, stuMark)
  • 注意:要和数据库表属性 一 一 对应

实体类有属性和方法,属性对应数据库中表的字段,主要有getter和setter方法。

package micro.entity;

public class Student {
	
	String testNum;
	String stuName;
    String stuClass;
    String stuCourse;
    String stuMark;
    
	public String getTestNum() {
		return testNum;
	}
	public void setTestNum(String testNum) {
		this.testNum = testNum;
	}
	public String getStuName() {
		return stuName;
	}
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	public String getStuClass() {
		return stuClass;
	}
	public void setStuClass(String stuClass) {
		this.stuClass = stuClass;
	}
	public String getStuCourse() {
		return stuCourse;
	}
	public void setStuCourse(String stuCourse) {
		this.stuCourse = stuCourse;
	}
	public String getStuMark() {
		return stuMark;
	}
	public void setStuMark(String stuMark) {
		this.stuMark = stuMark;
	}

}

3.4 Controller,控制层 FindByNum.java

Controller层负责具体的业务模块流程的控制,其实就是与前台、后台数据交互,把前台传进来的参数进行处理,controller层主要调用Service层(继承 HttpServlet 类)里面的接口控制具体的业务流程,控制的配置也需要在配置文件中进行。

package micro.controller;

import java.io.IOException;
import java.sql.SQLException;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import micro.dao.ServiceDao;
import micro.entity.Student;

/**
 * Servlet implementation class FindByNum
 */
@WebServlet("/FindByNum")
public class FindByNum extends HttpServlet {
	
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public FindByNum() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        this.doPost(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        String testNum = request.getParameter("testNum");
//        long id = Long.valueOf(request.getParameter("id"));
        System.out.println(testNum);


            try
            {
            	Student student = ServiceDao.getNameByNum_Student(testNum); // 返回一个student对象
            	if (student.getTestNum()==null) { 
request.getRequestDispatcher("/NOResult.jsp").forward(request, response);//查不到
				}else {
					
				
            	System.out.println(student);
                System.out.println("try"+testNum);
                 
                //结果页面显示的内容 
                /**
                    * 	String testNum;
	                * 	String stuName;
                    * 	String stuClass;
                    * 	String stuCourse;
                    * 	String stuMark;
                 * */
                
                request.setAttribute("testNum", student.getTestNum()); 
                request.setAttribute("stuName", student.getStuName());
                request.setAttribute("stuClass", student.getStuClass());
                request.setAttribute("stuCourse", student.getStuCourse()); 
                request.setAttribute("stuMark", student.getStuMark()); 
                
    request.getRequestDispatcher("/NameResult.jsp").forward(request, response);
				}//else
             }
            catch(SQLException e)
            {
                System.out.println("数据库出现异常");
                e.printStackTrace();
            }
           
        }           
}

3.4 Model,事务模型层之Dao类

主要与数据库进行交互。具体到对于某个表的增删改查,也就是说某个Dao一定是和数据库的某一张表一一对应的,其中封装了增删改查基本操作,建议Dao只做原子操作,增删改查。

  • 注:一般情况下,Dao层的数据源和数据库连接的参数都是在配置文件中进行配置的。在该项目中为了方便初学者了解整个项目具体流程,在dao文件写死数据库连接方式。

  • 下列java中
    * * String url = “jdbc:mysql://localhost:3306/数据库名”;//
    * * String username = “root”; 注意自己数据库登录名,一般默认为root
    * * String pass-word = “密码”;//自己修改

package micro.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mysql.jdbc.PreparedStatement;

public class Dao {
    public static Connection getConnection() throws SQLException
    {
        String url = "jdbc:mysql://localhost:3306/studentfindbynum"; //注意自己数据库名字
        String username = "root";//注意自己数据库登录名,默认为root
        String password = "  ";//注意自己数据库登录密码
        Connection conn = null;
        try
        {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(url, username, password);
        }
        catch(ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        return conn;
    }
    public static void close(ResultSet rs,PreparedStatement ps,Connection conn) throws SQLException
    {
        try
        {
            rs.close();
            ps.close();
            conn.close();
        }
        catch(SQLException e)
        {
            e.printStackTrace();
        }
    }
}

3.5 Model,事务模型层之Service类

主要负责业务模块的逻辑应用设计。粗略的理解就是对一个或多个Dao进行的再次封装,封装成一个服务,所以这里也就不会是一个原子操作了,需要事物控制。

package micro.dao;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import micro.entity.Student;

import com.mysql.jdbc.PreparedStatement;

public class ServiceDao {

    
    /**
     * @param testNum
     * @return Student  8.16
     * @throws SQLException
     */
    @SuppressWarnings("null")
	public static Student getNameByNum_Student(String testNum) throws SQLException {
        Connection conn;
        String name = null; 
        Student student = new Student();
        try {
            conn = Dao.getConnection();
            PreparedStatement ps = (PreparedStatement) conn
                    .prepareStatement("select * from student where testNum = ?");
            // ps.setString(1, "");
            ps.setString(1, testNum);//(1, id);
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
//                name = rs.getString("name");
//                String major = rs.getString("major");
                String stuName = rs.getString("stuName");
                String stuClass = rs.getString("stuClass");
                String stuCourse = rs.getString("stuCourse");
                String stuMark = rs.getString("stuMark");
                   student.setTestNum(testNum);  
                   student.setStuName(stuName);
                   student.setStuClass(stuClass);
                   student.setStuCourse(stuCourse);
                   student.setStuMark(stuMark); 
            }
            Dao.close(rs, ps, conn);

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return student;
    }
    
    
}

四、总结

综上几个文件,可以得到大致架构如下:
在这里插入图片描述
建议一步一步跟着教程操作,这样会容易理解点。

源码下载学习: link

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值