【Jsp】第三课 Servlet常用对象(综合案例)
本次任务是基于Spring Boot框架构建的一个图书订阅与购买管理系统。以下是系统的整体架构及主要功能:
系统架构
- 使用Spring Boot框架创建项目
- 通过ServletContext管理动态生成和删除购买记录
- 实现多步操作以确保业务逻辑正确
核心功能- Home Servlet: 实现用户登录后的主页面
- 引导用户进行两次点击操作完成注册
- 显示初始的购买图书列表页面
- Show Book Info Servlet: 显示已购图书信息列表
- 使用工具类生成多本图书数据并展示为表格形式
- Buy Book Servlet: 处理用户的购书请求
- 通过传递下标索引快速定位目标书籍
- 更新书籍下单时间和状态信息至数据库
- Alert Page: 提示购书操作完成状态
- 向用户发送刷新指令跳转至首页或继续购物
- Select Order Page: 展示用户的购书记录列表
- 根据Cookie中的数据动态更新展示内容
技术特点- 使用JSP动态传入Cookie值以保持前后端的一致性
- 避免重复查询数据库以提高效率
- 通过Cookie机制实现客户端与服务器端之间的数据交互
业务流程
- 用户登录后进入主界面并注册信息;
- 系统引导注册成功后的用户进行两次点击操作;
(第一次点击生成初始卡片号;
第二次点击生成初始密码)
然后自动跳转至初始的购物系统;
(如果没有满足条件则提示失败)
(如果注册成功则提示注册成功)
在线提交订单流程:
点击任意一本想要购买的书名所在的超链接之后,
系统会直接跳转至对应的“购买”按钮,
用户填写支付方式,
最终将支付方式存入数据库中,
并将支付结果返回给浏览器上显示出来
概述
本文主要围绕第三章中ServletContext、HttpServletRequest和HttpServletResponse等核心组件展开讨论,并详细描述了其在图书订阅系统中的应用及其功能实现。
本文主要围绕第三章中ServletContext、HttpServletRequest和HttpServletResponse等核心组件展开讨论,并详细描述了其在图书订阅系统中的应用及其功能实现。
搭建项目主页面
创建一个动态网站项目,在src中新建包com.book.servlet.
在包中,新建HomeServlet作为主页。效果图如下:

为了使访问应用根路径时自动映射到HomeServlet服务端口,默认情况下该 servlet需被配置为 web.xml 文件中的默认首页 servlet 虚拟地址。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Day07Jsp</display-name>
<welcome-file-list>
<welcome-file>HomeServlet</welcome-file>
</welcome-file-list>
</web-app>
在HomeServlet中实现超链接显示,在此需要为该Servlet设置两个静态数据字段,并采用Java注解的形式进行配置。
package com.book.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** * Servlet implementation class HomeServlet
*/
@WebServlet(urlPatterns = "/HomeServlet",
initParams = {
@WebInitParam(name = "buy",value = "购买图书"),
@WebInitParam(name = "selectOrder",value = "查看订单")
})
public class HomeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/** * @see HttpServlet#HttpServlet()
*/
public HomeServlet() {
super();
// TODO Auto-generated constructor stub
}
/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
然后,在类体内的空行处,覆盖初始化方法用于加载两个静态的数据对象。因为这两个静态的数据对象将在其他方法中被引用使用的原因,在类之外定义为全局变量存储。以下即为此处的具体实现:

