基础知识预备:
目标:
构建一个书籍管理系统,实现以下功能。
功能:
1 图书信息查询,(查)
2 书籍管理:添加书籍
3 书籍管理:修改书籍信息
4 书籍管理:删除书籍
一、预备工作
Book{
Id,
Name,
Price,
Author,
Pubdate,
}
建表:
CREATE TABLE `book` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `price` double NULL DEFAULT NULL, `author` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `pubDate` date NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;
二、书籍查询功能
在java项目中新建实体类(Book类):放于cn.piggy.entity中
package cn.piggy.entity; import java.util.Date; public class Book { private int id; private String name; private double price; private String author; private Date pubDate; //需要三种构造方法:1无参的;2不带id的,用于添加书籍时;3 带有id的,用于查询时 //1无参构造方法 public Book(){ } //2 不带id public Book(String name, double price, String author, Date pubDate) { super(); this.name = name; this.price = price; this.author = author; this.pubDate = pubDate; } //3 带有id public Book(int id, String name, double price, String author, Date pubDate) { super(); this.id = id; this.name = name; this.price = price; this.author = author; this.pubDate = pubDate; } 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 double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public Date getPubDate() { return pubDate; } public void setPubDate(Date pubDate) { this.pubDate = pubDate; } @Override public String toString() { return "Book [id=" + id + ", name=" + name + ", price=" + price + ", author=" + author + ", pubDate=" + pubDate + "]"; } }
分析功能:先做显示所有书籍的功能。
先做书籍查询功能----
由于对于书籍的操作有很多:如查询,修改,增加等与数据库交互的操作。将它们放于一个类中,放于BookDao中。
建一个Dao包,该包下放所有与数据库相关的操作。
由于需要与数据库进行连接、返回结果等操作,所以写了一个util的工具包,放于cn.piggy.util包中,其中有一个类叫做BaseDao.
BaseDao:加载jdbc驱动;实现数据库连接和关闭连接;查询,增删改SQL语句的实现。
package cn.piggy.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class BaseDao { private Connection conn; private PreparedStatement ps; private ResultSet rs; //获得连接 private void getConnection(){ try { Class.forName("com.mysql.cj.jdbc.Driver");//加载MySQL的驱动,jar包放于webroot的lib目录下 System.out.println("数据库加载成功!"); String url="jdbc:mysql://localhost:3306/booksys?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false";//booksys数据库的地址,本地,3306端口 conn = DriverManager.getConnection(url,"root","******"); System.out.println("连接成功,获取连接对象: " + conn); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } //关闭连接 public void close(){ if(rs!=null) try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } if(ps!=null) try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } if(conn!=null) try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } //更新--修改,增加,删除 //sql=insert into book(name,price,author,pubDate) values(?,?,?,?),更新时只需要传入这条sql语句即可 public int executeUpdate(String sql,Object...objects){//这里objects是不定参数,需要查资料看一下是什么 try { this.getConnection(); ps = conn.prepareStatement(sql); if(objects!=null)//设置四个参数 for(int i=0;i<objects.length;i++){ ps.setObject(i+1, objects[i]);//从1开始 } return ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { this.close(); } return -1; } //查询(查询与前面三者不同) public ResultSet executeQuery(String sql,Object...objects){ try { this.getConnection(); ps = conn.prepareStatement(sql); if((ps!=null)&(objects!=null))//设置四个参数 for(int i=0;i<objects.length;i++){ ps.setObject(i+1, objects[i]);//从1开始 } return rs = ps.executeQuery(); } catch (SQLException e) { e.printStackTrace(); } return null; } }
BookDao:继承自BaseDao,当具体的实体类(Book)需要与数据库进行交互的时候,在BookDao中实现相应的查询,增加,修改,删除功能。
编写ListServlet类
部署Servlet
1、500错误 显示语句中BaseDao的第71行if(objects!=null)有NullException的错误。一开始以为是没有判断空指针。后来分析,出现空指针的原因是 01 mysql没有连接上 02 数据库是空的 一开始以为是加载jdbc驱动失败的问题, 旧版本的驱动加载是这样写的: com.mysql.jdbc.Driver 新版本是这样的: com.mysql.cj.jdbc.Driver 修改完以后,添加一条打印语句: Class.forName("com.mysql.cj.jdbc.Driver"); System.out.println("数据库加载成功!"); 发现打印了该语句,说明并不是加载驱动失败的问题。 然后检查发现是URL写错了,booksys写成了sysbook。 2 The server time zone value '???ú±ê×??±??' is unrecognized or represents more than one time zone. 出现这个的原因是因为 mysql返回的时间总是有问题,比实际时间要早8小时。 在jdbc连接的url后面加上serverTimezone=GMT即可解决问题,如果需要使用gmt+8时区,需要写成GMT%2B8 public static final String URL="jdbc:mysql://localhost:3306/jdbc01?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false";//链接的mysql
三、书籍添加功能
思路:新建add.html,完成图书添加的操作(客户端请求,表单以post方式提交);编写AddServlet类,处理表单提交的数据,对get和post两种提交方式,有对应的doGet和doPost两种处理方式;获得表单数据以后,编写BookDao,将数据存到数据库中。
新建add.html,完成图书添加的操作。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>add.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta name="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> </head> <body> <form action="add" method="post"> <table width="80%" align="center"> <tr> <td colspan="2"><h3>添加书籍</h3>></td> </tr> <tr> <td>书名</td> <td><input type="text" name="name"/></td> </tr> <tr> <td>价格</td> <td><input type="text" name="price"/></td> </tr> <tr> <td>作者</td> <td><input type="text" name="author"/></td> </tr> <tr> <td>出版日期</td> <td><input type="text" name="pubDate"/></td> </tr> <tr> <td colspan="2" align="center"><input type="submit" name="提交"/></td> </tr> </table> </form> </body> </html>
这里存在一个乱码的问题待解决(已解决:Chrome没有utf-8,插件也不太方便安装,转用360浏览器后,编码选择utf-8就可以正常显示了;更新:在add.html的head后增加
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>add.html</title>
即可解决问题)。
下面编写AddServlet类,处理add.html提交的数据:HttpServletRequest有一个方法getParameter("fieldName"),可以获取表单提交的数据(fieldName是表单的项)。
package cn.piggy.servlet; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.piggy.dao.BookDao; import cn.piggy.entity.Book; public class AddServlet extends HttpServlet{ private BookDao bookDao = new BookDao();//BookDao.java是一个类,需要new一个对象进行保存 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); //对乱码进行处理 resp.setCharacterEncoding("utf-8"); String bookName = req.getParameter("name"); //HttpServletRequest获取表单中fieldName的方法 //System.out.println("书名:"+bookName); double price = Double.parseDouble(req.getParameter("price"));//getParameter返回的是String类型,需要转换一下 String author = req.getParameter("author"); Date pubDate = null; try { pubDate = new SimpleDateFormat("yyyy-MM-dd").parse(req.getParameter("pubDate")); //日期的格式转换 } catch (ParseException e) { e.printStackTrace(); } Book book = new Book(bookName, price, author, pubDate); if(bookDao.add(book)>0){ // resp.setContentType("text/html;charset=utf-8"); // resp.getWriter().print("添加成功!! <a href='list'>查询列表</>");//出现查询列表按钮,点击可以跳转到“list”;还可以使用重定向方法 //重定向 resp.sendRedirect("list");//response对象的该函数可以重新定向到添加书籍后的状态 }else{ resp.getWriter().print("添加失败"); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); //当以post提交时,也采用get提交,以简化操作 } }
在web.xml中增加代码,对AddServlet进行部署。
<servlet> <servlet-name>addServlet</servlet-name> <servlet-class>cn.piggy.servlet.AddServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>addServlet</servlet-name> <url-pattern>/add</url-pattern> </servlet-mapping>
在BookDao.java中添加一个查询书籍的函数,通过添加SQL语句进行添加。
package cn.piggy.dao; import java.sql.ResultSet; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import cn.piggy.entity.Book; import cn.piggy.util.BaseDao; public class BookDao extends BaseDao{ //查询出所有书籍,放到一个List中 public List<Book> getAll(){ List<Book> list = new ArrayList<Book>(); String sql="select * from book"; //查询的操作 try { ResultSet rs=this.executeQuery(sql); while(rs.next()){ list.add(new Book(rs.getInt(1),rs.getString(2),rs.getDouble(3), rs.getString(4),rs.getDate(5))); } } catch (SQLException e) { e.printStackTrace(); }finally{ this.close(); } return list; } public Book getById(int id){ String sql="select * from book where id=?"; //查询的操作 try { ResultSet rs=this.executeQuery(sql,id); if(rs.next()){ return new Book(rs.getInt(1),rs.getString(2),rs.getDouble(3), rs.getString(4),rs.getDate(5)); } } catch (SQLException e) { e.printStackTrace(); }finally{ this.close(); } return null; } //添加书籍 public int add(Book b){ String sql = "insert into book(name,price,author,pubDate) values(?,?,?,?)"; return this.executeUpdate(sql, b.getName(),b.getPrice(),b.getAuthor(), new SimpleDateFormat("yyyy-MM-dd").format(b.getPubDate()));//b.getPubDate()直接传入不行 } //修改书籍 public int update(Book b){ String sql="update book set name=?,price=?,author=?,pubDate=? where id=?"; return this.executeUpdate(sql,b.getName(),b.getPrice(),b.getAuthor(), new SimpleDateFormat("yyyy-MM-dd").format(b.getPubDate()),b.getId()); } //删除书籍 public int delete(int id){ String sql = "delete from book where id=?"; return this.executeUpdate(sql, id); } }
四、书籍修改功能
package cn.piggy.servlet; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.piggy.dao.BookDao; import cn.piggy.entity.Book; public class SelectByIdServlet extends HttpServlet { private BookDao bookDao = new BookDao(); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取id int id = 0; if(req.getParameter("id")!=null) id = Integer.parseInt(req.getParameter("id")); //根据id查询对应记录 Book book = bookDao.getById(id); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.print("<html>"); out.print("<head>"); out.print("<title>书籍列表</title>"); out.print("</head>"); out.print("<body>"); out.print("<form action='update' method='post'>"); out.print("<table width='80%' align='center'>"); out.print("<tr><td colspan='2' align='center'>修改书籍</td></tr>"); out.print("<tr>"); out.print("<td>"); out.print("书名:<input type='hidden' name='id' value='"+book.getId()+"'/>"); out.print("</td>"); out.print("<td>"); out.print("<input type='text' name='name' value='"+book.getName()+"'/>"); out.print("</td>"); out.print("</tr>"); out.print("<tr>"); out.print("<td>"); out.print("价格"); out.print("</td>"); out.print("<td>"); out.print("<input type='text' name='price' value='"+book.getPrice()+"'/>"); out.print("</td>"); out.print("</tr>"); out.print("<tr>"); out.print("<td>"); out.print("作者"); out.print("</td>"); out.print("<td>"); out.print("<input type='text' name='author' value='"+book.getAuthor()+"'/>"); out.print("</td>"); out.print("</tr>"); out.print("<tr>"); out.print("<td>"); out.print("出版日期"); out.print("</td>"); out.print("<td>"); out.print("<input type='text' name='pubDate' value='"+book.getPubDate().toLocaleString()+"'/>"); out.print("</td>"); out.print("</tr>"); out.print("<tr>"); out.print("<td colspan='2' align='center'>"); out.print("<input type='submit' value='修改'/>"); out.print("</td>"); out.print("</tr>"); out.print("</table>"); out.print("</form>"); out.print("</body>"); out.print("</html>"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub this.doGet(req, resp); } }
package cn.piggy.servlet; import java.io.IOException; import java.io.PrintWriter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.piggy.dao.BookDao; import cn.piggy.entity.Book; public class UpdateServlet extends HttpServlet { private BookDao bookDao = new BookDao();//BookDao.java是一个类,需要new一个对象进行保存 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); //对乱码进行处理 resp.setCharacterEncoding("utf-8"); int id = 0; if(req.getParameter("id")!=null) id = Integer.parseInt(req.getParameter("id")); String bookName = req.getParameter("name"); //HttpServletRequest获取表单中fieldName的方法 //System.out.println("书名:"+bookName); double price = Double.parseDouble(req.getParameter("price"));//getParameter返回的是String类型,需要转换一下 String author = req.getParameter("author"); Date pubDate = null; try { pubDate = new SimpleDateFormat("yyyy-MM-dd").parse(req.getParameter("pubDate")); //日期的格式转换 } catch (ParseException e) { e.printStackTrace(); } Book book = new Book(id,bookName,price,author,pubDate); System.out.println(book); if(bookDao.update(book)>0){ // resp.setContentType("text/html;charset=utf-8"); // resp.getWriter().print("添加成功!! <a href='list'>查询列表</>");//出现查询列表按钮,点击可以跳转到“list”;还可以使用重定向方法 //重定向 resp.sendRedirect("list");//response对象的该函数可以重新定向到添加书籍后的状态 }else{ resp.getWriter().print("修改失败"); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); //当以post提交时,也采用get提交,以简化操作 } }
package cn.piggy.servlet; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.piggy.dao.BookDao; import cn.piggy.entity.Book; public class SelectByIdServlet extends HttpServlet { private BookDao bookDao = new BookDao(); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取id int id = 0; if(req.getParameter("id")!=null) id = Integer.parseInt(req.getParameter("id")); //根据id查询对应记录 Book book = bookDao.getById(id); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.print("<html>"); out.print("<head>"); out.print("<title>书籍列表</title>"); out.print("</head>"); out.print("<body>"); out.print("<form action='update' method='post'>"); out.print("<table width='80%' align='center'>"); out.print("<tr><td colspan='2' align='center'>修改书籍</td></tr>"); out.print("<tr>"); out.print("<td>"); out.print("书名:<input type='hidden' name='id' value='"+book.getId()+"'/>"); out.print("</td>"); out.print("<td>"); out.print("<input type='text' name='name' value='"+book.getName()+"'/>"); out.print("</td>"); out.print("</tr>"); out.print("<tr>"); out.print("<td>"); out.print("价格"); out.print("</td>"); out.print("<td>"); out.print("<input type='text' name='price' value='"+book.getPrice()+"'/>"); out.print("</td>"); out.print("</tr>"); out.print("<tr>"); out.print("<td>"); out.print("作者"); out.print("</td>"); out.print("<td>"); out.print("<input type='text' name='author' value='"+book.getAuthor()+"'/>"); out.print("</td>"); out.print("</tr>"); out.print("<tr>"); out.print("<td>"); out.print("出版日期"); out.print("</td>"); out.print("<td>"); out.print("<input type='text' name='pubDate' value='"+book.getPubDate().toLocaleString()+"'/>"); out.print("</td>"); out.print("</tr>"); out.print("<tr>"); out.print("<td colspan='2' align='center'>"); out.print("<input type='submit' value='修改'/>"); out.print("</td>"); out.print("</tr>"); out.print("</table>"); out.print("</form>"); out.print("</body>"); out.print("</html>"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub this.doGet(req, resp); } }
难点:
out.print("<td>");
out.print("书名:<input type='hidden' name='id' value='"+book.getId()+"'/>");
out.print("</td>");
在SelectByIdServlet中,建立了一个表单,其中不需要显示Id。该表单向服务器提交请求。
服务器收到请求以后,在UpdateServlet中响应。UpdateServlet需要获取Id的值,所以有了上述代码。‘hidden’参数:请求中既提交了id的信息,又不会在表单中显示id。
五、最终效果:
六、附录:
知识点(包括笔记):
1 DAO:data access object数据访问对象
2 HttpServletResponse对象
3 HttpServletRequest对象
注:http协议的小知识:
客户端:浏览器;服务端:Tomcat服务器
如果表单是get提交,所提交的参数是跟在URL后的,以?name=value&price=23这样的方式追加在URL后。特点:长度有限;不安全;效率相对较高。
如果表单是post提交,那么数据将被封装在formdata里面。特点:长度没有限制;安全性高;效率相对低。
HttpServletRequest有一个方法getParameter("fieldName"),可以获取表单提交的数据(fieldName是表单的项)。
4 重定向与转发
由response.sendRedirect("list") 实现,当使用重定向时,服务器会将重新定向的地址(“list”)交给浏览器,浏览器会根据新的URL,重新发起请求。
5 JDBC
Java 数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。
简单地说,就是用于执行SQL语句的一类Java API
Base.Dao中:
public ResultSet executeQuery(String sql,Object...objects){ } //在java中实现query(查询)SQL语句 java.sql.ResultSet类型包含从数据库中查询的结果集
public int executeUpdate(String sql,Object...objects){
} //在java中实现Update(增删改)SQL语句
6 书籍管理系统中的难点分析