Eclipse用JSP、JSTL+El表达式、servlet、MySQL数据库写一个Java Web的学生管理系统、赋赠整个小项目。

1.要求:


  1. 软件:有MySQL数据库、Eclipse
  2. 有前台显示页面
  3. 实现对学生的、增、删、改、查
    1. 查询是模糊查询,输入姓或者名得出一个表
    2. 修改是根据账号修改,且账号不可以修改
    3. 删除保留在当前页面(分页后会有好多页,在删除最后一页最后一个数据时刷新后还在当前页面只是要删除数据消失了)
    4. 删除前:
    5. 删除后:还在第三页
  4. 并对结果进行分页显示,每一页只显示三条信息。

2.分析:


  1. 数据库表必须要有:账号、姓名、密码,且其中账号为主键。                        

3.实施


(1).:创建Java web项目:

  • (2).:Java和后端交互(Eclipse链接数据,实现学生对数据库的增删改查)


       Java web项目中创建4个包

  • 其中:
  • bean包(JavaBean):JavaBean是一个符合特定规范的Java类。通常用于封装数据,并提供公共的getter和setter方法以及其他操作方法。JavaBean用于在不同的层之间传递数据或表示业务实体。                                                                                                                        (简单理解就是定义Java类地方,其中包含这个类属性、get、set、toString、有参、无参构造方法)

  • dao包(Data Access Object):DAO是数据访问对象的缩写。DAO模式是一种用于数据持久化的设计模式。DAO类封装了与数据存储相关的操作方法,如增加、删除、修改和查询等。通过DAO,应用程序可以更方便地与底层数据库进行交互,并隐藏数据库细节。           (简单理解就是链接数据库、对数据库进行增删改查地方)

  • service包:Service层位于DAO层之上,负责处理业务逻辑。Service层通常封装了一系列的业务操作,如数据校验、事务管理和调用多个DAO方法等。它使得控制层,如Servlet,能够更专注于处理请求和响应,将业务逻辑的处理分离出来。同时,service层的存在使得信息处理的代码更加模块化可复用,方便进行单元测试和维护、确保输入的数据是有效和可信的,以及对数据进行必要的处理和操作,满足业务需求和数据完整性的要求。。                                 简单理解就是对数据检测、以及数据处理

  • servlet包:Servlet是Java Web开发中处理HTTP请求和生成HTTP响应的组件。Servlet是运行在Web服务器上的Java类。它可以接收来自客户端的请求,并生成相应的响应。Servlet可以处理不同类型的请求(如GET、POST等),在服务端执行相应的业务逻辑,并与客户端进行交互。Servlet将Java代码嵌入到Web应用程序中,实现与客户端的交互和业务逻辑处。Servlet运行在服务器端,所以它可以与数据库、文件系统等后台资源进行交互,处理复杂的数据操作和业务需求。                                                                                                                  简单理解就是处理HTTP请求、生成动态内容并实现服务器端业务逻辑的Java组件,是构建Java Web应用程序的重要组成部分

 


1.: Eclipse链接数据库

 Eclipse链接数据库,数据库链接测试,MySQL环境变量配置:http://t.csdn.cn/3Hp1Y


2.:Eclipse链接测试过数据库后,开始把链接测试代码规范化。上文讲到dao包就是链接数据库、对数据库进行增删改查地方,所有要在dao包中创建文件把链接写到里面。

 

package com.jd.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.jd.bean.Student;

/**
 * 数据持久化层
 * @author lenovo
 */
public class BaseDAO<E> {
	
	private static final String DRIVER="com.mysql.cj.jdbc.Driver";
	private static final String URL="jdbc:mysql://127.0.0.1:3306/gs?useUnicode=true&characterEncoding=utf-8";
	private static final String USERNAME="root";
	private static final String USERPWD="000000";
	private Connection conn=null;
	private Statement stmt=null;
	protected ResultSet rs=null;
	//加载驱动  在整个使用的过程中,只需要加载一次 所以使用static
	static {
		try {
			//加载驱动
			Class.forName(DRIVER);
			System.out.println("===驱动加载成功===");
		} catch (Exception e) {
			e.printStackTrace();//捕获异常
		}
	}
	