再重写init方法,并通过两个静态数据,存储至全局变量。
@Override
public void init(ServletConfig config) throws ServletException {
buy=config.getInitParameter("buy");
selectOrder=config.getInitParameter("selectOrder");
}
由于浏览器访问服务器时默认采用Get请求方式,在此我们于diGet方法中编写了两个超链接并将其传递给浏览器以实现其显示效果。
/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//当浏览器访问该Servlet的时候,servlet将静态数据发给浏览器显示
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
PrintWriter pw=response.getWriter();
pw.append("<div align='center'>");
pw.append("<a href=''>"+buy+"</a> ");
pw.append("<a href=''>"+selectOrder+"</a> ");
pw.append("</div>");
}
这里运行以后,可看到以上的效果图所示的页面。
定义图书实体类
在系统中设计实体类用于存储每本书的相关数据信息,并确保每个图书对象都包含书名字段、价格字段、出版社字段以及购买时间等信息项。
新建
随后,在src文件夹内创建了一个名为com.book.entity的包,并将其用作存储所有实体类的信息库。接着右键点击文件资源管理器中的【新建
package com.book.entity;
/** * 图书的实体类
* @author teacher
* 2021/10/14
*/
public class Book {
//java类的封装
private String bookName;//书名
private String author;//作者
private String price;//单价
private String address;//出版社
private String buyTime;//购买时间
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getBuyTime() {
return buyTime;
}
public void setBuyTime(String buyTime) {
this.buyTime = buyTime;
}
//生成所有变量的get和set方法
//构造方法的作用:
//1.用于创建这个类的对象
//2.用于快速给变量进行赋值
//生成无参构造方法
public Book() {
// TODO Auto-generated constructor stub
}
//生成有参构造方法
public Book(String bookName, String author, String price, String address, String buyTime) {
super();
this.bookName = bookName;
this.author = author;
this.price = price;
this.address = address;
this.buyTime = buyTime;
}
@Override
public String toString() {
return "Book [bookName=" + bookName + ", author=" + author + ", price=" + price + ", address=" + address
+ ", buyTime=" + buyTime + "]";
}
//生成toString方法,为了在做功能的时候,
//查看检查这个对象中是否有数据
}
定义临时图书库工具类
为了暂时存储多本图书信息,在项目开发过程中
package com.book.util;
/** * 图书信息的工具类
* @author teahcer
* 2021/10/14
*用于临时存储一些图书信息
*/
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.book.entity.Book;
public class BookDataUtil {
//定义方法,用于存储多本书的信息
public List<Book> getBooks(){
Book book1=new Book("Java编程思想", "马云", "120.0元", "人民邮电出版社", "");
Book book2=new Book("MySQL数据库教程", "任正非", "89.0元", "清华大学出版社", "");
Book book3=new Book("Java疯狂讲义", "马化腾", "108.0元", "电子工业出版社", "");
Book book4=new Book("Python爬虫技术", "李彦宏", "66.0元", "新华出版社", "");
Book book5=new Book("C语言从入门到放弃", "李云龙", "56.0元", "江西出版社", "");
//创建List用于存储以上五本书
List<Book> oBooks=new ArrayList<Book>();
oBooks.add(book1);
oBooks.add(book2);
oBooks.add(book3);
oBooks.add(book4);
oBooks.add(book5);
return oBooks;
}
//获得当前实时时间
public static String getNowTime() {
//获得的现在实时时间是毫秒计算的
Date date=new Date();
//简单日期格式类 2021年10月20 日 13:55:30
SimpleDateFormat sdf=
new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
//按照设定的格式进行格式化
String time=sdf.format(date);
return time;
}
}
创建图书信息列表页面供用户购买图书
现已准备好多本图书。在此处需要创建一个名为ShowBookInfoServlet的Servlet来完成图书信息列表的页面展示。首先从工具类中获取所有图书数据,并将其以表格形式发送至浏览器以展示。其代码如下:
package com.book.servlet;
import java.io.IOException;
import java.io.PrintWriter;
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.book.entity.Book;
import com.book.util.BookDataUtil;
/** * Servlet implementation class ShowBookInfoServlet
*/
@WebServlet("/ShowBookInfoServlet")
public class ShowBookInfoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/** * @see HttpServlet#HttpServlet()
*/
public ShowBookInfoServlet() {
super();
// TODO Auto-generated constructor stub
}
/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获得所有图书信息
BookDataUtil util=new BookDataUtil();
List<Book> oBooks=util.getBooks();
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
PrintWriter pw=response.getWriter();
pw.append("<div align='center'>");
pw.append("<table border='1' style='width:800px;text-align:center;'>");
//写标题
pw.append("<tr>");
pw.append("<td>书名</td>");
pw.append("<td>作者</td>");
pw.append("<td>单价</td>");
pw.append("<td>出版社</td>");
pw.append("<td>操作</td>");
pw.append("</tr>");
for (int i=0;i<oBooks.size();i++) {
pw.append("<tr>");
pw.append("<td>"+oBooks.get(i).getBookName()+"</td>");
pw.append("<td>"+oBooks.get(i).getAuthor()+"</td>");
pw.append("<td>"+oBooks.get(i).getPrice()+"</td>");
pw.append("<td>"+oBooks.get(i).getAddress()+"</td>");
pw.append("<td><a href='BuyBookServlet?index="+i+"'><input type='button' "
+ "style='background-color:green;' "
+ "value='购买'></a></td>");
pw.append("</tr>");
}
pw.append("</table>");
pw.append("</div>");
}
/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
同时,在网站首页(即位于HomeServlet组件中的)购买图书相关的超链接将指向相应的虚拟地址。

其运行后,点击购买图书即课跳转至图书信息列表页面,效果如下:


