详情模块-公告详情
需要的资源
链接: https://pan.baidu.com/s/1BiSSWcxTpwF-YLH9GTGNyw .
提取码:m71z
思路
前台:
- 由于新闻详情、公告详情和商品详情的页面布局一样,只是显示的内容不同,为了节省工作量,可以将notice.jsp里的主要代码进行复用。所以第一步将拷贝至WebContent文件夹下的notice.jsp文件重命名为details.jsp(资源已给)
- details.jsp文件中动态包含notice.jsp
- 通过EL表达式从域对象中获取公告信息
- index.jsp中设置公告链接的路径
后台:
-
建一个NoticeServlet
-
接收参数id
-
非空判断
空则无操作
不空,调用service通过id查询公告详情notice -
公告详情不需要一直保留在会话中,考虑服务器性能,所以将pageName、changePage和notice存在作用域request中
-
请求转发跳转details.jsp
实操
- 将notice.jsp文件拷贝至WebContent文件夹下,文件重命名为details.jsp。
- 重写details.jsp的代码
details.jsp文件更新代码
...
<!-- 用参数pageName 来标示当前小模块标题 -->
<title>易买网 - ${
pageName }</title>
</head>
<body>
<!-- 头部 -->
<div id="header" class="wrap">
<jsp:include page="common/top.jsp" />
</div>
<div id="position" class="wrap">
<!-- 文字的导航 -->
<!-- 用参数pageName 来标示当前小模块标题 -->
您现在的位置:<a href="index">首页</a> > ${
pageName }详情
</div>
<div id="main" class="wrap">
<div class="lefter">
<jsp:include page="common/left.jsp" />
</div>
<!-- 动态包含页面 (公告详情,新闻详情,商品详情)-->
<!-- 用参数changePage来标示去哪个小模块的详情内容-->
<jsp:include page="${changePage }"></jsp:include>
<div class="clear"></div>
</div>
...
- 在WebContent文件夹下新建一个notice文件夹,并在文件夹里新建一个notice.jsp文件来专门完成公告详情代码。
notice.jsp文件代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<div class="main">
<div id="notice" class="right-main">
<h1>${
notice.title }</h1>
<div class="content" style="word-wrap: break-word;word-break: break-all;overflow: hidden;">
${
notice.content }
</div>
</div>
</div>
- index.jsp文件中设置不同公告链接的路径
index.jsp文件相关更新代码
...
<div class="side">
<div class="news-list">
<h4>最新公告</h4>
<ul>
<!-- 循环遍历存放最新公告信息的<li>标签,过程中动态获取最新公告信息,最多显示7条 -->
<c:forEach items="${noticeList }" var="notice" end="6">
<li>
<!-- 从后台用id查公告内容,所以要向负责详情的Servlet传一个id值 -->
<a href="notice?id=${notice.id }">${
notice.title }</a>
</li>
</c:forEach>
</ul>
</div>
...
-
新建一个NoticeServlet
右击com.xxx.servlet包⇥New⇥servlet⇥ClassName填写NoticeServlet⇥next⇥URL mappings栏下修改路径名为notice⇥next⇥取消勾选Constructors from supclass、doPost和doGet,勾选service⇥Finish -
NoticeServlet.java文件里完成功能代码
NoticeServlet.java文件代码
@WebServlet("/notice")
public class NoticeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
//之前写过NoticeService和NoticeServiceImpl文件所以不报红,但是需要去NoticeServiceImpl文件里添加一下下面的findNoticeById方法
private NoticeService noticeService = new NoticeServiceImpl();
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//接收参数id
String id = request.getParameter("id");
//非空判断
if(StringUtil.isEmpty(id)){
//空则无操作
return;
}
//不空,调用service通过id查询公告详情notice
Notice notice = noticeService.findNoticeById(Integer.parseInt(id)); //findNoticeById报红添加一下方法,跳转的文件中将parseInt参数改为id
//公告详情不需要一直保留在会话中,考虑服务器性能,所以将pageName、changePage和notice存在作用域request中
//用户访问公告详情时标题显示公告
request.setAttribute("pageName", "公告");
request.setAttribute("changePage", "notice/notice.jsp");
request.setAttribute("notice", notice);
//请求转发跳转details.jsp
request.getRequestDispatcher("details.jsp").forward(request, response);
//写完后有报红,ctrl+shift+o先自动导一下包
}
}
- NoticeServiceImpl.java文件里写一下方法代码:
NoticeServiceImpl.java文件findNoticeById方法:
...
//写在查询公告集合方法后面
//通过Id查询公告
@Override
public Notice findNoticeById(int id) {
// TODO Auto-generated method stub
Notice notice = null;
Connection conn = null;
//异常
try{
//数据库操作
//建立连接
conn = DBUtil.getConnection();
//编写sql语句
String sql = "select * from t_notice where id = ?";
//new一个QueryRunner
QueryRunner qr = new QueryRunner();
//创建参数数组
Object[] params = {
id};
//执行查询
notice = qr.query(conn, sql ,new BeanHandler<>(Notice.class),params);//BeanHandler报红导一下包
} catch (Exception e){
e.printStackTrace();
}finally{
//关闭连接
DBUtil.close(null, null, conn);
}
return notice;
}
...
这样,公告详情模块就写完了。
详情模块-商品详情
思路
前台:
- details.jsp文件中动态包含product.jsp
- 通过EL表达式从域对象中获取商品信息
- index.jsp中设置商品链接的路径
后台:
-
建一个ProductServlet
-
判断用户行为
-
接收参数
-
非空判断
空则无操作
不空,调用service通过id查询商品详情product -
公告详情不需要一直保留在会话中,考虑服务器性能,所以将pageName、changePage和product存在作用域request中
-
请求转发跳转details.jsp
实操
- 在WebContent文件夹下新建一个product文件夹,并在文件夹里新建一个product.jsp文件来专门完成商品详情代码。
product.jsp文件代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<div id="product" class="main">
<h1>${
product.name }</h1>
<div class="infos">
<div class="thumb">
<img class="img" src="${product.proPic }" />
</div>
<div class="buy">
<br/>
<p>
商城价:<span class="price">${
product.price }</span>
</p>
<p>库 存:${
product.stock }</p>
<br/>
<div class="button">
<input type="button" name="button" value=""/><br/>
<a href="">放入购物车</a>
</div>
</div>
<div class="clear"></div>
</div>
<div class="introduce">
<h2>
<strong>商品详情</strong>
</h2>
<div class="text">
${
product.description }
</div>
</div>
</div>
- index.jsp中设置商品链接的路径
index.jsp文件相关更新代码:
...
<h2>今日特价</h2>
<ul class="product clearfix">
<!-- 循环遍历存放今日特价商品信息的<li>标签 -->
<c:forEach items="${specialProductList }" var="specialProduct" end="7">
<li>
<dl>
<dt>
<!-- 从后台用id查商品详情,所以要向负责商品详情的Servlet传一个id值 -->
<a href="product?id=${specialProduct.id }" target="_blank"><img src="${specialProduct.proPic }" /></a>
</dt>
<dd class="title">
<a href="product?id=${specialProduct.id }" target="_blank">${
specialProduct.name }</a>
</dd>
<dd class="price">¥${
specialProduct.price}</dd>
</dl>
</li>
</c:forEach>
</ul>
</div>
...
<h2>热卖推荐</h2>
<ul class="product clearfix">
<li>
<dl>
<dt>
<!-- 从后台用id查商品详情,所以要向负责商品详情的Servlet传一个id值 -->
<!-- 热卖模块留在最后写,所以这里的商品是定死的 ,且热卖模块暂时不可用-->
<a href="product?id=${hotProduct.id }" target="_blank"><img src="images/product/5.jpg" /></a>
</dt>
<dd class="title">
<a href="product?id=${hotProduct.id }" target="_blank">优衣库2019春装新款中腰蓝色刺绣修身</a>
</dd>
<dd class="price">¥78</dd>
</dl>
</li>
</ul>
...
-
新建一个ProductServlet
右击com.xxx.servlet包⇥New⇥servlet⇥ClassName填写ProductServlet⇥next⇥URL mappings栏下修改路径名为product⇥next⇥取消勾选Constructors from supclass、doPost和doGet,勾选service⇥Finish -
ProductServlet.java文件里完成功能代码
ProductServlet.java文件代码
@WebServlet("/product")
public class ProductServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
private ProductService productService = new ProductServiceImpl();
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//判断用户行为
String action = request.getParameter("action");
if("".equals(action)){
}else{
//商品详情
details(request,response); //details报红创建一下方法
}
}
//商品详情
private void details(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//接收参数
String id = request.getParameter("id");
//非空判断
if(StringUtil.isEmpty(id)){
//空则无操作
return;
}
//不空,调用service通过id查询商品详情product
Product product = productService.findProductById(Integer.parseInt(id)); //findProductById报红生成一下方法,跳转的文件中将parseInt参数改为id
//详情不需要一直保留在会话中,考虑服务器性能,所以将pageName、changePage和product存在作用域request中
//用户访问商品详情时标题商品公告
request.setAttribute("pageName", "商品");
request.setAttribute("changePage", "product/product.jsp");
request.setAttribute("product", product);
//请求转发跳转details.jsp
request.getRequestDispatcher("details.jsp").forward(request, response);
}
}
- ProductServiceImpl.java文件里写一下方法代码:
ProductServiceImpl.java文件findProductById方法:
...
//写在查询今日特价商品集合方法后面
//通过id查询商品详情
@Override
public Product findProductById(int id) {
// TODO Auto-generated method stub
Product product = null;
Connection conn = null;
//异常
try{
//数据库操作
//建立连接
conn = DBUtil.getConnection();
//编写sql语句
String sql = "select * from t_product where id = ?";
//new一个QueryRunner
QueryRunner qr = new QueryRunner();
//创建参数数组
Object[] params = {
id};
//执行查询
product = qr.query(conn, sql ,new BeanHandler<>(Product.class),params);//BeanHandler报红导一下包
} catch (Exception e){
e.printStackTrace();
}finally{
//关闭连接
DBUtil.close(null, null, conn);
}
return product;
}
...
做完后保存文件,重启服务器,再刷新网页,当我们点击今日特价里的商品图片或者文字时,就可以访问商品的详细信息啦。
详情模块-商品详情-最近浏览
思路
此功能后台写在商品详情小模块里的调用service通过id查询商品详情product这一步骤后面。
前台:
- WebContent文件夹的子文件夹common下找到left.jsp文件
- 循环遍历获取最新浏览商品
后台:
-
依旧是在ProductServlet.java文件里完成功能
-
从Session中获取最近浏览商品集合
-
非空判断
空,创建集合 -
不为空,
循环遍历最近浏览商品集合,先判断是不是浏览同一件商品 -
如果是同一件商品,把浏览的这一件商品放在集合最前。
-
如果不是再判断是否有4个商品(最近浏览最多显示四个)
如果有4个商品,移除最后一个,把浏览的这个商品放在最前
如果没有4个商品,就把浏览的这个商品放在最前 -
存Session,覆盖集合
实操
- left.jsp文件中修改最近浏览的相关代码
left.jsp文件相关代码:
...
<h2>最近浏览</h2>
<dl class="clearfix">
<!-- 循环遍历<dt>和<dd>标签 -->
<c:forEach items="${recentProductList }" var="recentProduct">
<dt>
<a href="product?id=${recentProduct.id }" target="_blank"><img src="${recentProduct.proPic }" class="imgs" style="height: 50px;width: 50px;"></a>
</dt>
<dd>
<a href="product?id=${recentProduct.id }" target="_blank">${
recentProduct.name }</a>
</dd>
</c:forEach>
</dl>
...
- ProductServlet.java文件更新代码:
...
//不空,调用service通过id查询商品详情product
Product product = productService.findProductById(Integer.parseInt(id)); //findProductById报红生成一下方法,跳转的文件中将parseInt参数改为id
/**
* 最近浏览功能
*/
//从Session中获取最近浏览商品集合
List<Product> recentProductList = ((List<Product>) request.getSession().getAttribute("recentProductList"));
//非空判断
if(recentProductList == null){
//空,创建集合
recentProductList = new LinkedList<>();
}
//写一个标记
boolean flag = true;
//不为空,
//循环遍历最近浏览商品集合
//先判断是不是浏览同一件商品
for(Product recentProduct : recentProductList){
if(Integer.parseInt(id) == recentProduct.getId()){
//是同一件商品,改一下标记
flag = false;
//先删除原来的浏览记录
recentProductList.remove(recentProduct);
//再把浏览的这一件商品放在集合最前。
recentProductList.add(0, recentProduct);
break;
}
}
if(flag){
//不是
//再判断是否有4个商品(最近浏览最多显示四个)
if(recentProductList.size() == 4){
//有4个商品,移除最后一个,把浏览的这个商品放在最前
recentProductList.remove(3);
recentProductList.add(0, product);
}else{
//如果没有4个商品,就把浏览的这个商品放在最前
recentProductList.add(0, product);
}
}
//存Session,覆盖集合
request.getSession().setAttribute("recentProductList", recentProductList);
//详情不需要一直保留在会话中,考虑服务器性能,所以将pageName、changePage和product存在作用域request中
...
完成以上代码,最近浏览功能也就做完了。点击没一件商品时,右下角的最近浏览第一个都会显示最新浏览的商品,第二个显示上一个浏览的商品,最多显示4个。在里面点击也可以跳转商品详情,贴上成功图(PS:我的今日特价商品因为数据库表的数据时间到了,商品变得很少,所以我干脆给他们的特价时间改到了明年,这样就一直有商品了):
下一篇继续写详情模块的查看留言和发表留言。