	public void getConn() {
		try {
			//连接数据库
			//连接云端就把localhost改成地址
			conn= DriverManager.getConnection(URL,USERNAME,USERPWD);
			System.out.println("===连接成功===");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void getStmt() {
		try {
			//创建命令执行对象
			stmt=conn.createStatement();
			System.out.println("===创建命令执行对象成功===");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void closeRes() {
		try {
			if(rs!=null) {
				rs.close();
				rs=null;
			}
			if(stmt!=null) {
				stmt.close();
				stmt=null;
			}
			if(conn!=null) {
				conn.close();
				conn=null;
			}
			System.out.println("===资源释放成功===");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	//通用的增删改操作
	public void update(String sql) throws Exception {
		//1.加载驱动
		//2.连接数据库  连接云端就把localhost改成地址
		getConn();	
		//3.创建命令执行对象
		getStmt();
		//4.执行命令
		stmt.executeUpdate(sql);
		//stmt.executeQuery(sql);
		System.out.println("====sql===="+sql);
		//5.释放资源
		closeRes();
	}
	
	//查询方法
	public List<E> query(String sql) throws SQLException{
		getConn();
		getStmt();
		rs=stmt.executeQuery(sql);
		List<E> list=new ArrayList<E>();
		rs2list(list);
		closeRes();
		return list;
	}
	
	public void rs2list(List<E> list) {
		//子类E类会继承这个方法并且对其重写
		
	}

	/*
    这是一个泛型类,使用<E>表示泛型参数,可以根据需要指定具体类型。

	定义了与数据库连接和操作相关的常量,如驱动、URL、用户名和密码。

	getConn()方法用于获取数据库连接。

	getStmt()方法用于创建命令执行对象。

	closeRes()方法用于释放资源,关闭ResultSet、Statement和Connection对象。

	update(String sql)方法用于执行更新操作(增删改)。

	query(String sql)方法用于执行查询操作,返回一个泛型为E的结果列表。

	rs2list(List<E> list)方法用于将查询结果转换为列表。子类可以继承并重写此方法来实现自定义的结果处理逻辑。
	*/

}

 其中用到了Java泛型类解释:http://t.csdn.cn/gnvbA

BaseDAO<E>就是一个泛型类,BaseDAO<E>类中也有方法使用了类型参数E。

        例如 :List<E> query(String sql)方法返回一个泛型为E的结果列表。这样一来,使用BaseDAO类时,可以根据需要将E替换为具体的类型,并在方法中使用相应的类型。这样就使得BaseDAO类具有了通用的数据持久化能力,可以处理不同类型的数据,提高了代码的复用性和灵活性。

        总之,泛型类是一种能够适应不同类型的通用类,通过使用类型参数可以达到代码重用和类型安全的目的。


3.: 创建学生类对象实现对学生在数据库的操作,bean包定义Java类地方,其中包含这个类属性、get、set、toString、有参、无参构造方法。

package com.jd.bean;

/**
 * 学生类
 */
public class Student {
	private String stu_id; // 学生编号
	private String stu_name; // 学生姓名
	private String stu_pwd; // 学生密码
	
	/**
	 * 获取学生编号
	 * @return 学生编号
	 */
	public String getStu_id() {
		return stu_id;
	}
	
	/**
	 * 设置学生编号
	 * @param stu_id 学生编号
	 */
	public void setStu_id(String stu_id) {
		this.stu_id = stu_id;
	}
	
	/**
	 * 获取学生姓名
	 * @return 学生姓名
	 */
	public String getStu_name() {
		return stu_name;
	}
	
	/**
	 * 设置学生姓名
	 * @param stu_name 学生姓名
	 */
	public void setStu_name(String stu_name) {
		this.stu_name = stu_name;
	}
	
	/**
	 * 获取学生密码
	 * @return 学生密码
	 */
	public String getStu_pwd() {
		return stu_pwd;
	}
	
	/**
	 * 设置学生密码
	 * @param stu_pwd 学生密码
	 */
	public void setStu_pwd(String stu_pwd) {
		this.stu_pwd = stu_pwd;
	}
	
	/**
	 * 构造方法
	 * @param stu_id 学生编号
	 * @param stu_name 学生姓名
	 * @param stu_pwd 学生密码
	 */
	public Student(String stu_id, String stu_name, String stu_pwd) {
		super();
		this.stu_id = stu_id;
		this.stu_name = stu_name;
		this.stu_pwd = stu_pwd;
	}
	
	/**
	 * 无参构造方法
	 */
	public Student() {
		super();
	}
	
	/**
	 * 返回学生对象的字符串表示形式
	 */
	@Override
	public String toString() {
		return "Student [stu_id=" + stu_id + ", stu_name=" + stu_name + ", stu_pwd=" + stu_pwd + "]";
	}
}

(get、set、toString、有参、无参构造方法可以让其自动生成快捷方便):

4.:创建好学生对象就对可以写增删改查等操作方法具体内容,上文讲到dao包就是链接数据库、对数据库进行增删改查地方,所以详细代码写作dao包中。

package com.jd.dao;

import java.sql.SQLException;
import java.util.List;
import com.jd.bean.Student;

/**
 * 将所有对Student表的crud操作全部写在子类中
 * 好管理!
 * @author jd
 */
public class StudentDao extends BaseDAO<Student>{
	
	//查询全部
	public List<Student> findAll() throws SQLException{
		String sql="select * from student";
		return super.query(sql);
	}
	
	//模糊查询全部学生
	public List<Student> FuzzySearch(String name) throws SQLException {
		System.out.println(name);
		String sql="select * from student where name like '"+name+"%' ";
		System.out.println("mysql语句:"+sql);
//		SELECT * FROM 表名 WHERE 姓名列 LIKE '%查询关键词%';
		return super.query(sql);
	}
	
	
	//查询指定范围内的学生记录
	public List<Student> findShow(int currentP, int currentS,String name) throws SQLException {
		int star=currentP;
		System.out.println("开始"+star);
		System.out.println("长度"+currentS);
		String sql;
		if(name==null) {
			 sql="select * from student limit "+star+","+currentS+"";
		}else {
			 sql="select * from student where name like '"+name+"%' limit "+star+","+currentS+"";
		}
		System.out.println("sql:"+sql);
		return super.query(sql);
	}
	
	
	//根据学生编号查询学生记录
	public List<Student> findStudentById(String stu_id) throws Exception{
		String sql="select *from student where stu_id='"+stu_id+"'";
		return super.query(sql);
	}//stu_id='"+stu_id+"'表示stu_id等于输入的值
	
	//添加学生记录
	public void addStudent(Student stu) throws Exception {
		String sql="insert into student values('"+stu.getStu_id()+"', '"+stu.getStu_name()+"', '"+stu.getStu_pwd()+"')";
		System.out.println("sql:"+sql);
		super.update(sql);
	}
	//更新学生记录
	public void updateStudentById(Student stu) throws Exception {
		String sql="UPDATE student SET name='"+stu.getStu_name()+"', pwd='"+stu.getStu_pwd()+"' WHERE code='"+stu.getStu_id()+"'";
		System.out.println("sql="+sql);
		super.update(sql);
	}
	
	
	//删除学生记录
	public void deleteStudentById(String stu_id) throws Exception {
		String sql="delete from student where code='"+stu_id+"'";
		System.out.println("sql:"+sql);
		super.update(sql);
	}
	
/*	
 * rs2list(List<Student> list)方法是对父类方法的重写。
	在父类BaseDAO中可能存在一个名为rs2list()的方法,但它的实现方式与子类StudentDao中的方法不同。
	子类通过重写父类方法,可以根据自己的需求重新定义方法的实现逻辑。
	*/
	public void rs2list(List<Student> list) {
		try {
			while(rs.next()) {
				String stu_id=rs.getString("code");
				String stu_name=rs.getString("name");
				String stu_pwd=rs.getString("pwd");
				Student stu=new Student(stu_id,stu_name,stu_pwd);
				list.add(stu);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

前期Eclip链接数据库以及对数据库增删修改都基本完成。

  • (3).前端和Java交互:(实现页面传递数据到Java中)

  1. servlet包就是处理HTTP请求、生成动态内容并实现服务器端业务逻辑的Java组件。

创建servlet:

package com.jd.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.jd.bean.Student;
import com.jd.service.StudentService;

/**
 * Servlet implementation class ShowSudentServlet
 * 学生信息展示的Servlet
 */
@WebServlet("/show2")
public class ShowSudentServletTextJavaWeb extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     * 构造函数
     */
    public ShowSudentServletTextJavaWeb() {
        super();
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 * 处理GET请求
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);//不管是get还是post都取post里面
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 * 处理POST请求
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		/*requese   请求  
		 * respond  响应
		 * */
		
		// 设置请求乱码,解决从HTML页面到Servlet的数据乱码问题
		request.setCharacterEncoding("utf-8");
		
		// 设置响应乱码,解决从Servlet到浏览器显示的数据乱码问题
		response.setContentType("text/html;charset=utf-8");
		
		// 通过页面接收分页数据currentPage-当前页,currentSize-每页记录数
		String currentPage = request.getParameter("currentPage");
		String currentSize = request.getParameter("currentSize");
		
		System.out.println("**********currentPage" + currentPage);
		System.out.println("**********currentSize" + currentSize);
		
		// 分页实际使用的参数
		int currentP = 1;
		
		// 判断是否传递了currentP参数,若传递了则使用传递的值,否则默认为1
		if (request.getParameter("currentP") != null) {
			currentP = Integer.valueOf(request.getParameter("currentP"));
			System.out.println("&&&&&&&&&&&&&&&&&&currentP" + currentP);
		}
		
		int currentS = 3;
		
		// 如果传递了currentPage和currentSize参数,则使用传递的值
		if (currentPage != null || currentSize != null) {
			currentP = Integer.valueOf(currentPage);
			currentS = Integer.valueOf(currentSize);
		}
		
		// 计算总页数
		int totalPage = new StudentService().getTotalPage(currentS);
		List<Student> list = null;
		
		// 判断是否进行了模糊查找
		String sname = null;
		if (request.getParameter("queryname") == null) {
			sname = request.getParameter("sname"); // 获取Java Web传递的sname
		} else {
			sname = request.getParameter("queryname");
			/* 
			 * 获取Java Web中的queryname,而不是Java Web传递的。
			 * 因为这是要获取输入框输入的name字段,形成一个闭环,只要输入框进行了输入,就会一直传递name。
			 * 当不传递name时就跳出这个闭环。
			 */
		}
		
		// 查看是否获取到了sname
		System.out.println(sname);
		
		// 调用模糊查询函数,将查询到的学生集合传递给list
		System.out.println("模糊查询函数");
		try {
			System.out.println(sname);
			if (sname != null) {
				list = new StudentService().FuzzySearchSname(sname);
				
				// 重新计算总页数
				totalPage = (list.size() - 1) / 3 + 1;
			}
			
			// 分页显示
			int n = (currentP - 1) * currentS;
			list = new StudentService().findStudentPage(n, currentS, sname);
			System.out.println("模糊查询list大小:" + list.size());
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		System.out.println("list.size():" + list.size());
		
		// 使用request域传递数据
		request.setAttribute("list", list);
		request.setAttribute("currentP", currentP);
		request.setAttribute("totalPage", totalPage);
		request.setAttribute("sname", sname);
		
		/*
		 * 将当前请求转发给名为 "JavaWeb.jsp" 的JSP页面。
		 * 在该JSP页面中,可以使用 request 和 response 对象来访问请求和响应相关的信息,并生成相应的内容返回给客户端。
		 */
		request.getRequestDispatcher("JavaWeb.jsp").forward(request, response);
	}
}

其中的

1.:request.setCharacterEncoding("utf-8")

  request.setCharacterEncoding("utf-8")用于设置请求的编码为UTF-8,确保能够正确处理传递给Servlet的数据,特别是中文字符。这样设置后,Servlet 就能正确地读取请求中的参数值,并将其转换成 UTF-8 编码的字符串。(servlet->html)

  response.setContentType("text/html;charset=utf-8")用于设置响应的内容类型及编码。在该代码中,设置响应的内容类型为"text/html",表示返回的是HTML页面;同时设置编码为UTF-8,以确保在浏览器中正确显示中文字符。(html->servlet)

通过这两行代码的设置,可以有效解决在请求和响应过程中可能出现的乱码问题,确保数据能够正确传递和显示。

        

2.: request.setAttribute("sname", sname);和request.getRequestDispatcher("JavaWeb.jsp").forward(request, response);区别
  •   定变量sname包含了一个字符串类型的值,通过request.setAttribute("sname", sname)方法将该值设置为请求属性。这样,你可以在接下来的请求转发中通过请求对象(request)来访问这个属性。
  •   接下来,使用request.getRequestDispatcher("JavaWeb.jsp")方法获取一个请求调度器,该调度器用于将请求转发到指定的目标URL或资源。在这里,我们将请求转发到名为JavaWeb.jsp的JSP页面进行处理。
  •   最后,调用forward(request, response)方法执行请求转发操作。这将将控制权从当前Servlet转移到指定的JSP页面,并将请求和响应对象传递给JSP页面进行处理。
  •   在接收到转发请求后,JavaWeb.jsp页面可以通过${sname}表达式访问请求属性"sname"的值,并在页面上显示或进行其他处理。

简单理解就是把sname值(后面的那个sname重新命名为:"sname"传递)传递到JavaWeb.jsp中,在JavaWeb.jsp中可以用

         1.${sname} 表达式:这是最简单和常用的方式 

         2.使用 Java 代码调用 request.getAttribute("sname") 方法:在 JavaWeb.jsp 页面中可以使用 <% String sname = (String) request.getAttribute("sname"); %> 这样的脚本片段来获取请求属性值,并将其存储在局部变量 sname 中。

         3.使用 EL 隐式对象 requestScope${requestScope.sname} 可以通过 requestScope 对象来获取请求属性值

3.:requestScope.sname request.getAttribute("sname") 的区别

        1.作用域不同:

  •  requestScope.sname 表达式从请求范围(request scope)中获取属性值。请求范围是指在同一次请求处理过程中,多个 servlet 或 JSP 页面之间共享的数据。
  •  request.getAttribute("sname") 方法从 request 对象中获取请求属性的值,该属性可以是放置在请求范围或其他作用域中的。

        

        2.表达式 、 方法:

  •  requestScope.sname 是 EL(Expression Language)表达式,用于访问 Java 对象的属性。
  •  request.getAttribute("sname") 是 request 对象的方法,通过名称获取请求属性的值。

        

        3.表达式语法 、 Java 方法语法:

  •  requestScope.sname 使用 ${} 语法,即${requestScope.sname }其中 requestScope 是一个隐式对象,用于访问请求范围中的属性。
  •  request.getAttribute("sname") 是 Java 方法调用的语法,通过 getAttribute 方法获取请求属性值。

综上所述requestScope.snamerequest.getAttribute("sname") 都可以用来获取请求属性 "sname" 的值,但其语法和作用域有所不同。一般情况下,在 JSP 页面中使用 EL 表达式的方式更为简洁和方便。

  1. 创建JavaWeb.jsp,实现前台页面。

<%@page import="java.lang.Thread.State"%>
<%@page import="com.jd.bean.Student"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>

<!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>Insert title here</title>
    <style type="text/css">
        table {
            border: 1px solid black;
            border-collapse: collapse;
            width: 800px;
        }
        table tr {
            height: 40px;
        }
        table tr td {
            border: 1px solid black;
        }
    </style>
</head>
<body>	
    <%-- 获取请求属性 list,并将其转换为 List<Student> 类型 --%>
    <% List<Student> list = (List<Student>) request.getAttribute("list"); %>
    <table>
        <tr>
            <td>账号</td>
            <td>姓名</td>
            <td>密码</td>
            <td>操作</td>
        </tr>
        <%-- 遍历 List<Student>,显示每个学生的相关信息 --%>
        <% for (int i = 0; i < list.size(); i++) { %>
        <tr>
            <td><%= list.get(i).getStu_id() %></td>
            <td><%= list.get(i).getStu_name() %></td>
            <td><%= list.get(i).getStu_pwd() %></td>
            <td>
                <a href='deletstudent?stu_id=<%= list.get(i).getStu_id() %>&currentP=${currentP}'>删除</a>
                <a href='modifystu.jsp?code=<%= list.get(i).getStu_id() %>&name=<%= list.get(i).getStu_name() %>&pwd=<%= list.get(i).getStu_pwd() %>&currentP=${currentP}'>修改</a>
            </td>
        </tr>
        <% } %>
        <form action="show2" method="get">
            <input type="text" name="queryname" placeholder="在此输入检索姓名" />
            <input type="submit" value="搜索" />
        </form>
    </table>
    
    <%-- 分页导航 --%>
    <a href='show2?currentPage=1&currentSize=3&sname=${requestScope.sname }'>首页</a>
    <a href='show2?currentPage=${(currentP - 1) < 1 ? 1 : (currentP - 1)}&currentSize=3&sname=${requestScope.sname }'>上一页</a>
    <a href='show2?currentPage=${(currentP + 1) > totalPage ? totalPage : (currentP + 1)}&currentSize=3&sname=${requestScope.sname }''>下一页</a>
    <a href='show2?currentPage=${totalPage}&currentSize=3&sname=${requestScope.sname }'>末页</a> 
    <a href='show2?currentPage=1&currentSize=3'>全部信息</a>
    
    <%-- 显示当前页数和总页数 --%>
    <span>${currentP}/${totalPage}: 当前页/总页数</span>
    <%-- 等价于:<span><%=(int)request.getAttribute("currentP") %>/<%=(int)request.getAttribute("totalPage") %>:当前页/总页数</span> --%>
</body>
</html>

   

2.1.<% List<Student> list=(List<Student>)request.getAttribute("list");%>

        1.在.jsp页面写Java代码都需要<% %>

        2.request.getAttribute("list")是ShowSudentServletTextJavaWeb 中 request.setAttribute("list", list);和request.getRequestDispatcher("JavaWeb.jsp").forward(request, response);传递过来的,需要用request.getAttribute("list")或者 EL 表达式${list}等方法接收。

2.2.<a href='show2?currentPage=1&currentSize=3&sname=${requestScope.sname }'>首页</a>

其是一个超链接,用于跳转到显示页面的第一页:

  • <a> 标签用于创建一个超链接。
  • href 属性指定了超链接的目标地址。在这里,目标地址是 'show2',表示要发送到名为 'show2' 的 URL。(其中的show2就是当初创建的ShowSudentServletTextJavaWeb,有的eclipse不显示,版本问题也有可能缺少相关的配置或错误导入的原因。)

  • 在 href 属性中嵌入了查询参数,用于传递当前页码、每页显示数量和学生姓名信息。
    • currentPage=1 表示当前页码为1,固定值。
    • currentSize=3 表示每页显示数量为3,固定值。
    • sname=${requestScope.sname } 表示学生姓名作为查询参数的一部分。${requestScope.sname } 是一个 EL 表达式,用于从请求作用域中获取学生姓名的值并插入链接中。
  • 链接的文本内容为 '首页',当用户点击该链接时,将跳转到显示页面的第一页,并将相关的查询参数传递给 'show2' 页面。

       总之,这段代码生成了一个带有当前页码、每页显示数量和学生姓名作为查询参数的超链接,用于跳转到显示页面的第一页。用户点击该链接时,将导航到 'show2' 页面并显示第一页的内容。且该超链接传递了当前页码、每页显示数量和学生姓名三个属性到 "show2" 页面,在show2页面可以用String sname = (String) request.getAttribute("sname") 来获取学生姓名的值也可以但是用 String currentPage = request.getParameter("currentPage") 来获取当前页码的值最符合。

3.区分request.getAttribute("sname")和request.getParameter("sname")

     

        3.1. request.getParameter("sname")适用于:当在超链接或表单中使用参数、传递到下一个页面。且获取的是是参数值。

简述:如果上一个页面使的是:

        <a href='show2?currentPage=1&currentSize=3&sname=${requestScope.sname }'>首页</a>

URL转发页面,其中URL拼接属性就使用 request.getParameter("sname"),接受的值是参数值

       3.2. request.getAttribute("sname")适用于请求属性是在服务器端传递值或对象的一种方式。

简述: 如果上一个页面使的是:

            request.setAttribute("sname", sname);
            request.getRequestDispatcher("JavaWeb.jsp").forward(request, response);

传递的,可以用request.getAttribute("sname")接收,且接收的是Object 类型的数据

收时需要定义类型接受:String sname = (String) request.getAttribute("sname");

或者在jsp页面中可以使用:${requestScope.sname },现在当前页面的请求作用域中查找名为 "sname" 的属性如果当前页面没有在去、请求作用域(Request Scope)->页面作用域(Page Scope)->会话作用域(Session Scope)->应用程序作用域(Application Scope),如果在任何作用域中都找不到该属性,${requestScope.sname} 表达式将返回空字符串。

总结:

如果上一个是用URL拼接传递的,可以用 request.getParameter("sname")接收接受的值是参数值。

如果是用请求属性和请求转发可以用 request.getAttribute("sname")接收且jsp页面可以多一个接收方式(${requestScope.sname })接受的是Object 类型的数据。

这已经完成了主体大致功能,接下来就是对细节填写,与优化。包括数据库数据的插入、显示数据库学生信息、对信息的分页、对增删改查的填写与调用、模糊查询、修改删除数据还显示在当前页。(当然这个只是简写版,没有登录验证、不包含数据检索、问题出错等一系列检索。只是完成如图功能:


1.数据库导入数据:

2. 连接数据库,分页显示出来

        首先看整个流程:servlet的ShowSudentServletTextJavaWeb.java会在分页显示方法处--->调用service的StudentService.java中的分页查询方法处---->调用dao的StudentDao中的查询指定范围内的学生记录方法处并且声明E为学生类、rs2list(List<Student> list)方法是对父类方法的重写后-->调用dao的BaseDAO其中的查询方法连接数据库查询输入到list数组返回--->最后回到servlet的ShowSudentServletTextJavaWeb.java,这时的list集合就已经有数据了。接着把list集合通过请求属性和请求转发把前台需要的属性传递过去,最后在前台输出

 因为StudentDao 继承了BaseDAO<Student>且把E赋值成了Student类(泛型类)

且其中方法rs2list(List<Student> list)方法是对父类方法的重写

 最后查询的信息就传递到list数组中了,接着把list集合通过请求属性和请求转发把前台需要的属性传递到javaWeb.jsp输出。

结果:

 其他代码几乎都是方法填充。