【左京淳的JAVA WEB学习笔记】第十一章 显示列表、图片、商品细节

显示列表

访问案例网站时默认调用index.jsp,在此页面设定转向MainSvl。
http://localhost:8080/BookShop
新建index.jsp

<%request.getRequestDispatcher("/MainSvl").forward(request, response);%>

新建MainSvl(控制层)

@WebServlet("/MainSvl")public class MainSvl extends HttpServlet {    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {      BookBiz biz = new BookBiz();      try {        List<TBook> books = biz.getAllBooks();        request.setAttribute("books", books);        request.getRequestDispatcher("/WEB-INF/main/main.jsp").forward(request, response);      }catch(Exception e){        request.setAttribute("msg", "网路异常,请跟网站管理员联繫。");        request.getRequestDispatcher("/error.jsp").forward(request, response);      }    }  (余略)}

新建BookBiz(服务层)

public class BookBiz {  public List<TBook> getAllBooks() throws Exception{    IBookDao dao = new BookDaoMysql();    try {      return dao.getAllBooks();    }finally{      dao.closeConnection();    }  }}

新建BookDaoMysql(持久层:负责DB访问)

public class BookDaoMysql extends BaseDao{  public List<TBook> getAllBooks() throws Exception{    List<TBook> books = null;    String sql = "select isbn,name,press,price,pdate from tbook order by isbn";    //从BaseDao取得connection = DriverManager.getConnection(dbInfo.getUrl(), dbInfo.getUname(), dbInfo.getPwd());    this.openConnection();     PreparedStatement ps = this.connection.prepareStatement(sql);    ResultSet rs = ps.executeQuery();    if(rs != null) {      books = new ArrayList<TBook>();      //当rs里面还有下一件资料时      while(rs.next()) {        //把取出的资料都保存到TBook物件中        TBook bk = new TBook();        bk.setBname(rs.getString("bname"));        bk.setIsbn(rs.getString("isbn"));        bk.setPdate(rs.getString("Pdate"));        bk.setPress(rs.getString("press"));        bk.setPrice(rs.getString("price"));        //将TBook物件加入列表        books.add(bk);      }    }    return books;

记忆重点

使用DriverManager取得connection使用connection内的prepareStatement(sql)装载sql文使用connection内的executeQuery()发送sql文并取得resultSet使用迴圈将resultSet的资料保存至javaBean物件中,并将物件加入列表。由服务层呼叫closeConnection()

在JSP页面显示列表

使用JSTL的<c:forEath>标籤即可简单取出列表
var为保存资料用的变数名(可自取),items为资料来源列表的名字。

<table border="1" width=100%>  <c:forEach var="bk" items="${books }">    <tr>      <td rowspan=3>        <img width=100 height=100 src="<%=basePath%>BookPicSvl?isbn=${bk.isbn }">      </td>      <td colspan=2 align=center style="color:red">        <a href="<%=basePath%>BookDetailSvl?isbn=${bk.isbn }">${bk.bname }</a>      </td>    </tr>    <tr><td>商品价格</td><td>${bk.price }</td></tr>    <tr><td>出版社</td><td>${bk.press }</td></tr>  </c:forEach></table>

在这个案例中,使用了标籤和<%=basePath%>,这两个部分是常用的代码,可以抽取出来放在base.jsp页面中。
使用以下指令进行静态引用

<%@include file ="/WEB-INF/base.jsp" %>

另外一种引用方法为动态引用,不过动态引用就无法取得base页面里的变数。得要在页面静态编译时便建立好变数才能引用。
<jsp:include page="/WEB-INF/base.jsp"></jsp:include>

c标籤也有引用页面的import方法

<c:import url="base.jsp"></c:import>

不过这样做的话就必须先加载以下标籤库

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

在本案例中标籤库的加载交给base页面做了,所以选择include file指令更方便。

显示图片

当用户进行下载图片等比较耗时的处理,可以使用NIO(非阻塞流)技术(一种异步处理技术)。

新建BookPicSvl并开启支援异步模式。

@WebServlet(urlPatterns="/BookPicSvl",asyncSupported=true)public class BookPicSvl extends HttpServlet {    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{      String isbn = request.getParameter("isbn");      if(isbn == null) {        throw new RuntimeException("isbn不能为空");      }      BookBiz biz = new BookBiz();      try {        byte[] pic = biz.getBookPic(isbn);        if(pic != null) {          AsyncContext acontext = request.startAsync();          ServletOutputStream out = acontext.getResponse().getOutputStream();          out.setWriteListener(new MyPicWriter(out,acontext,pic));        }      }catch(Exception e){        Log.logger.error(e.getMessage(), e);        request.setAttribute("msg", "网路异常,请检查。");        request.getRequestDispatcher("/error.jsp").forward(request, response);      }    }(余略)}

记忆重点

使用request.startAsync(),取得AsyncContext物件。使用acontext.getResponse().getOutputStream(),取得ServletOutputStream物件。使用out.setWriteListener(new MyPicWriter(out,acontext,pic)),将刚取得的AsyncContext物件、ServletOutputStream物件及欲处理资料都丢进WriteListener进行处理。

新建MyPicWriter

public class MyPicWriter implements WriteListener {  private ServletOutputStream out;  private AsyncContext ac;  private byte[] pic;    public MyPicWriter(ServletOutputStream out,AsyncContext ac,byte[] pic) {    this.ac = ac;    this.out = out;    this.pic = pic;  }    @Override  public void onError(Throwable t) {    t.printStackTrace();  }  @Override  public void onWritePossible() throws IOException {    try {      if(pic != null && out.isReady()) {        out.write(pic);        //out.flush(); --此处不能使用flush        out.close();      }    }catch(Exception e){      e.printStackTrace();    }finally {      ac.complete();    }  }}

记忆重点

当图片资料不为空,且输出流已经準备好时,使用write(pic)将资料写出后关闭输出流。最后关闭异步处理物件。

服务层的动作

public class BookBiz {  public byte[] getBookPic(String isbn) throws Exception{    IBookDao dao = new BookDaoMysql();    try {      return dao.getBookPic(isbn);    }finally{      dao.closeConnection();    }  }}

DAO层的动作

public class BookDaoMysql extends BaseDao{  public byte[] getBookPic(String isbn) throws Exception{    byte[] pic = null;    String sql = "select pic from tbook where isbn = ?";    this.openConnection();     PreparedStatement ps = this.connection.prepareStatement(sql);    ps.setString(1, isbn);    ResultSet rs = ps.executeQuery();    if(rs != null) {      while(rs.next()) {        pic = rs.getBytes("pic");        break;      }    }    rs.close();    ps.close();    return pic;  }}

利用特定条件取得资料时,SQL文内会放置"?"佔位符。跟取得全部列表时不一样。
当SQL文内有佔位符时,依照其数量,使用PreparedStatement物件的setString(index, value)将值代入;
例如ps.setString(1, isbn);,意思是将isbn变数内的值代入第一个佔位符内。

使用while迴圈来确保至少有一行资料,然后将其读取。
疑问:之前的教材中没有关闭rs和ps,不知道为什么。

jsp页面的设置

在main.jsp和BookDetail.jsp中,使用标籤来请求图片的数据流。

<img src="<%=basePath%>BookPicSvl?isbn=${bk.isbn}"/>

商品细节页面

在首页列表中点击任一商品之后,跳转到商品细节页面。连结长得像下面这样
http://localhost:8080/BookShop/BookDetailSvl?isbn=is001

新建BookDetailSvl

@WebServlet("/BookDetailSvl")public class BookDetailSvl extends HttpServlet {    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {      String isbn = request.getParameter("isbn");      if(isbn == null) {        throw new RuntimeException("isbn不能为空");      }            BookBiz biz = new BookBiz();      try {        TBook book = biz.getBookDetail(isbn);        request.setAttribute("book", book);        request.getRequestDispatcher("/WEB-INF/main/BookDetail.jsp").forward(request, response);      }catch(Exception e){        Log.logger.error(e.getMessage(),e);        request.setAttribute("msg", "网路异常,请跟网站管理员联繫。");        request.getRequestDispatcher("/error.jsp").forward(request, response);      }    }}

记忆重点

Servlet负责呼叫service层取得资料。将资料存进request物件里。带着资料,转发到目标页面。

服务层
新增getBookDetail(isbn)方法

