尚硅谷网上书城项目总结

第一阶段:登录、注册的验证

1.使用jQuery技术对登录中的用户名、密码进行非空验证

      思路:1.给提交按钮设置绑定点击事件

                 2.获取用户框中的值进行非空判断:如果为空进行输出语句+return false(使提交表单之后不再跳转页面)

      代码如下:

       1.表单提交按钮的输入框代码和登录注册的输入框代码:

<input type="submit" value="登录" id="sub_btn" />
<input class="itxt" type="text"  placeholder="请输入用户名" autocomplete="off"  tabindex="1" name="username" id="username"  value="${empty param.username?"":param.username}"<!-- 用来设置数据的回显--> />
 <input class="itxt" type="password" placeholder="请输入密码" autocomplete="off" tabindex="1" name="password" id="password"/>
                  
                  
                  
                  
                  
                  
                

        2.给登录和密码设置点击事件

$(function () {
        //给登录设置点击事件
        $("#sub_btn").click(function () {
          //获取用户输入框的值
          var usernameval = $("#username").val();
          if (usernameval==""){
            alert("用户名不能为空");
            return false;
          }
          //获取密码框的值
          var pwdval = $("#password").val();
          if (pwdval==""){
            alert("密码框不能为空");
            return false;
          }
        });

      });

2.使用jQuery技术和正则表达式对注册中的用户名、密码、确认密码、邮箱进行格式验证,对验证码进行非空验证。

      思路同第一步

        代码如下:

        

  $(function () {
        //‘给提交按钮设置点击事件
        $("#btn").click(function () {
          //获取用户输入的内容
          var userNameTest = $("#username").val();
          //判断用户输入的正则表达式
          var testuser=/^[a-z0-9_-]{3,16}$/;
          //进行判断
          var userpanduan = testuser.test(userNameTest);
          if (!userpanduan){
            $("#usermsg").text("请输入3到16位的字母、数字、下划线、减号组合的用户名");
            return false;
          }
          //获取密码框的值
          var passwordtest = $("#password").val();
          //密码正则表达式
          var testpassword=/^[a-z0-9_-]{6,18}$/;
          //判断输入的密码是否符合
          var passwordpanduan = testpassword.test(passwordtest);
          if (!passwordpanduan){
            // alert("密码输入格式不对");
            $("#pwdmsg").text("密码输入格式不对");
            return false;
          }
          //获取确认密码的文本框的值
          var repwd = $("#repwd").val();
          if (repwd!=passwordtest){
            // alert("确认密码错误,请重新输入");
            $("#repwdmsg").text("确认密码错误,请重新输入");
            //设置确认密码框的内容为空
            $("#repwd").val("");
            return false;
          }
          //获取用户邮箱的值
          var emailval = $("#email").val();
          //设置邮箱的正则表达式
          var emailzhengze=/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
          //进行输入邮箱的判断
          if (!emailzhengze.test(emailval)){
            // alert("输入邮箱格式错误,请重新输入");
            $("#emailmsg").text("输入邮箱的格式错误,请重新输入");
            return false;
          }
          //获取验证码框内的值
          var codeval = $("#code").val();
          if (codeval==""){
            alert("验证码不能为空");
            return false;
          }

        });

第二阶段:实现登录、注册功能 

小tip:软件中的三层架构:表示层<-->业务逻辑层<-->数据访问层

优势:结构清晰,耦合度降低,可维护性高,可扩展性高,利于开发任务同步进行,容易适应需求变化

书层的三层架构:

表示层:HTML、Servlet.接收用户的请求,调用业务逻辑层处理用户的请求,显示处理的结果

业务逻辑层:Service,调用数据访问层处理业务逻辑,采用面向接口编程的思想,先定义接口,再创建实现类

采用面向接口编程的思想,先定义接口,再创建实现类

思路:

1.创建baseServlet,在该Servlet里面从页面form表单获取执行方法名字的参数,利用反射的形式将这个方法执行,注意:这里获取到的参数名必须和在Servelt中要创建的方法名称一样。

2.创建userDao和它的实现类,在dao中写数据库然后Service层调用dao中的方法,最后传到Servlet执行判断

代码:

1.baseServlet的创建:

public class BaseServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //在第一次获取页面参数前设置乱码问题
        request.setCharacterEncoding("UTF-8");
        String methName = request.getParameter("way");

//         if ("login".equals(request.getParameter("way"))){
//            //证明在登录,调用当前类中的login方法
//            login(request,response);
//        }else if ("regist".equals(request.getParameter("way"))){
//            //证明在注册,调用当前类中的regist方法
//            regist(request,response);
//        }
        Method method = null;

        try {
            method = this.getClass().getDeclaredMethod(methName, HttpServletRequest.class, HttpServletResponse.class);
            //设置访问权限
            method.setAccessible(true);
            //调用方法
            method.invoke(this, request, response);
        } catch (Exception e) {
            //在baseDao往上抛异常的过程中,抛到servlet然后servlet再抛到baseServlet,通过baseservlet再往过滤器中抛异常
//            e.printStackTrace();
            throw new RuntimeException();
        }

    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }
}

2.创建UserDao及其实现类

 创建UserDao:

public interface UserDao {
    /**
     * 通过username,password向数据库中查询一条记录
     * @param username 传入的username
     * @param password 传入的password
     * @return User对象:存在
     *         null:不存在
     */
    User logincheck(String username,String password);

    /**
     * 通过username在数据库中查询出一条数据
     * @param username 传入的username
     * @return true:说明数据库中存在数据
     *         false:说明数据库中不存在数据
     */
    boolean isExistUsername(String username);

    /**
     * 向数据库中添加数据
     * @param username 传入的username
     * @param password 传入的password
     * @param email 传入的email
     */
    void addUser(String username,String password,String email);

}

创建它的实现类UserDaoImpl:

public class UserDaoImpl extends BaseDao<User> implements UserDao {
    @Override
    public User logincheck(String username, String password) {
        String sql="select id,username,password,email from users where username=? and password=?";
        User user=getBean(sql,username,password);
        return user;
    }

    @Override
    public boolean isExistUsername(String username) {
//获取baseDao中获取一个对象的方法
        String sql="select id,username,password,email from users where username=?";
        User user=getBean(sql,username);
        if (user!=null){
            return true;
        }else {
            return false;
        }
    }

    @Override
    public void addUser(String username, String password, String email) {
        String sql="insert into users(username,password,email) values(?,?,?)";
        update(sql,username,password,email);
    }
}

 3.创建service及其实现类

创建UserService

public interface UserService {
    //用于登录判断
    User login(User user);
    //用于注册判断
    boolean regist(User user);
    //用于添加数据
    void addUser(User user);
}

创建它的实现类

public class UserServiceImpl  implements UserService {
    UserDao userDao=new UserDaoImpl();
    @Override
    public User login(User user) {
        return userDao.logincheck(user.getUsername(),user.getPassword());
    }

    @Override
    public boolean regist(User user) {
     return userDao.isExistUsername(user.getUsername());
    }

    @Override
    public void addUser(User user) {
        userDao.addUser(user.getUsername(),user.getPassword(),user.getEmail());
    }
}

4.创建Useservlet继承BaseServlet,通过BaseServlet的反射将Userservlet中的login和regist方法执行

