一、需求:
利用html+java+mysql等技术手段,写一个demo,功能如下:根据准考号查找学生相关信息。
在查询页面中输入学生的考试号,及时查询到学生的姓名、班级、课程、成绩等信息。(该文主要讲述MVC模式,所以默认数据库只有一门课程一个成绩,利用第一范式构建数据库)
二、分析:
- 利用html+CSS来构建展示页面作为视图,包括:查询、查询结果页面等页面;
- 利用mysql构建数据库,学生(准考证号,姓名,班级,课程名,成绩);
- 利用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" />
<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