学习笔记是参考的how2j
本章笔记的目的是介绍如何与JDBC结合,通过servlet对数据库中的数据进行增、删、改、查。
一、前期准备
1、新建一个Dynamic Web Project 步骤为:file-new-other-Dynamic Web Project-next-项目名为【servlet_CURD】-finish,配置如下图。
![1f4e767e70d1b39e3fcaffbfb215ec65.png](https://i-blog.csdnimg.cn/blog_migrate/aca90c112213fd24f12e4aad2772cbd3.jpeg)
2、新建三个包,bean、dao,在三个包中分别创建类Hero、HeroDAO,配置如下图。
![9d31bcf4c0de390cea0a5f27df5b6201.png](https://i-blog.csdnimg.cn/blog_migrate/a0cf099043992f11c0a16dcc912b44a0.jpeg)
3、右键项目名,新建一个文件夹lib,在电脑中找到tomcat目录D:tomcat7-8080-eclipselib下的servlet-api.jar复制到刚刚建立的lib文件夹中。
同时在电脑中找到自己的mysql-jdbc驱动包,比如我的是mysql-connector-java-5.1.39-bin.jar放到项目目录WEB-INF/lib目录下。
然后对刚刚复制到项目中的两个jar包执行build path-add build to path,此时整个项目的结构如下:
![46450e28a46178e7779e309585bd4585.png](https://i-blog.csdnimg.cn/blog_migrate/2983c540185f480d455c961c96d5b600.jpeg)
4、在Hero类中写程序
我们使用的数据库中的数据是这样的,每个英雄对应4个属性,id、name、hp、damage
![45845253f71495558be0aaa11c3cd515.png](https://i-blog.csdnimg.cn/blog_migrate/b288f9e77ccd81af041233518947597b.png)
因此要在Hero类中,定义4个属性,并添加setter和getter方法。
package bean;
public class Hero {
public int id;
public String name;
public float hp;
public int damage;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getHp() {
return hp;
}
public void setHp(float hp) {
this.hp = hp;
}
public int getDamage() {
return damage;
}
public void setDamage(int damage) {
this.damage = damage;
}
}
5、在HeroDAO类中写程序
这个类中主要提供对数据库进行操作的方法,比如增删改查。当然这个类只是对数据库进行操作,如果要想通过在网页上执行这些操作,还需要其他的步骤,后面会讨论。
程序如下,带有注释:
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import bean.Hero;
public class HeroDAO {
//加载数据库驱动只需一次,因此定义在构造方法中
public HeroDAO() {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//建立数据库连接,因为后续的增删改查操作之前都需要和数据库建立连接,因此定义成一个方法
public Connection getConnection() throws SQLException {
String user="root";//这里的用户名和密码要和自己的数据库对应上,否则后面会无法访问数据库
String password="root";
//注意数据库名是how2j,自己的数据库名是什么就写什么
return DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2j?characterEncoding=UTF-8", user, password);
}
//获取表中数据的条数
public int getTotal() {
int total=0;
//先建立连接,然后处理sql语句
try(Connection c = getConnection();Statement s=c.createStatement();){
String sql="select count(*) from hero";
//执行sql语句并返回一个结果集,实际上结果集中只有一个数,表示的是表中数据的条数
ResultSet rs = s.executeQuery(sql);
while(rs.next()) {
total=rs.getInt(1);//获取结果集中的第一个数据,也就是数据的条数
}
} catch(SQLException e) {
e.printStackTrace();
}
return total;
}
//往表中添加数据
public void add(Hero hero) {
String sql="insert into hero values(null,?,?,?)";
try(Connection c=getConnection();PreparedStatement ps=c.prepareStatement(sql);){
//定义要添加的数据
ps.setString(1, hero.name);//为sql语句中的?赋值,1、2、3顺序
ps.setFloat(2, hero.hp);
ps.setInt(3, hero.damage);
//执行添加数据操作
ps.execute();
//获取刚刚插入的数据的id
ResultSet rs = ps.getGeneratedKeys();
while(rs.next()) {
int id = rs.getInt(1);
hero.id=id;
}
} catch(SQLException e) {
e.printStackTrace();
}
}
//更新表中的数据,也就是把表中的一条数据换成其他内容
public void update(Hero hero) {
String sql="update hero set name=?,hp=?,damage=? where id=?";
try(Connection c=getConnection();PreparedStatement ps=c.prepareStatement(sql);){
//更新表中的数据为
ps.setString(1, hero.name);
ps.setFloat(2, hero.hp);
ps.setInt(3, hero.damage);
ps.setInt(4, hero.id);
//执行更新数据操作
ps.execute();
} catch(SQLException e) {
e.printStackTrace();
}
}
//删除制定id的英雄
public void delete(int id) {
String sql="delete from hero where id=?";
try(Connection c=getConnection();PreparedStatement ps=c.prepareStatement(sql);){
ps.setInt(1, id);//给sql语句中的第一个?赋值
ps.execute();
} catch(SQLException e) {
e.printStackTrace();
}
}
//获取制定id的英雄的所有信息
public Hero get(int id) {
Hero hero=null;//新建一个Hero对象,后续返回Hero对象
String sql="select * from hero where id=?";
try(Connection c=getConnection();PreparedStatement ps=c.prepareStatement(sql);){
ps.setInt(1, id);
ResultSet rs = ps.executeQuery();
while(rs.next()) {
hero=new Hero();
String name=rs.getString("name");
Float hp=rs.getFloat("hp");
int damage=rs.getInt("damage");
hero.name=name;
hero.hp=hp;
hero.damage=damage;
hero.id=id;
}
} catch(SQLException e) {
e.printStackTrace();
}
return hero;
}
//暂时不知道这个函数是要干什么
public List<Hero> list(){
return list(0,Short.MAX_VALUE);
}
//返回整个表的所有值
public List<Hero> list(int start,int count){
List<Hero> heros = new ArrayList<Hero>();//一个Hero类型的列表,用来放多个英雄的列表
String sql="select * from hero order by id desc limit ?,?";
try(Connection c=getConnection();PreparedStatement ps=c.prepareStatement(sql);){
ps.setInt(1, start);
ps.setInt(2, count);
ResultSet rs = ps.executeQuery();
while(rs.next()) {
Hero hero = new Hero();//定义一个hero对象,用来放一个英雄的所有信息
int id = rs.getInt("id");
String name=rs.getString("name");
float hp = rs.getFloat("hp");
int damage = rs.getInt("damage");
hero.id=id;
hero.name=name;
hero.hp=hp;
hero.damage=damage;
heros.add(hero);
}
} catch(SQLException e) {
e.printStackTrace();
}
return heros;
}
}
6、想要从数据库中进行数据的操作,必须有对应的数据库和表,比如从上面程序中可以看出来,我的数据库名是how2j,且这个数据库下有一个表叫做hero;如果没有的话可以新建一个how2j数据库,然后再新建一个表;
#先执行这一句新建数据库
CREATE DATABASE how2j;
#再执行这一串新建hero表
CREATE TABLE `hero` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) DEFAULT NULL,
`hp` FLOAT DEFAULT NULL,
`damage` INT(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#然后多次执行这一串,往表中插入一些数据
INSERT INTO hero ( NAME, hp,damage )
VALUES( 'hero1', 44,1);
二、Servlet查询
上面做了一些准备工作,基于上面的工作,我们这一节主要目的是把hero表中的所有英雄信息都显示到网页上。
1、新建包servlet且在包内新建类HeroListServlet,然后在类中写程序如下:
package servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bean.Hero;
import dao.HeroDAO;
public class HeroListServlet extends HttpServlet{
public void service(HttpServletRequest request,HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=UTF-8");
//新建Hero对象列表,存放多个hero对象;调用heroDAO中的list()方法,获得hero的所有数据
List<Hero> heros = new HeroDAO().list();
StringBuffer sb = new StringBuffer();//下面用来存储所有要提交出去的信息
//新建一个table,和下面的/table构成一个闭环,中间的是表格中的内容
sb.append("<table align='center' border='1' cellspacing='0'>rn");//表格边框等样式
sb.append("<tr><td>id</td><td>name</td><td>hp</td><td>damage</td></tr>rn");//表头:id、name、hp、damage
String trFormat = "<tr><td>%d</td><td>%s</td><td>%f</td><td>%d</td></tr>rn";//每个表头对应的数据类型:%d、%s、%f、%d
for (Hero hero : heros) {//从Hero对象列表中取出一个Hero对象
//获得一个对象的属性:id、name、hp、damage
String tr = String.format(trFormat, hero.getId(), hero.getName(), hero.getHp(), hero.getDamage());
sb.append(tr);//把一条数据放到StringBuffer中
}
sb.append("</table>");
response.getWriter().write(sb.toString());//把所有Stringbuffer中的数据一起提交出去
}
}
2、配置xml文档
在WEB-INF下新建web.xml文档,然后在里面写入配置信息,如下。
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>HeroListServlet</servlet-name>
<servlet-class>servlet.HeroListServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HeroListServlet</servlet-name>
<url-pattern>/listHero</url-pattern>
</servlet-mapping>
</web-app>
3、启动tomcat
项目名右键-run as-run on server-next-add all-finish
![4bc477235b4217a58c0d34ad98737d3c.png](https://i-blog.csdnimg.cn/blog_migrate/46c0b0610377d57f3d559dae5c32b004.jpeg)
然后在新出现的页面中输入网址http://localhost:8080/servlet_CURD/listHero,可以看到在网页上显示了从数据库中查询到的数据。
![c9daa8a31f956a6edbec846b07736c8f.png](https://i-blog.csdnimg.cn/blog_migrate/601cb0bdac7bd18e6c3dc0f600de1296.jpeg)
三、Servlet添加数据
本节目的是在网页上输入一个新英雄的数据,添加到数据库中,并在网页上显示添加后的所有数据。
1、在WebContent目录下新建addHero.html
注意,一定要在WebContent目录下建立文件,否则按照下面的步骤,最后可能访问不到这个网页。
这个html文件主要负责在网页上显示出来输入框,和提交按钮。
写入如下程序:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="addHero" method="post">
名字:<input type="text" name="name"> <br>
血量:<input type="text" name="hp"> <br>
伤害:<input type="text" name="damage"> <br>
<input type="submit" value="增加 ">
</form>
</body>
</html>
2、新建类HeroAddServlet
这个类的作用是,获得addHero.html输入的数据,新建一个Hero对象,并添加到数据库的表中。
package servlet;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bean.Hero;
import dao.HeroDAO;
public class HeroAddServlet extends HttpServlet{
protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
request.setCharacterEncoding("UTF-8");
Hero hero = new Hero();//新建一个Hero对象
hero.setName(request.getParameter("name"));//从网页上获取提交的信息,name是什么,下同
hero.setHp(Float.parseFloat(request.getParameter("hp")));//因为request.getParameter()返回的是字符串,所以需要转换成float
hero.setDamage(Integer.parseInt(request.getParameter("damage")));
new HeroDAO().add(hero);//调用HeroDAO中的add()方法,把hero对象添加到数据库中
response.sendRedirect("/servlet_CURD/listHero");//添加完之后,跳转到listHero页面,显示数据库表中所有数据,看看是否添加成功
}
}
3、运行项目
右键项目名-run as-run on server...
在弹出来的界面里面输入网址http://localhost:8080/servlet_CURD/addHero.html,在弹出来的网页中输入要添加的英雄的信息。
![a788953b192fa911bfe032836d82dd8b.png](https://i-blog.csdnimg.cn/blog_migrate/4993eccdf3600c621d73bfbd7b7f3c4a.png)
然后点击添加按钮,跳转到listHero界面,如下图,可以看到添加成功。
![69e90aaa513e0f3a0210f7cec180663b.png](https://i-blog.csdnimg.cn/blog_migrate/27d575a88feb6502b37ca3c8464299a9.jpeg)
Servlet删除数据
1、修改HeroListServlet
原来访问listHero页面的显示如下,
![094f355c1a7b98ff121f48026f9e3b24.png](https://i-blog.csdnimg.cn/blog_migrate/bf53e127d809b9c10b77c50839d9a210.png)
现在想要在最右端增加一列delete,且delete在网页上是个超链,点击delete就可以删除对应的数据。
修改后的程序如下,被修改的地方已经添加了注释
package servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bean.Hero;
import dao.HeroDAO;
public class HeroListServlet extends HttpServlet{
public void service(HttpServletRequest request,HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=UTF-8");
List<Hero> heros = new HeroDAO().list();
StringBuffer sb = new StringBuffer();
sb.append("<table align='center' border='1' cellspacing='0'>rn");
//添加了一个表头<td>delete</td>
sb.append("<tr><td>id</td><td>name</td><td>hp</td><td>damage</td><td>delete</td></tr>rn");
//添加了超链<td><a href='deleteHero?id=%d'>delete</a></td>
String trFormat = "<tr><td>%d</td><td>%s</td><td>%f</td><td>%d</td><td><a href='deleteHero?id=%d'>delete</a></td></tr>rn";
for (Hero hero : heros) {
String tr = String.format(trFormat, hero.getId(), hero.getName(), hero.getHp(), hero.getDamage(), hero.getId());//又添加了一个hero.getid()
sb.append(tr);
}
sb.append("</table>");
response.getWriter().write(sb.toString());
}
}
然后右键项目名-run as-run on server...,在弹出来的界面输入网址http://localhost:8080/servlet_CURD/listHero,显示的界面如下,但是这个时候点击delete会报错,因为没有为超链delete指明跳转到什么地方,
![8667e525d340601bd94ad89129d6d9e8.png](https://i-blog.csdnimg.cn/blog_migrate/c52d1fcabda6dbe21f1a2b240661db49.jpeg)
2、编写HeroDeleteServlet类
这个类负责删除对应的数据,程序如下
package servlet;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.HeroDAO;
public class HeroDeleteServlet extends HttpServlet{
protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
//HeroListServlet中可以看到,页面上点击delete会额外返回一个id,这里使用request.getParameter()获取到这个id
int id = Integer.parseInt(request.getParameter("id"));
new HeroDAO().delete(id);//然后新建HeroDAO对象且调用这个对象的delete()方法删除这个id对应的数据
response.sendRedirect("/servlet_CURD/listHero");//删除之后跳转到listHero页面看是否删除成功
}
}
3、配置web.xml
上面两部分完成之后,在web.xml文档中要指明在网页上点击delete后执行什么操作,在xml文档中添加以下程序
<servlet>
<servlet-name>HeroDeleteServlet</servlet-name>
<servlet-class>servlet.HeroDeleteServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HeroDeleteServlet</servlet-name>
<url-pattern>/deleteHero</url-pattern>
</servlet-mapping>
全部的xml文档如下
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>HeroListServlet</servlet-name>
<servlet-class>servlet.HeroListServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HeroListServlet</servlet-name>
<url-pattern>/listHero</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HeroAddServlet</servlet-name>
<servlet-class>servlet.HeroAddServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HeroAddServlet</servlet-name>
<url-pattern>/addHero</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HeroDeleteServlet</servlet-name>
<servlet-class>servlet.HeroDeleteServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HeroDeleteServlet</servlet-name>
<url-pattern>/deleteHero</url-pattern>
</servlet-mapping>
</web-app>
4、重启tomcat,也就是右键项目名-run as-run on server...
在界面上输入网址http://localhost:8080/servlet_CURD/listHero,界面如下:
![b0a2c65036ca93b4147cab4801edae03.png](https://i-blog.csdnimg.cn/blog_migrate/e00df11f6d3fd605c3b51f7296819b04.jpeg)
点击第一个delete,删除id为10的英雄信息,执行完删除操作后会跳转到listHero页面,如下,可以看到删除成功。
![6c3705c480708d5c86e611e6f491d53f.png](https://i-blog.csdnimg.cn/blog_migrate/a5688617c411088b439bfafa37f8c39a.jpeg)
5、执行步骤解析
这个地方有点复杂,为了辅助理解,说明一下程序的执行步骤
![d309a63240507bde34ee167c373f28f0.png](https://i-blog.csdnimg.cn/blog_migrate/c0f041e9fbb1828bfe53b0f659b5770b.jpeg)
Servlet更新数据
本节目标是,在listHero中再新增一列edit,edit是一个超链,点击edit就会跳转到一个信息输入界面,把对应英雄的信息进行更新
1、修改HeroListServlet
修改HeroListServlet主要是为了增加一列edit超链,程序如下:
package servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bean.Hero;
import dao.HeroDAO;
public class HeroListServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
List<Hero> heros = new HeroDAO().list();
StringBuffer sb = new StringBuffer();
sb.append("<table align='center' border='1' cellspacing='0'>rn");
//增加一列<td>edit</td>
sb.append("<tr><td>id</td><td>name</td><td>hp</td><td>damage</td><td>edit</td><td>delete</td></tr>rn");
//增加超链<td><a href='editHero?id=%d'>edit</a></td>,执行editHero文件
String trFormat = "<tr><td>%d</td><td>%s</td><td>%f</td><td>%d</td><td><a href='editHero?id=%d'>edit</a></td><td><a href='deleteHero?id=%d'>delete</a></td></tr>rn";
for (Hero hero : heros) {
String tr = String.format(trFormat, hero.getId(), hero.getName(), hero.getHp(), hero.getDamage(),hero.getId(),hero.getId());//又增加了一个getid(),获得要编辑的英雄的id,在HeroEditServlet中可以被获得。
sb.append(tr);
}
sb.append("</table>");
response.getWriter().write(sb.toString());
}
}
![79447c73352ba3977359d323851d4189.png](https://i-blog.csdnimg.cn/blog_migrate/c17cdf651fa4f44d46791cf33e34928e.jpeg)
当然这个时候,点击edit会报错,因为没有为超链制定任何操作。
2、新建类HeroEditServlet
下面为超链指定操作,一点击超链edit就会执行HeroEditServlet中的代码。
package servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bean.Hero;
import dao.HeroDAO;
public class HeroEditServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
int id = Integer.parseInt(request.getParameter("id"));
Hero hero = new HeroDAO().get(id);//获得刚才点击edit对应的英雄信息
StringBuffer format = new StringBuffer();
response.setContentType("text/html; charset=UTF-8");
//从这里开始到</form>中间的代码是在写一个简单的网页,
format.append("<!DOCTYPE html>");
format.append("<form action='updateHero' method='post'>");//updateHero和下面的submit对应,点击submit后会执行updateHero,同时会把文本框中的内容提交给updateHero
format.append("名字 : <input type='text' name='name' value='%s' > <br>");//接下来三行都是定义在网页上显示的内容
format.append("血量 : <input type='text' name='hp' value='%f' > <br>");//要显示出来name、hp、damage,只是一个框,
format.append("伤害: <input type='text' name='damage' value='%d' > <br>");//后面的代码写要显示的信息
format.append("<input type='hidden' name='id' value='%d'>");//隐式提交这个英雄得id给updateHero
format.append("<input type='submit' value='更新'>");//点击submit后跳转到updateHero
format.append("</form>");
String html = String.format(format.toString(), hero.getName(), hero.getHp(), hero.getDamage(), hero.getId());
response.getWriter().write(html);//在文本框中写入edit对应得英雄得信息
}
}
所以,点击一个edit之后,界面显示是这样的,会把这个英雄现有的信息先显示出来,这个时候点击更新会报错,因为虽然制定了点击【更新】会去执行updateHero的代码,但是updateHero还没有写,所以会报错。
![ecd7fb1b049fc5f8dd7daa7d27cb8444.png](https://i-blog.csdnimg.cn/blog_migrate/5ed73bdf81883d10544398c0cc0ad922.png)
3、编写HeroUpdateServlet
package servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bean.Hero;
import dao.HeroDAO;
public class HeroUpdateServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
Hero hero = new Hero();
//以下4句获取刚刚从HeroEditServlet提交的信息
hero.setId(Integer.parseInt(request.getParameter("id")));
hero.setName(request.getParameter("name"));
hero.setHp(Float.parseFloat(request.getParameter("hp")));
hero.setDamage(Integer.parseInt(request.getParameter("damage")));
new HeroDAO().update(hero);//执行更新操作
response.sendRedirect("/servlet_CURD/listHero");//跳转到listHero去
}
}
比如我们点击了id为6的英雄对应的edit,跳转到了编辑页面,输入了新的信息,比如
![0dc36bb65ed152b362dd255572fed630.png](https://i-blog.csdnimg.cn/blog_migrate/f4888bb830ee78037f0276d2b3b71df2.png)
然后点击更新,可以看到跳转到新的页面,且信息被更新了
![92918fa87b3aefccb23efd4532785e86.png](https://i-blog.csdnimg.cn/blog_migrate/8fb7f95bde88b074ebbbe7dc06c654db.jpeg)