@WebServlet(name = "UserServlet",urlPatterns = "/UserServlet")
public class UserServlet extends BaseServlet {
    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建userservice的实现类的对象
        UserService userService=new UserServiceImpl();
        //获取从页面传来的username,password
        String username=request.getParameter("username");
        String password=request.getParameter("password");
        //封装进User
        User user=new User(null,username,password,null);
        //调用userservice实现类的重写方法得到User对象进行判断
        User loginuser=userService.login(user);
        if (loginuser!=null){
            //查询到数据,用户名密码正确
            //创建session
            HttpSession session = request.getSession();
            //将loginuser添加到session域中
            session.setAttribute("user",loginuser);
            // ,重定向到成功页面
            response.sendRedirect(request.getContextPath()+"/pages/user/login_success.jsp");
        }else {
            //设置域
            request.setAttribute("msg","密码错误请重新输入");
            //未查询到数据,转发到登录页面
            request.getRequestDispatcher("/pages/user/login.jsp").forward(request,response);
        }
    }
    protected void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取userservice的实现类对象
        UserService userService= new UserServiceImpl();
        //获取页面传过来的username,password,email
        String username=request.getParameter("username");
        String password=request.getParameter("password");
        String email=request.getParameter("email");
        //获取输入框验证码的值
        String inputcode = request.getParameter("code");
        //获取session域中的验证码的值
        HttpSession session = request.getSession();
        String sessioncode = (String) session.getAttribute("code");
        if (inputcode.equals(sessioncode)){
            //验证码正确,清除session
            session.removeAttribute("code");
            //封装进User对象
            User user=new User(null,username,password,email);
            //调用Userservice实现类的方法获得对象进行判断
            boolean isflag= userService.regist(user);
            if (isflag){
                //返回true:数据库中存在用户
                //转发到regist.html页面
                request.setAttribute("msg","已存在用户,请重新输入");
                request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response);
            }else {
                //返回false:数据库中没有数据,进行添加操作

                userService.addUser(user);
                //注册成功重定向跳入regist_success.html页面
                response.sendRedirect(request.getContextPath()+"/pages/user/regist_success.jsp");
            }
        }
        else {
            //验证码不正确
            request.setAttribute("msg","验证码错误");
            //请求转发到注册页面
            request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response);
        }
    }
}

第三阶段:动态书城的开始及局部优化

思路:

代码:

动态获取base标签:

1.在WEB-INF下创建一个include目录,将base.jsp放入include目录中,包含base标签

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<base href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">

2.在每个页面合适的地方使用静态包含

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

显示错误消息并表单回显:

登录:

1.在UserServlet中的login方法中如果登录失败设置错误消息保存到request域中

 //设置域
            request.setAttribute("msg","密码错误请重新输入");
            //未查询到数据,转发到登录页面
            request.getRequestDispatcher("/pages/user/login.jsp").forward(request,response);

2.并在login.jsp页面从request域中获取到数据显示在页面上:

<div class="msg_cont">
              <b></b>
              <span class="errorMsg">${empty requestScope.msg?"请输入用户名和密码":requestScope.msg}</span>
 </div>

3.登录失败之后将用户名回显在表单中,用户input中设置属性:

value="${empty param.username?"":param.username}"

注册:

1.在UserServlet中的regist方法如果数据库中存在用户,设置request域将错误的信息保存在域中

if (isflag){
                //返回true:数据库中存在用户
                //转发到regist.html页面
                request.setAttribute("msg","已存在用户,请重新输入");
                request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response);
            }

2.错误信息的显示:

 </div>
            <span class="errMess" id="usermsg">${empty requestScope.msg?"请输入用户名":requestScope.msg}</span>
 </div>

第四阶段:图书的增删改查

思路:1.创建Book的javaBean

2.创建dao,service',servlet及其相关方法

3.实现查询所有的功能

查询所有流程图

(1)编写dao及其实现类

dao:

 /**
     * 在数据库查询出所有的图书列表
     * @return 返回一个list集合
     */
    List<Books> selectAllBooks();

dao实现类:

@Override
    public List<Books> selectAllBooks() {
        String sql="select id,title,author,price,sales,stock,img_path imgPath from books";
        List<Books> beanList = getBeanList(sql);
        return beanList;
    }

(2)编写service及其实现类

service:

  List<Books> selectAllBooks();

service实现类:

    @Override
    public List<Books> selectAllBooks() {

        List<Books> books = bookDao.selectAllBooks();
        return books;
    }

 (3)编写servlet

 protected void selectAllBook(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //调用方法获得books集合
        List<Books> books = bookService.selectAllBooks();
        //将books集合存放在request域当中
        request.setAttribute("books",books);
        //请求转发到book_manager.jsp页面
        request.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(request,response);
    }

 最后在book_manager.jsp页面中使用jstl和el表达式进行查询

4.实现添加的功能

添加图书的流程

(1)编写dao及其实现类的代码

dao:

    /**
     * 向数据库中添加图书
     * @param books
     */
    void addBooks(Books books);

实现类中的代码:

@Override
    public void addBooks(Books books) {
        String sql="insert into books(title,author,price,sales,stock,img_path) values(?,?,?,?,?,?)";
        update(sql, books.getTitle(), books.getAuthor(), books.getPrice(), books.getSales(), books.getStock(),books.getImgPath());
    }

(2)编写service及其实现类的代码

service:

 void addBooks(Books books);

service实现类中的代码:

@Override
    public void addBooks(Books books) {
        bookDao.addBooks(books);
    }

(3)编写servlet中的代码

protected void addBooks(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取页面传来的参数
        String bookName = request.getParameter("bookName");
        String bookPrice = request.getParameter("bookPrice");
        String bookAuthor = request.getParameter("bookAuthor");
        String bookSales = request.getParameter("bookSales");
        String bookStock = request.getParameter("bookStock");
        //创建Books的实例
        Books books = new Books(null,bookName,bookAuthor,Double.parseDouble(bookPrice),Integer.parseInt(bookSales),Integer.parseInt(bookStock));
        //调用service的增加图书的方法
        bookService.addBooks(books);
        //添加图书之后跳转查询所有显示所有的图书
        response.sendRedirect(request.getContextPath()+"/BookServlet?way=selectAllBook");
    }

5.实现删除的功能

删除功能流程图

(1)编写dao及其实现类

dao:

 /**
     * 根据id删除图书
     * @param id
     */
    void deleteBookById(int id);

 dao的实现类:

  @Override
    public void deleteBookById(int id) {
        String sql="delete from books where id=?";
        update(sql,id);
    }

(2)编写service及其实现类

service:

void deleteBookById(int id);

实现类:

  @Override
    public void deleteBookById(int id) {
        bookDao.deleteBookById(id);
    }

(3)编写servlet

  protected void deleteById(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取页面参数值id
        String id = request.getParameter("id");
        //调用service的删除方法
        bookService.deleteBookById(Integer.parseInt(id));
        //跳转查询所有页面
        response.sendRedirect(request.getContextPath()+"/BookServlet?way=getBooks");
    }

最终跳转到查询所有界面

6.实现修改的功能

修改流程图:

修改的步骤如图所示:首先通过id查询获取要修改的图书的信息传到修改页面,然后通过修改图书的操作重定向到查询所有的界面

(1)编写通过id查询数据的dao实现类和service实现类