完成存储用户购买的图书记录信息
当用户在任意一本图书页面进行下单操作时,在此过程中,我们会将书籍唯一标识码发送至服务器端,并能够迅速获取到所需书籍的信息。在此基础上,我们创建了一个名为BuyBookServlet的新Servlet类。这个类的主要职责是接收用户的书籍订单编号,并进一步查询到具体的书籍信息。并通过内部方法获取当前订单提交的时间戳,并将其保存在对应的书籍记录中。随后会将这些书籍加入到一个列表集合中。由于每位用户提供可能有多个待购书籍,在此之后又会收集更多订单数据。最后会将所有已提交的信息整合并存入到应用服务器的核心数据库中。
package com.book.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
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.book.entity.Book;
import com.book.util.BookDataUtil;
/** * Servlet implementation class BuyBookServlet
*/
@WebServlet("/BuyBookServlet")
public class BuyBookServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/** * @see HttpServlet#HttpServlet()
*/
public BuyBookServlet() {
super();
// TODO Auto-generated constructor stub
}
/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获得用于点击购买按钮发送过来的请求
//获得浏览器发送过来的图书的下标
String index=request.getParameter("index");
//将接收的字符串类型转换成int类型
int i=Integer.parseInt(index);
//根据用户发送过来的下标,去查找用户将要购买的书籍
List<Book> oBooks=new BookDataUtil().getBooks();
Book book=oBooks.get(i);
//当用户购买图书的时候,需要获得当前实时时间
book.setBuyTime(BookDataUtil.getNowTime());
//获得ServletContext对象
ServletContext sc=getServletContext();
//判断ServletContext是否存在List集合
Object object=sc.getAttribute("orders");
List<Book> oList=null;
if (object==null) {
//说明以前从来没有购买过书
oList=new ArrayList<Book>();
oList.add(book);
}else {
//以前有购买书,只需要拿到List集合继续添加购买记录即可
//不需要重新创建List集合
oList=(List<Book>) object;
oList.add(book);
}
//保存完购买记录,之后存储至ServletContext对象
sc.setAttribute("orders", oList);
//购买成功之后,跳转至提示页面
//使用请求转发跳转,因为请求转发可以携带数据跳转页面
request.setAttribute("book", book);
request.getRequestDispatcher("AlertServlet")
.forward(request, response);
}
/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
创建提示信息页面
当图书记录的信息被存储完成后,请向用户提示购买该图书的下单流程完成情况。同时,请提供是否有必要继续购买该图书的提示,并在此处创建一个新的Servlet类用于显示相关提示信息。
package com.book.servlet;
import java.io.IOException;
import java.io.PrintWriter;
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.book.entity.Book;
/** * Servlet implementation class AlertServlet
*/
@WebServlet("/AlertServlet")
public class AlertServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/** * @see HttpServlet#HttpServlet()
*/
public AlertServlet() {
super();
// TODO Auto-generated constructor stub
}
/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Book book=(Book) request.getAttribute("book");
String info="您的《"+book.getBookName()+"》购买成功,"
+ "如果继续购买请<a href='ShowBookInfoServlet'>点击这里</a>,"
+ "或者5秒之后自动跳回首页";
response.setHeader("refresh", "5;url=HomeServlet");
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
PrintWriter pw=response.getWriter();
pw.print(info);
}
/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
效果如下:


完成查看图书记录信息列表页面
在用户的购书流程完成后, 我们需要查看当前购买的所有图书的记录信息, 为此需求, 我们会新建一个Servlet类, 类名为:SelectOrderServlet, 从应用服务器中获取完整的购书记录数据, 并以表格形式呈现这些信息. 同时要求系统能够识别用户的购书状态, 其代码如下:
package com.book.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletContext;
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.book.entity.Book;
/** * Servlet implementation class SelectOrderServlet
*/
@WebServlet("/SelectOrderServlet")
public class SelectOrderServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/** * @see HttpServlet#HttpServlet()
*/
public SelectOrderServlet() {
super();
// TODO Auto-generated constructor stub
}
/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//因为用户购买的图书信息被存储在ServletContext对象中
//要展示用户的购买记录,需要先获得ServletContext对象
ServletContext sc=getServletContext();
//从该对象中获得存储图书记录的List集合
Object object=sc.getAttribute("orders");
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
PrintWriter pw=response.getWriter();
List<Book> oBooks=null;
if (object!=null) {
oBooks=(List<Book>) object;
pw.append("<div align='center'>");
pw.append("<table border='1' style='width:800px;text-align:center;'>");
//写标题
pw.append("<tr>");
pw.append("<td>书名</td>");
pw.append("<td>作者</td>");
pw.append("<td>单价</td>");
pw.append("<td>出版社</td>");
pw.append("<td>购买时间</td>");
pw.append("</tr>");
for (int i=0;i<oBooks.size();i++) {
pw.append("<tr>");
pw.append("<td>"+oBooks.get(i).getBookName()+"</td>");
pw.append("<td>"+oBooks.get(i).getAuthor()+"</td>");
pw.append("<td>"+oBooks.get(i).getPrice()+"</td>");
pw.append("<td>"+oBooks.get(i).getAddress()+"</td>");
pw.append("<td>"+oBooks.get(i).getBuyTime()+"</td>");
pw.append("</tr>");
}
pw.append("</table>");
pw.append("</div>");
}else {
pw.print("当前还没有购买图书的记录,请先购买再查看!!!");
}
}
/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
并把给Servlet的虚拟地址添加至主页面的第二个超链接上,

其运行的效果如下:


全文至此结束。对于新手用户而言,通过参考代码实现上述功能后,默认情况下系统会保存所有图书信息;然而,在需要时,默认状态下无法删除购买记录
