recap:
- 上节课重点讲述了JSP的一个内置对象request在JSP页面于servlet之间传递数据的特性
- 对比的以前用纯JSP完成对用户提供服务的模式与加入servlet与JSP协同合作的模式,特显了纯JSP页面的弊端
- 上节课的传输数据都是写死在了servlet中的(StudentServlet.java),首先通过index.jsp暴露一个连接到做处理的servlet的超链接,再通过StudentServlet类的构造器将数据进行传入,再通过显示的JSP页面将初始化数据进行展示;而不是连接上数据库,通过用户输入的数据,查找用户想要看到的数据,所以今天就通过连接数据库来实现从前端页面输入->查询DB->页面展示
- 本节课主要涉及:复习数据库知识、创建JavaBean、创建DAO、servlet通过调用JavaBean&DAO实现对数据库的增删改查(JDBC)、JSP内置对象session、EL表达式的简单用法
part1:在数据库中创建新表,创建字段(复习数据库知识)
-- 建表语句 注意先写字段名,再写数据类型,且数据类型后面要加括号指定该类型数据最大长度
create table student(
id int PRIMARY KEY,
stuno VARCHAR(20) NOT NULL,
name VARCHAR(20) NOT NULL,
age INT(3),
gender CHAR(2)
)
-- CHAR 固定长度,规定多少位,存储的时候就存多少位,不够就填充
-- VARCHAR 可变长度,只要没有超出规定的长度,则写多少位存多少位,存储长度可变
再复习一下对数据表的增删改查:
-- 增
INSERT INTO student(stuno,name,age,gender)
VALUES("2017124022","大王",21,'男');
INSERT INTO student(stuno,name,age,gender)
VALUES("2017124023","小王",22,'女');
INSERT INTO student(stuno,name,age,gender)
VALUES("2017124024","小小王",22,'男');
COMMIT;
-- 删
DELETE from student where name='大大王'
-- 改
UPDATE student SET name='大大小王' WHERE name='小小小王'
-- 查
SELECT * FROM student
part2:创建实体类Student(JavaBean):
package com.entity;
//实体类的作用:封装数据,即使得数据可以在JSP、servlet和DB之间传输
public class Student {
private String stuno;
private String name;
private int age;
private char gender;
//无参的构造方法
public Student() {
}
//带参的构造方法
public Student(String stuno, String name, int age, char geder) {
super();
this.stuno = stuno;
this.name = name;
this.age = age;
this.gender = geder;
}
public String getStuno() {
return stuno;
}
public void setStuno(String stuno) {
this.stuno = stuno;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGeder() {
return gender;
}
public void setGeder(char geder) {
this.gender = geder;
}
}
part3:创建连接DB的类DAO(database access object)--StudentDao.java
package com.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.entity.Student;
public class StudentDao {
//连接DB基本步骤
//1.连接字符串--即用于指定连接的数据库,以及对连接身份的认证
//使用JDBC技术连接MySQL数据库,地址为本机的3306端口,数据库名称为javawebdemo3
//Java database connection
private String url = "jdbc:mysql://localhost:3306/javawebdemo3";
private String user = "root";
private String password = "abc123456789";
//指定驱动类--在导入的架包中的com.mysql.jdbc包中的Driver.class
private String driver = "com.mysql.jdbc.Driver";
//建立全局都需要使用的变量
Connection conn = null;
PreparedStatement ps = null;
//2.建立连接
public Connection conn() {
try {
//1)加载驱动--可能会因为导包没导好而找不到这个class类
//所以要try-catch一下,即ClassNotFoundException
Class.forName(driver);
//2)建立链接--可能连接不上,所以也要try-catch一下,即SQLException
conn = DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
//本来连接数据库就是要获取连接,所以返回获取到的连接对象
return conn;
}
Student stu = null;
//通过学号查询学生实体,返回一个学生实体对象
public Student searchStudentById(String stuno) {
//获取数据库连接
conn = conn();
String sql = "select * from student where stuno = ?";
try {
//获取预编译对象,用于将参数化的SQL语句发送到数据库
ps = conn.prepareStatement(sql);
//设置sql语句中的缺省值
ps.setString(1, stuno);
//使用executeQuery方法真正去将sql语句发往DB
//其返回结果为一ResultSet对象,所以要用ResultSet对象接收
//execute()也可以发送ssql语句,但其返回值是 boolean类型
//且无论是否查到结果,只要传入的sql语句语法正确就会返回true
//因此不用execute()来做查询
ResultSet rs = ps.executeQuery();
//ResultSet返回的是“在数据库中查询到的,所有符合要求的数据行合成的数据表”
if(rs.next()) {
//resultset对象维护指向其当前数据行的游标
//最初,光标位于第一行之前,即什么都没有指向
//next方法将游标移动到下一行,第一次使用next,则该游标指向第一行数据
//游标指向的地方有数据,就返回true,没数据就返回false
String no = rs.getString("stuno");
String name = rs.getString("name");
int age = rs.getInt("age");
//因为resultset对象中没有设置getChar(),而设置了getCharacterStream()
//即获取字符流,但是数据表中gender字段只有一个字符,所以不能使用字符流去获取
//而是先用字符串存下来,在通过charAt(0)获取该字符串索引为0的字符,即第一个字符
char gender = rs.getString("gender").charAt(0);
//将从数据库中指定条件查询到的字段赋值给实体类
stu = new Student(no, name, age, gender);
}
} catch (SQLException e) {
e.printStackTrace();
}
return stu;
}
public static void main(String args[]) {
StudentDao stu = new StudentDao();
Student stuu = stu.searchStudentById("xxxxxx");
System.out.print(stuu.getName());
}
}
part4:写一个做用户查询请求处理的servlet(该servlet负责调用上述的DAO与JavaBean)
package com.servlets;
import java.io.IOException;
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 javax.servlet.http.HttpSession;
import com.dao.StudentDao;
import com.entity.Student;
@WebServlet("/search")
public class StudentServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置字符编码,防止出现汉字中文乱码
request.setCharacterEncoding("utf-8");
//获取数据层的对象,方便后面使用对DB的增删改查
String stuno = request.getParameter("stuno");
//获取用户输入的查询信息
StudentDao stu = new StudentDao();
//调用数据层的查询方法,返回的是自己定义的实体类Student
Student stuu = stu.searchStudentById(stuno);
//注意:在该处使用了两个对象,其中stu为StudentDao类的实例化对象;stuu为Student类的实例化对象
//获得具体的实体类之后需要将数据传向前端页面进行显示
//1.使用JSP内置对象request:request.setAttribute("stu", stu);将返回的实体类存入request的作用域中,再在前端页面去取该属性值进行输出即可显示
//2.使用JSP内置对象session:session的作用域比request的作用域要广一些
//第二课中使用了request,这里就用session
HttpSession session = request.getSession();
//将实体类存入session的作用域中
session.setAttribute("stuu", stuu);
//存好数据之后就跳转至显示页面(show.jsp)-- 内部跳转/转发,效率最高
request.getRequestDispatcher("showInfo.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
part5:写两个JSP页面(一个用于用户输入要查询的数据;一个用于向用户展示查询到的数据)
输入数据页面:index.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
</head>
<body>
<form action = search>
<input type="text" name="stuno">
<input type="submit" value="查询">
</form>
</body>
</html>
展示数据页面:showInfo.jsp(其中包含了使用JSP内置对象session取数据,也使用了EL表达式取数据)
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ page import="com.entity.Student" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
</head>
<body>
<h3>信息如下</h3>
<!-- 通过内置对象out输出实体类Student的实例化对象的属性值 -->
<%
Student stuu = (Student)session.getAttribute("stuu");
out.println("学号:"+stuu.getStuno()+"<br>");
out.println("姓名:"+stuu.getName()+"<br>");
out.println("年龄:"+stuu.getAge()+"<br>");
out.println("性别:"+stuu.getGeder()+"<br>");
%>
<!-- 通过EL表达式输出实体类Student的实例化对象的属性值 -->
<!-- EL表达式专门用来取值 -->
<p> ${sessionScope.stuu.getName()} </p>
<p> ${sessionScope.stuu.name} </p>
<!-- sessionScope.stuu的作用就是获取存入session作用域中的Student实例化对象stuu -->
<!-- 其可以取出该对象的各个属性原因还是在于该语句变相的调用了对应的get、set方法 -->
<!-- 所以在使用EL表达式时,必须要对获取的实例化对象进行封装(即JavaBean),否则没有对应的get、set方法,EL表达式就取不了属性值了 -->
</body>
</html>