dao实现类:

 @Override
    public Books selectBookById(int id) {
        String sql="select id,title,author,price,sales,stock,img_path imgPath from books where id=?";
        Books books = getBean(sql, id);
        return books;
    }

service实现类:

  @Override
    public Books selectBookById(int id) {
        Books books = bookDao.selectBookById(id);
        return books;
    }

(2)编写通过id查询图书数据的方法

   protected void selectBookById(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       //从页面获取id的参数值
        String id = request.getParameter("id");
        //调用service的查询方法
        Books books = bookService.selectBookById(Integer.parseInt(id));
        //添加到request域中
        request.setAttribute("bookbyid",books);
        //请求转发
        request.getRequestDispatcher("/pages/manager/book_addandupdate.jsp").forward(request,response);
    }

查询到数据之后转发到修改的页面,修改页面获取从dao中根据id查询的信息,然后将id值和其他参数值传入到修改的servlet中

(3)编写修改语句的dao实现类及其service实现类:

dao实现类:

 @Override
    public void updateBook(Books books) {
        String sql="update books set title=?,author=?,price=?,sales=?,stock=? where id=?";
        update(sql,books.getTitle(),books.getAuthor(),books.getPrice(),books.getSales(),books.getStock(),books.getId());
    }

service实现类:

  @Override
    public void update(Books books) {
        bookDao.updateBook(books);
    }

(4)编写servlet中的修改的方法(和add(增加方法)的整合)    (注:修改方法带有参数id,添加方法不带有参数id)

protected void addAndupdateBook(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //从页面获取的参数值
        String id = request.getParameter("id");
        String bookName = request.getParameter("bookName");
        String bookPrice = request.getParameter("bookPrice");
        String bookAuthor = request.getParameter("bookAuthor");
        String bookSales = request.getParameter("bookSales");
        String bookStock = request.getParameter("bookStock");
        //判断是修改页面还是添加页面
        if ("".equals(id)){
            //创建Books的实例
            Books books = new Books(null,bookName,bookAuthor,Double.parseDouble(bookPrice),Integer.parseInt(bookSales),Integer.parseInt(bookStock));
            //调用service的增加图书的方法
            bookService.addBooks(books);
            //添加图书之后跳转查询所有显示所有的图书
            response.sendRedirect(request.getContextPath()+"/BookServlet?way=getBooks");
        }else {
            //创建Books的对象
            Books books = new Books(Integer.parseInt(id),bookName,bookAuthor,Double.parseDouble(bookPrice),Integer.parseInt(bookSales),Integer.parseInt(bookStock));
            //调用bookservice方法
            bookService.update(books);
            response.sendRedirect(request.getContextPath()+"/BookServlet?way=getBooks");
        }

    }

