jsp-servlet(2)响应HTML文档-书籍管理系统

基础知识预备:

 目标:

构建一个书籍管理系统,并且部署到GitHub上。

功能:

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.jdbc.Driver");//加载MySQL的驱动,jar包放于webroot的lib目录下 String url="jdbc:mysql://localhost:3306:/booksys";//booksys数据库的地址,本地,3306端口 conn = DriverManager.getConnection(url,"root","qyzSQL"); } 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(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; } }

BaseDao

 

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%2B8public 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数据访问对象

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 书籍管理系统中的难点分析

 

 

 

 

相关文章