  public TBook getBookDetail(String isbn) throws Exception{    IBookDao dao = new BookDaoMysql();    try {      return dao.getBookDetail(isbn);    }finally{      dao.closeConnection();    }  }

DAO层
新增getBookDetail(String isbn)方法

  public TBook getBookDetail(String isbn) throws Exception{    TBook book = null;    String sql = "select isbn,bname,press,price,pdate from tbook where isbn = ?";    this.openConnection();     PreparedStatement ps = this.connection.prepareStatement(sql);    ps.setString(1, isbn);    ResultSet rs = ps.executeQuery();    if(rs != null) {      while(rs.next()) {        book.setBname(rs.getString("bname"));        book.setIsbn(rs.getString("isbn"));        book.setPdate(rs.getString("Pdate"));        book.setPress(rs.getString("press"));        book.setPrice(rs.getString("price"));        break;      }    }    return book;  }

BookDetail.jsp页面

(前略)<table border="1" width=100%>  <tr>    <td rowspan=3>      <img width=100 height=100 src="<%=basePath%>BookPicSvl?isbn=${book.isbn }">    </td>    <td colspan=2 align=center style="color:red">      ${book.bname }    </td>  </tr>  <tr><td>商品价格</td><td>${book.price }</td></tr>  <tr><td>出版社</td><td>${book.press }</td></tr>  <tr><td height=300 colspan=3>图书简介</td></tr>  <tr><td colspan=3 align="center">    <a href="<%=basePath%>user/ShopCarAddSvl?isbn=${book.isbn }">加入购物车</a>&nbsp;    <a href="<%=basePath%>MainSvl">返回</a>    </td>  </tr></table>

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章