7.实现分页的功能

    • 如果添加分页操作我们需要知道总页数、当前页码、总记录数等信息,但是List中并没有这些信息,所有我们需要创建一个类来封装分页的信息
    • 流程图
    • (1).创建Page<T>类(javabean)
    • public class Page<T> {
          private List<T> list;//从数据库分页得来的一页数据
          private static final int PAGE_SIZE=5;//每页显示的数据的数量
          private int pageNo;//当前的页码数,由用户在页面传来
          private int pageRecoder;//数据库中数据的总记录数
          private int pageNum;//总页码数,通过计算得到
          public Page(List<T> list, int pageNo, int pageRecoder, int pageNum) {
              this.list = list;
              this.pageNo = pageNo;
              this.pageRecoder = pageRecoder;
              this.pageNum = pageNum;
          }
      
          public Page() {
          }
          public List<T> getList() {
              return list;
          }
      
          public void setList(List<T> list) {
              this.list = list;
          }
      
          public static int getPageSize() {
              return PAGE_SIZE;
          }
      
          public int getPageNo() {
              //如果当前页码小于1,则返回1
              if (pageNo<1){
                  return 1;
                  //如果当前页码大于总页数,则返回总页数
              }else if (pageNo>getPageNum()){
                  return getPageNum();
              }else {
                  //如果当前页码大于等于1,小于等于总页数,则返回当前页码
                  return pageNo;
              }
          }
      
          public void setPageNo(int pageNo) {
              this.pageNo = pageNo;
          }
      
          public int getPageRecoder() {
              return pageRecoder;
          }
      
          public void setPageRecoder(int pageRecoder) {
              this.pageRecoder = pageRecoder;
          }
      
          public int getPageNum() {
              if (pageRecoder%PAGE_SIZE==0){
                  return pageRecoder/PAGE_SIZE;
              }else{
                  return pageRecoder/PAGE_SIZE+1;
              }
          }
      
      
          @Override
          public String toString() {
              return "Page{" +
                      "list=" + list +
                      ", pageNo=" + pageNo +
                      ", pageRecoder=" + pageRecoder +
                      ", pageNum=" + pageNum +
                      '}';
          }
      
      
      }

      (2).修改dao添加一个分页的方法:编写dao的实现类

    •    @Override
          public Page<Books> getBooks(Page<Books> page) {
              String sql="select count(*) from books";
              long count = (long)getCount(sql);
              page.setPageRecoder((int) count);
              String sql1="select id,title,author,price,sales,stock,img_path imgPath from books limit ?,?";
              List<Books> beanList = getBeanList(sql1, (page.getPageNo()-1) * Page.getPageSize(), Page.getPageSize());
              page.setList(beanList);
              return page;
          }

      (3).修改service,编写service的实现类

    •  @Override
          public Page<Books> getBooks(String pageNo) {
              Page<Books> page = new Page<>();
              int defaultPage=1;
              try {
                  defaultPage=Integer.parseInt(pageNo);
              } catch (Exception e) {
                  e.printStackTrace();
              }
              page.setPageNo(defaultPage);
             return bookDao.getBooks(page);
          }

      (4).编写servlet

    •     protected void getBooks(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //从页面获取参数
              String pageNo = request.getParameter("pageNo");
      
      
              //调用bookservice方法传入页码数的对象
              Page<Books> pagebooks = bookService.getBooks(pageNo);
              //将books放到域对象中
              request.setAttribute("page",pagebooks);
              //请求转发到显示图书页面
              request.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(request,response);
      
          }

      8.关于页码分页的问题

    •        </div>
                  <div class="list-footer">
                    <c:if test="${requestScope.page.pageNo>1}">
                      <div><a href="clientBookServlet?way=getPageAndPrice&pageNo=1&minPrice=${requestScope.minPrice}&maxPrice=${requestScope.maxPrice}">首页</a></div>
                      <div><a href="clientBookServlet?way=getPageAndPrice&pageNo=${requestScope.page.pageNo-1}&minPrice=${requestScope.minPrice}&maxPrice=${requestScope.maxPrice}">上一页</a></div>
                    </c:if>
      <%--
      需求:页码数量等于五
      1.当总页码小于5时,begin值为1,end值为当前最大页码数
      2.当总页码数超过5时
         1)当当前页码<=3时,begin值为1,end值为5.
         2)当当前页码>3时,begin值为当前页码值-2,end值为当前页码值+2
           2.1)当end值>总页码时,end值为页码最大值
                  begin值为最大值-4
      --%>
                    <c:choose>
                      <%--当总页码小于5时--%>
                      <c:when test="${requestScope.page.pageNum<5}">
                        <%--begin的值为1,end值为当前的最大页码数--%>
                        <c:set var="begin" value="1"></c:set>
                        <c:set var="end" value="${requestScope.page.pageNum}"></c:set>
                      </c:when>
                      <%--当当前页码值小于三时--%>
                      <c:when test="${requestScope.page.pageNo<=3}">
                        <%--begin值为1,end值为5--%>
                        <c:set var="begin" value="1"></c:set>
                        <c:set var="end" value="5"></c:set>
                      </c:when>
                      <%--当当前页码大于三时--%>
                      <c:otherwise>
                        <%--begin值为当前页码-2,end值为当前页码+2--%>
                        <c:set var="begin" value="${requestScope.page.pageNo-2}"></c:set>
                        <c:set var="end" value="${requestScope.page.pageNo+2}"></c:set>
                        <%--当end值大于总页码值时,end值为页码最大值,begin值为页码最大值-4--%>
                        <c:if test="${end>requestScope.page.pageNum}">
                          <c:set var="begin" value="${requestScope.page.pageNum-4}"></c:set>
                          <c:set var="end" value="${requestScope.page.pageNum}"></c:set>
                        </c:if>
                      </c:otherwise>
                    </c:choose>
      
      
                    <ul>
                      <c:forEach begin="${begin}" end="${end}" var="index">
      
                        <c:if test="${requestScope.page.pageNo==index}">
                          <li class="active"><a href="clientBookServlet?way=getPageAndPrice&pageNo=${index}&minPrice=${requestScope.minPrice}&maxPrice=${requestScope.maxPrice}">${index}</a></li>
                        </c:if>
                        <c:if test="${requestScope.page.pageNo!=index}">
                          <li><a href="clientBookServlet?way=getPageAndPrice&pageNo=${index}&minPrice=${requestScope.minPrice}&maxPrice=${requestScope.maxPrice}">${index}</a></li>
                        </c:if>
      
                      </c:forEach>
                    </ul>
                    <c:if test="${requestScope.page.pageNo<requestScope.page.pageNum}">
                      <div><a href="clientBookServlet?way=getPageAndPrice&pageNo=${requestScope.page.pageNum}&minPrice=${requestScope.minPrice}&maxPrice=${requestScope.maxPrice}">末页</a></div>
                      <div><a href="clientBookServlet?way=getPageAndPrice&pageNo=${requestScope.page.pageNo+1}&minPrice=${requestScope.minPrice}&maxPrice=${requestScope.maxPrice}">下一页</a></div>
                    </c:if>
                    <span>共${requestScope.page.pageNum}页</span>
                    <span>${requestScope.page.pageRecoder}条记录</span>
                    <span>到第</span>
                    <input type="text" id="yema" name="yema"/>
                    <span>页</span>
                    <button class="btn">确定</button>
                  </div>
                </div>
              </div>
      

      8.前台图书的显示

    • 创建dao中的方法

    •  @Override
          public Page<Books> getPageAndPrice(Page<Books> page, double defaultminPrice, double defaultmaxPrice) {
              String sql="select count(*) from books where price between ? and ?";
              long count = (long)getCount(sql,defaultminPrice,defaultmaxPrice);
              page.setPageRecoder((int) count);
              String sql1="select id,title,author,price,sales,stock,img_path imgPath from books where price between ? and ? limit ?,?";
              List<Books> beanList = getBeanList(sql1,defaultminPrice,defaultmaxPrice, (page.getPageNo()-1) * Page.getPageSize(), Page.getPageSize());
              page.setList(beanList);
              return page;
          }

      在service中获取dao中的方法

    •  @Override
          public Page<Books> getPageAndPrice(String pageNo, String minPrice, String maxPrice) {
              Page<Books> page = new Page<>();
              int defaultPage=1;
              double defaultminPrice=0;
              double defaultmaxPrice=Double.MAX_VALUE;
              try {
                  defaultPage=Integer.parseInt(pageNo);
              } catch (Exception e) {
                  e.printStackTrace();
              }
              try {
                  defaultminPrice=Double.parseDouble(minPrice);
              } catch (Exception e) {
                  e.printStackTrace();
              }
              try {
                  defaultmaxPrice=Double.parseDouble(maxPrice);
              } catch (Exception e) {
                  e.printStackTrace();
              }
              if (defaultminPrice>defaultmaxPrice){
                  double temp=defaultminPrice;
                  defaultminPrice=defaultmaxPrice;
                  defaultmaxPrice=temp;
              }
              page.setPageNo(defaultPage);
              return bookDao.getPageAndPrice(page,defaultminPrice,defaultmaxPrice);
          }

      创建servlet

    •  protected void getPageAndPrice(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //从页面获取参数
              String pageNo = request.getParameter("pageNo");
              String minPrice = request.getParameter("minPrice");
              String maxPrice = request.getParameter("maxPrice");
              //调用bookservice方法传入页码数的对象
              Page<Books> pagebooks = bookService.getPageAndPrice(pageNo,minPrice,maxPrice);
              //将pagebooks放到域对象中
              request.setAttribute("page",pagebooks);
              //将最大值和最小值放到域中
              request.setAttribute("minPrice",minPrice);
              request.setAttribute("maxPrice",maxPrice);
              //请求转发到显示图书页面
              request.getRequestDispatcher("/pages/client/client.jsp").forward(request,response);
          }

      第五阶段:登录,登出、验证码、购物车

    • 登录:在第二阶段已经实现

    • 登出:

    •   protected void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //创建session域
              HttpSession session = request.getSession();
              //使session失效
              session.invalidate();
              //重定向到首页
              response.sendRedirect(request.getContextPath()+"/index.jsp");
      //        //请求转发到首页
      //        request.getRequestDispatcher("/index.jsp").forward(request,response);
          }

      验证码:

    • 导入kaptcha-2.3.2.jar包之后
    • 在web.xml文件中注册Servlet
    • <!--配置验证码的servlet-->
          <servlet>
              <servlet-name>KaptchaServlet</servlet-name>
              <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
              <!--配制session中的key值-->
              <init-param>
                  <param-name>kaptcha.session.key</param-name>
                  <param-value>code</param-value>
              </init-param>
          </servlet>
          <servlet-mapping>
              <servlet-name>KaptchaServlet</servlet-name>
              <url-pattern>/code</url-pattern>
          </servlet-mapping>

      在session域中获取验证码,获取之后移除

    • //获取输入框验证码的值
              String inputcode = request.getParameter("code");
              //获取session域中的验证码的值
              HttpSession session = request.getSession();
              String sessioncode = (String) session.getAttribute("code");
              //进行判断
              if (inputcode.equals(sessioncode)){
                  //验证码正确,清除session
                 session.removeAttribute("code");
                 //下面写要实现的需求
      }

      购物车:

    • 购物车,购物项的理解
    • 购物车模块的分析
    • 创建购物项类
    • package com.atguigu.bean;
      
      import java.math.BigDecimal;
      
      public class CartItem {
          private Books books;//购物项中购买的图书
          private double amount;//购物项中图书的金额小计,通过计算得到
          private int count;//购物项中购买的图书的数量
      
          public CartItem(Books books, double amount, int count) {
              this.books = books;
              this.amount = amount;
              this.count = count;
          }
      
          public CartItem() {
          }
      
          @Override
          public String toString() {
              return "CartItem{" +
                      "books=" + books +
                      ", amount=" + amount +
                      ", count=" + count +
                      '}';
          }
      
          public Books getBooks() {
              return books;
          }
      
          public void setBooks(Books books) {
              this.books = books;
          }
          //图书的金额小计由图书的数量和单价计算得出
          public double getAmount() {
              BigDecimal price = new BigDecimal(books.getPrice()+"");
              BigDecimal count = new BigDecimal(this.count+"");
              BigDecimal total = price.multiply(count);
              double v = total.doubleValue();
              return v;
          }
      
      
          public int getCount() {
              return count;
          }
      
          public void setCount(int count) {
              this.count = count;
          }
      }
      

       

    • 创建购物车类
    • 创建购物车类的同时,也创建其相关的方法
    • package com.atguigu.bean;
      
      import java.math.BigDecimal;
      import java.util.*;
      
      public class Cart {
          //String代表的是图书的id,CartItem代表的是图书项
          private Map<String,CartItem> map=new HashMap<>();
          private int totalCount;
          private double totalAmount;
      
          @Override
          public String toString() {
              return "Cart{" +
                      "map=" + map +
                      ", totalCount=" + totalCount +
                      ", totalAmount=" + totalAmount +
                      '}';
          }
      
          public Cart(Map<String, CartItem> map, int totalCount, double totalAmount) {
              this.map = map;
              this.totalCount = totalCount;
              this.totalAmount = totalAmount;
          }
      
          public Cart() {
          }
      
          public Map<String, CartItem> getMap() {
              return map;
          }
      
          public void setMap(Map<String, CartItem> map) {
              this.map = map;
          }
          //得到每一个图书项
          public List<CartItem> getCartItem(){
              Collection<CartItem> values = map.values();
              return new ArrayList<>(values);
          }
          //获取图书的总数量
          public int getTotalCount() {
              //得到图书项
              List<CartItem> cartItem = getCartItem();
              int totalCount=0;
              //遍历图书项
              for (CartItem c:cartItem){
                  totalCount+=c.getCount();
              }
              return totalCount;
          }
      
          public void setTotalCount(int totalCount) {
              this.totalCount = totalCount;
          }
          public void setTotalAmount(double totalAmount) {
              this.totalAmount = totalAmount;
          }
      //获取金额小计的总金额
          public double getTotalAmount() {
              //获取图书项
              List<CartItem> cartItem = getCartItem();
      //        double totalAmount=0;
              BigDecimal totalAmount = new BigDecimal("0");
              for (CartItem c:cartItem){
                  BigDecimal amout = new BigDecimal(c.getAmount() + "");
                  totalAmount = totalAmount.add(amout);
              }
              return totalAmount.doubleValue();
          }
          //删除图书项
          public void deleteCartItem(String bookId){
              map.remove(bookId);
          }
          //清空图书项
          public void clearCartItem(){
              map.clear();
          }
          //更新图书
          public void updateCartItem(String bookId,String bookCount){
              //通过bookId得到图书项
              CartItem cartItem = map.get(bookId);
              int count=0;
              try {
                   count=Integer.parseInt(bookCount);
                   if (count<0){
                       count=1;
                   }
              } catch (NumberFormatException e) {
                  e.printStackTrace();
              }
              cartItem.setCount(count);
          }
          //添加图书
          public void addCartItem(Books books){
              //根据图书的id从购物车中查询对应的购物项
              CartItem cartItem = map.get(books.getId() + "");
              //判断cartItem是否为null
              if(cartItem == null){
                  //证明购物车中还没有该购物项
                  //创建该图书对应的购物项
                  cartItem = new CartItem();
                  //将book设置到购物项中
                  cartItem.setBooks(books);
                  //设置该购物项中图书的数量为1
                  cartItem.setCount(1);
                  //将该购物项添加到购物车中
                  map.put(books.getId()+"",cartItem);
              }else{
                  //证明购物车中已经有该购物项,此时只需要将该购物项中图书的数量加1即可
                  //获取当前购物项中图书的数量
                  int count = (int) cartItem.getCount();
                  //将数量加1
                  cartItem.setCount(count+1);
              }
          }
      }
      

      创建servlet

    • package com.atguigu.servlet;
      
      import com.atguigu.bean.Books;
      import com.atguigu.bean.Cart;
      import com.atguigu.bean.CartItem;
      import com.atguigu.service.BookService;
      import com.atguigu.service.Impl.BookServiceImpl;
      import com.google.gson.Gson;
      
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import javax.servlet.http.HttpSession;
      import java.io.IOException;
      import java.util.HashMap;
      import java.util.Map;
      
      @WebServlet(name = "CartServlet",urlPatterns = "/cartServlet")
      public class CartServlet extends BaseServlet {
          BookService bookService=new BookServiceImpl();
          protected void changeinput(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //获取id值
              String id = request.getParameter("id");
              //获取bookCount
              String bookCount = request.getParameter("bookCount");
              //从session域中获取cart
              HttpSession session = request.getSession();
              Cart cart = (Cart) session.getAttribute("cart");
              if (cart!=null){
                  //更新图书的数量
                  cart.updateCartItem(id,bookCount);
              }
      
              //得到图书项
              CartItem cartItem = cart.getMap().get(id);
              //得到图书项的小计金额
              double amount = cartItem.getAmount();
              //得到所有图书项的总金额
              double totalAmount = cart.getTotalAmount();
              //得到所有图书项的总数量
              int totalCount = cart.getTotalCount();
              //将获取到的数据填充在map中
              Map<String,Object> map=new HashMap<>();
              map.put("amount",amount+"");
              map.put("totalCount",totalCount+"");
              map.put("totalAmount",totalAmount+"");
              Gson gson=new Gson();
              String json = gson.toJson(map);
              response.setContentType("text/html;charset=utf-8");
              //将JSON字符串响应到浏览器
              response.getWriter().write(json);
      
          }
          protected void addCart(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //从页面获取id值
              String id = request.getParameter("id");
              //调用bookservice的方法获取得到books对象
              Books books = bookService.selectBookById(Integer.parseInt(id));
              //获取session
              HttpSession session = request.getSession();
              //从session域中获取cart
              Cart cart = (Cart) session.getAttribute("cart");
              if (cart==null){
                  //证明session域中还没有购物车,创建一个cart对象放在session中
                  cart = new Cart();
                  session.setAttribute("cart",cart);
              }
              //调用cart的添加方法,
              cart.addCartItem(books);
              //重定向到index页面
              //response.sendRedirect(request.getContextPath()+"/index.jsp");
              //获取请求头中的Referer属性值
              String referer=request.getHeader("Referer");
              //重定向到referer
              response.sendRedirect(referer);
          }
          protected void clear(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      
              //获取session
              HttpSession session = request.getSession();
              //从session域中获取cart
              Cart cart = (Cart) session.getAttribute("cart");
              if (cart!=null){
                  cart.clearCartItem();
              }
      
              //重定向到index页面
              //response.sendRedirect(request.getContextPath()+"/index.jsp");
              //获取请求头中的Referer属性值
              String referer=request.getHeader("Referer");
              //重定向到referer
              response.sendRedirect(referer);
          }
          protected void deleteCartItem(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //获取页面中参数id
              String id = request.getParameter("id");
      
              //获取session
              HttpSession session = request.getSession();
              //从session域中获取cart
              Cart cart = (Cart) session.getAttribute("cart");
              if (cart!=null){
                  //调用cart对象的删除的方法
                  cart.deleteCartItem(id);
              }
              //重定向到index页面
              //response.sendRedirect(request.getContextPath()+"/index.jsp");
              //获取请求头中的Referer属性值
              //重定向到购物车页面
              response.sendRedirect(request.getContextPath()+"/pages/cart/cart.jsp");
          }
          protected void updateCartItem(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //获取页面中参数id
              String id = request.getParameter("id");
              //获取页面中的参数bookCount
              String bookCount = request.getParameter("bookCount");
              //获取session
              HttpSession session = request.getSession();
              //从session域中获取cart
              Cart cart = (Cart) session.getAttribute("cart");
              if (cart!=null){
                  //调用cart对象的根更新的方法
                  cart.updateCartItem(id,bookCount);
              }
              //重定向到index页面
              //response.sendRedirect(request.getContextPath()+"/index.jsp");
              //获取请求头中的Referer属性值
              //重定向到购物车页面
              response.sendRedirect(request.getContextPath()+"/pages/cart/cart.jsp");
          }
      }
      

      第六阶段:结账、添加事务、使用ajax

    • 1.创建订单类和订单项类
    • package com.atguigu.bean;
      
      import java.util.Date;
      
      //订单类
      public class Order {
          private String id;//订单号
          private Date orderTime;//生成订单的时间
          private int totalCount;//购物车中图书的总数量
          private double totalAmount;//购物车中图书的总金额
          private int state;//订单的状态 0 未发货 1已发货 2交易完成
          private int userId;//订单所属的用户
      
          public Order(String id, Date orderTime, int totalCount, double totalAmount, int state, int userId) {
              this.id = id;
              this.orderTime = orderTime;
              this.totalCount = totalCount;
              this.totalAmount = totalAmount;
              this.state = state;
              this.userId = userId;
          }
      
          public Order() {
          }
      
          @Override
          public String toString() {
              return "Order{" +
                      "id='" + id + '\'' +
                      ", orderTime=" + orderTime +
                      ", totalCount=" + totalCount +
                      ", totalAmount=" + totalAmount +
                      ", state=" + state +
                      ", userId=" + userId +
                      '}';
          }
      
          public String getId() {
              return id;
          }
      
          public void setId(String id) {
              this.id = id;
          }
      
          public Date getOrderTime() {
              return orderTime;
          }
      
          public void setOrderTime(Date orderTime) {
              this.orderTime = orderTime;
          }
      
          public int getTotalCount() {
              return totalCount;
          }
      
          public void setTotalCount(int totalCount) {
              this.totalCount = totalCount;
          }
      
          public double getTotalAmount() {
              return totalAmount;
          }
      
          public void setTotalAmount(double totalAmount) {
              this.totalAmount = totalAmount;
          }
      
          public int getState() {
              return state;
          }
      
          public void setState(int state) {
              this.state = state;
          }
      
          public int getUserId() {
              return userId;
          }
      
          public void setUserId(int userId) {
              this.userId = userId;
          }
      }
      
      package com.atguigu.bean;
      
      public class OrderItem {
          private Integer id;//订单项的id
          private int count;//购物项中购买的图书数量
          private double amount;//购物项中图书的金额小计
          private String title;//书名
          private String author; //作者
          private double price; //图书的价格
          private String imgPath; //图书的封面
          private String orderId; //订单项所属的订单
      
      
          public OrderItem() {
          }
      
          public OrderItem(int count, double amount, String title, String author, double price, String imgPath, String orderId) {
              this.count = count;
              this.amount = amount;
              this.title = title;
              this.author = author;
              this.price = price;
              this.imgPath = imgPath;
              this.orderId = orderId;
          }
      
          @Override
          public String toString() {
              return "OrderItem{" +
                      "id=" + id +
                      ", count=" + count +
                      ", amount=" + amount +
                      ", title='" + title + '\'' +
                      ", author='" + author + '\'' +
                      ", price=" + price +
                      ", imgPath='" + imgPath + '\'' +
                      ", orderId='" + orderId + '\'' +
                      '}';
          }
      
          public Integer getId() {
              return id;
          }
      
          public void setId(Integer id) {
              this.id = id;
          }
      
          public int getCount() {
              return count;
          }
      
          public void setCount(int count) {
              this.count = count;
          }
      
          public double getAmount() {
              return amount;
          }
      
          public void setAmount(double amount) {
              this.amount = amount;
          }
      
          public String getTitle() {
              return title;
          }
      
          public void setTitle(String title) {
              this.title = title;
          }
      
          public String getAuthor() {
              return author;
          }
      
          public void setAuthor(String author) {
              this.author = author;
          }
      
          public double getPrice() {
              return price;
          }
      
          public void setPrice(double price) {
              this.price = price;
          }
      
          public String getImgPath() {
              return imgPath;
          }
      
          public void setImgPath(String imgPath) {
              this.imgPath = imgPath;
          }
      
          public String getOrderId() {
              return orderId;
          }
      
          public void setOrderId(String orderId) {
              this.orderId = orderId;
          }
      
          public OrderItem(Integer id, int count, double amount, String title, String author, double price, String imgPath, String orderId) {
              this.id = id;
              this.count = count;
              this.amount = amount;
              this.title = title;
              this.author = author;
              this.price = price;
              this.imgPath = imgPath;
              this.orderId = orderId;
          }
      }
      

      创建orderdao 

    • public class OrderDaoImpl extends BaseDao<Order> implements OrderDao {
          @Override
          public void addOrder(Order order) {
              String sql="insert into orders(id,order_time,total_count,total_amount,state,user_id) values(?,?,?,?,?,?)";
              update(sql, order.getId(), order.getOrderTime(), order.getTotalCount(), order.getTotalAmount(), order.getState(), order.getUserId());
          }
      }

      创建orderItemDao

    • public class OrderItemDaoImpl extends BaseDao<OrderItem> implements OrderItemDao {
      
      
          @Override
          public void addOrderItem(OrderItem orderItem) {
              String sql="insert into order_items(count,amount,title,author,price,img_path,order_id) values(?,?,?,?,?,?,?)";
              update(sql,orderItem.getCount(),orderItem.getAmount(),orderItem.getTitle(),orderItem.getAuthor(),orderItem.getPrice(),orderItem.getImgPath(),orderItem.getOrderId());
          }
      
          @Override
          public void batchAddOrderItems(Object[][] params) {
              String sql="insert into order_items(count,amount,title,author,price,img_path,order_id) values(?,?,?,?,?,?,?)";
              batchUpdate(sql,params);
          }
      }

      service层处理业务 

    • package com.atguigu.service.Impl;
      
      import com.atguigu.bean.*;
      import com.atguigu.dao.BookDao;
      import com.atguigu.dao.Impl.BookDaoImpl;
      import com.atguigu.dao.Impl.OrderDaoImpl;
      import com.atguigu.dao.Impl.OrderItemDaoImpl;
      import com.atguigu.dao.OrderDao;
      import com.atguigu.dao.OrderItemDao;
      import com.atguigu.service.OrderService;
      
      import java.util.Date;
      import java.util.List;
      
      public class OrderServiceImpl implements OrderService {
          OrderDao orderDao=new OrderDaoImpl();
          OrderItemDao orderItemDao=new OrderItemDaoImpl();
          BookDao bookDao=new BookDaoImpl();
          @Override
          public String checkout(Cart cart, User user) {
              //生成订单号
              String orderId=System.currentTimeMillis()+""+user.getId();
              //获取总数量
              int totalCount = cart.getTotalCount();
              //获取订单总额
              double totalAmount = cart.getTotalAmount();
              Order order = new Order(orderId, new Date(), totalCount, totalAmount, 0, user.getId());
              //将订单加入数据库
              orderDao.addOrder(order);
              //得到购物车中所有的图书项
              List<CartItem> cartItems = cart.getCartItem();
             
      
              for (CartItem cartItem1:cartItems){
                  //获取图书
                  Books books = cartItem1.getBooks();
                  //获取图书项的count数量
                  int count = (int)cartItem1.getCount();
                  //获取图书项的小计金额
                  double amount = cartItem1.getAmount();
                  //获取图书的书名
                  String title = books.getTitle();
                  //获取图书的作者
                  String author = books.getAuthor();
                  //获取单价
                  Double price = books.getPrice();
                  //获取图书图片
                  String imgPath = books.getImgPath();
                  //创建订单项
                  OrderItem orderItem = new OrderItem(null,  count,amount,title,author,price,imgPath,orderId);
                  //将订单项加入数据库
      
                  //设置图书的库存和销量
                  //库存-count,销量+count
                  //获取当前库存
                  Integer stock = books.getStock();
                  //获取当前销量
                  Integer sales = books.getSales();
                  //在book中设置
                  books.setStock(stock-count);
                  books.setStock(sales+count);
                  //修改数据库的book
                  bookDao.updateBook(books);
      
              }
      return orderId;
          }
      
      

      servlet

    • 在创建订单号的同时,也将订单和订单项加入到数据库中

    • protected void checkout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //获取session对象
              HttpSession session = request.getSession();
              //从session域中拿出购物车和用户对象
              Cart cart = (Cart) session.getAttribute("cart");
              User user = (User) session.getAttribute("user");
              //调用OrderService中的方法
              String OrderId = orderService.checkout(cart, user);
              //设置到session域中
              session.setAttribute("orderId",OrderId);
      //        request.getRequestDispatcher("/pages/cart/checkout.jsp").forward(request,response);
             //重定向到显示订单号的页面
              response.sendRedirect(request.getContextPath()+"/pages/cart/checkout.jsp");
          }

      添加事务

    • 事务控制的关键:在同一个事务中,不同的操作要求使用同一个的数据库连接

    • 如何保证使用同一个连接?使用ThreadLocal<T>对象保证一个线程对应一个数据库连接
    • 然后使用过滤器控制事务
  • 改变jdbcutils中的代码
  • package com.atguigu.utils;
    
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    
    import javax.sql.DataSource;
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.util.Properties;
    
    /**
     * ★通过德鲁伊连接池获取和释放连接的工具类(重点掌握)
     */
    public class JDBCUtils {
    
        private static DataSource dataSource;
        //获取threadlocal的连接池
       private static ThreadLocal<Connection> threadLocal=new ThreadLocal<>();
    
        static {
            try {
                //1.创建Properties对象
                Properties pro = new Properties();
                InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
                //2.将类路径下的properties文件读成一个流
                //3.加载properties文件
                pro.load(is);
                //4.创建数据源
                dataSource = DruidDataSourceFactory.createDataSource(pro);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        //获取同一个连接的方法
        public static Connection getConnection(){
    //        Connection connection = null;
    //        try {
    //            //从数据源中获取连接
    //            connection = dataSource.getConnection();
    //        } catch (SQLException e) {
    //            e.printStackTrace();
    //        }
    //        return connection;
            Connection connection = threadLocal.get();
            if (connection==null){
                try {
                    //在连接池中获取连接
                    connection = dataSource.getConnection();
                    //将连接与当前线程绑定
                    threadLocal.set(connection);
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            return connection;
        }
    
        //释放连接的方法
        public static void releaseConnection(){
    //        if(connection != null){
    //            try {
    //                connection.close();
    //            } catch (SQLException e) {
    //                e.printStackTrace();
    //            }
    //        }
            //从当前线程获取连接
            Connection connection = threadLocal.get();
            if (connection!=null){
                try {
                    //关闭连接
                    connection.close();
                    //将关闭的连接从threadlocal移除
                     threadLocal.remove();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
    
        }
    }
    

    使用过滤器过滤所有的请求

  • package com.atguigu.filter;
    
    import com.atguigu.utils.JDBCUtils;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.SQLException;
    
    @WebFilter(filterName = "TranslicationFilter",urlPatterns = "/*")
    public class TranslicationFilter implements Filter {
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            //获取连接
            Connection connection = JDBCUtils.getConnection();
            try {
                //设置自动提交为false
                connection.setAutoCommit(false);
                //放行
                chain.doFilter(req, resp);
                //放行之后进入servlet,serlet调用service,service调用dao,然后执行放行后的代码
                //设置提交
                connection.commit();
            } catch (Exception throwables) {
                //出现异常,数据回滚
                try {
                    connection.rollback();
                    //重定向到错误页面
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                throwables.printStackTrace();
            }
    
        }
    
        public void init(FilterConfig config) throws ServletException {
    
        }
    
    }
    

    批处理:

  • 在basedao中加入batchUpdate(String sql,Object[][] params)方法

  • package com.atguigu.utils;
    
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    import org.apache.commons.dbutils.handlers.ScalarHandler;
    
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.util.List;
    
    
    /**
     * 定义一个用来被继承的对数据库进行基本操作的Dao
     * 
     * @author HanYanBing
     *
     * @param <T>
     */
    public abstract class BaseDao<T> {
    	private QueryRunner queryRunner = new QueryRunner();
    	//定义一个变量来接收泛型的类型
    	private Class<T> type;
    	// 获取T的Class对象,获取泛型的类型,泛型是在被子类继承时才确定
    	public BaseDao() {
    		//获取子类的类型
    		Class clazz = this.getClass();
    		//获取父类的类型
    		//getGenericSuperclass()用来获取当前类的父类的类型
    		//ParameterizedType表示的是带泛型的类型
    		ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
    		//获取具体的泛型类型 getActualTypeArguments获取具体的泛型的类型
    		//这个方法会返回一个Type的数组
    		Type[] types = parameterizedType.getActualTypeArguments();
    		//获取具体的泛型的类型·
    		this.type = (Class<T>) types[0];
    	}
    	
    	/**
    	 * 通用的增删改操作
    	 * 
    	 * @param sql
    	 * @param params
    	 * @return
    	 */
    	public int update(String sql, Object... params) {
    		// 获取连接
    		Connection connection = JDBCUtils.getConnection();
    		int count = 0;
    		try {
    			count = queryRunner.update(connection, sql, params);
    		} catch (SQLException e) {
    			//在进行订单操作时,出现错误的话在这里将异常捕获,不再抛去上一级,所以错误不在过滤器中捕获到,也无法提交事务,
    			// 所以要在这里将编译时异常转换成运行时异常
    //			e.printStackTrace();
    			throw new RuntimeException();
    		} finally {
    			JDBCUtils.releaseConnection();
    		}
    		return count;
    	}
    
    	/**
    	 * 获取一个对象
    	 * 
    	 * @param sql
    	 * @param params
    	 * @return
    	 */
    	public T getBean(String sql, Object... params) {
    		// 获取连接
    		Connection connection = JDBCUtils.getConnection();
    		T t = null;
    		try {
    			t = queryRunner.query(connection, sql, new BeanHandler<T>(type),
    					params);
    		} catch (SQLException e) {
    //			e.printStackTrace();
    			throw new RuntimeException();
    		} finally {
    			JDBCUtils.releaseConnection();
    		}
    		return t;
    	}
    
    	/**
    	 * 获取所有对象
    	 * @param sql
    	 * @param params
    	 * @return
    	 */
    	public List<T> getBeanList(String sql, Object... params) {
    		// 获取连接
    		Connection connection = JDBCUtils.getConnection();
    		List<T> list = null;
    		try {
    			list = queryRunner.query(connection, sql, new BeanListHandler<T>(type), params);
    		} catch (SQLException e) {
    //			e.printStackTrace();
    			throw  new RuntimeException();
    		} finally {
    			JDBCUtils.releaseConnection();
    		}
    		return list;
    	}
    	public Object getCount(String sql,Object ...params){
    		Connection connection = JDBCUtils.getConnection();
    		Object query =null;
    		try {
    			query=queryRunner.query(connection, sql, new ScalarHandler<>(),params);
    		} catch (SQLException e) {
    //			e.printStackTrace();
    			throw new RuntimeException();
    		}finally {
    			JDBCUtils.releaseConnection();
    		}
    		return  query;
    	}
    
    	/**
    	 * 批处理的方法
    	 * @param sql
    	 * @param params 传入一个二维数组的参数
    	 *               二维数组的第一维是sql语句执行的次数
    	 *               二维数组的第二维是执行每条sql语句时要填充的占位符
    	 * */
    	public void batchUpdate(String sql,Object[][] params){
    		//获取连接
    		Connection connection = JDBCUtils.getConnection();
    
    		try {
    			//调用queryRunner中的batch的方法
    			queryRunner.batch(connection,sql,params);
    		} catch (SQLException throwables) {
    //			throwables.printStackTrace();
    			//将编译时异常转换为运行时异常往上抛
    			throw new RuntimeException();
    		}
    
    	}
    }
    

    在orderItem中写sql语句

  •  @Override
        public void batchAddOrderItems(Object[][] params) {
            String sql="insert into order_items(count,amount,title,author,price,img_path,order_id) values(?,?,?,?,?,?,?)";
            batchUpdate(sql,params);
        }

    在service中使用批量增加的方法

  • public class OrderServiceImpl implements OrderService {
        OrderDao orderDao=new OrderDaoImpl();
        OrderItemDao orderItemDao=new OrderItemDaoImpl();
        BookDao bookDao=new BookDaoImpl();
        @Override
        public String checkout(Cart cart, User user) {
            //生成订单号
            String orderId=System.currentTimeMillis()+""+user.getId();
            //获取总数量
            int totalCount = cart.getTotalCount();
            //获取订单总额
            double totalAmount = cart.getTotalAmount();
            Order order = new Order(orderId, new Date(), totalCount, totalAmount, 0, user.getId());
            //将订单加入数据库
            orderDao.addOrder(order);
            //得到购物车中所有的图书项
            List<CartItem> cartItems = cart.getCartItem();
            //创建两个二维数组
            Object[][] orderItemParams =new Object[cartItems.size()][];
            Object[][] bookParams  =new Object[cartItems.size()][];
            //遍历图书项
            for (int i=0;i<cartItems.size();i++){
                //获取每一个购物项
                CartItem cartItem = cartItems.get(i);
                //获取图书对象
                Books books = cartItem.getBooks();
                //获取书名
                String title = books.getTitle();
                //获取作者
                String author = books.getAuthor();
                //获取图书的价格
                Double price = books.getPrice();
                //获取图书的封面
                String imgPath = books.getImgPath();
                //获取购物项中图书的数量
                int count = cartItem.getCount();
                //获取购物项中图书的金额小计
                double amount = cartItem.getAmount();
                orderItemParams[i] = new Object[]{count, amount, title, author, price, imgPath, orderId};
                //更新图书的库存和销量
                //获取购物项中对应的库存和销量
                Integer sales = books.getSales();
                Integer stock = books.getStock();
                //设置现在的销量为sales+count,库存为stock-count
    //            book.setSales(sales+count);
    //            book.setStock(stock-count);
                //更新图书
    //            bookDao.updateBook(book);
                //update books set sales = ? , stock = ? where id = ?
                bookParams[i] = new Object[]{sales+count,stock-count,books.getId()};
            }
    // 清空购物车
            cart.clearCartItem();
            return orderId;
    }
    }

    使用ajax请求使注册时显示用户已经存在的信息

  • 创建servlet

  •     //通过发送ajax请求验证用户名是否存在
        protected void checkusername(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //获取应户名请求的参数
            String username = request.getParameter("username");
            //封存User对象
            User user = new User(null,username,null,null);
            //调用UserService的方法
            //创建userservice的实现类的对象
            UserService userService=new UserServiceImpl();
            boolean regist = userService.regist(user);
            response.setContentType("text/html;charset=utf-8");
            if (regist){
                response.getWriter().write("用户名已经存在");
            }else {
                response.getWriter().write("<font color='green'>用户名可用!</font>");
            }
    
        }

    在jsp页面用jQuery写ajax请求

  •   //给用户框设置改变事件
            $("#username").change(function (){
              //获取用户的用户名
              let username = $(this).val();
              //设置请求地址
              var url="${pageContext.request.contextPath}/UserServlet?way=checkusername";
              //设置请求参数
              var params={"username":username};
              $.post(url,params,function (res){
                //将响应的信息设置到显示的span标签中
                $("#usermsg").html(res);
              });
            });

    根据输入框的改变使用ajax请求改变图书项的总金额,改变所有的金额,改变总个数

  • 在cartservlet中编写changeinput方法

  •  protected void changeinput(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //获取id值
            String id = request.getParameter("id");
            //获取bookCount
            String bookCount = request.getParameter("bookCount");
            //从session域中获取cart
            HttpSession session = request.getSession();
            Cart cart = (Cart) session.getAttribute("cart");
            if (cart!=null){
                //更新图书的数量
                cart.updateCartItem(id,bookCount);
            }
    
            //得到图书项
            CartItem cartItem = cart.getMap().get(id);
            //得到图书项的小计金额
            double amount = cartItem.getAmount();
            //得到所有图书项的总金额
            double totalAmount = cart.getTotalAmount();
            //得到所有图书项的总数量
            int totalCount = cart.getTotalCount();
            //将获取到的数据填充在map中
            Map<String,Object> map=new HashMap<>();
            map.put("amount",amount+"");
            map.put("totalCount",totalCount+"");
            map.put("totalAmount",totalAmount+"");
            Gson gson=new Gson();
            String json = gson.toJson(map);
            response.setContentType("text/html;charset=utf-8");
            //将JSON字符串响应到浏览器
            response.getWriter().write(json);

    在cart.jsp页面使用ajax请求

  •  var text = $(this).parent().next().next();
              var url="cartServlet?way=changeinput";
              var params={"id":id,"bookCount":bookCount};
              $.post(url,params,function (ref){
                //改变图书项的总金额
                text.text(ref.amount);
                //改变总金额--%>
                $("#totalAmount").text(ref.totalAmount);
                //改变总个数--%>
                $("#totalCount").text(ref.totalCount);
              },"json");

     

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值