javaweb--------------------尚硅谷书城项目详细记录

文章目录

注册登录功能

在这里插入图片描述

  • 编写了利用德鲁伊数据库连接池的jdbcutils工具类实现数据库连接和关闭

package com.atguigu.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class JdbcUtils {
    private static DruidDataSource dataSource;

    static {
        try {
        //读取配置文件
            Properties properties =new Properties() ;
            InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("resource/druid.properties");
            properties.load(inputStream);
            dataSource= (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


     public static Connection getConnection(){
         Connection conn=null;
         try {
             conn=dataSource.getConnection();
         } catch (SQLException e) {
             e.printStackTrace();
         }
         return conn;
     }
     public static void close(Connection conn){
        if (conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

     }
}

  • 编写了dao层basedao,里面是一些用dbutils和自己写的jdbcutils实现的基本数据库查询和插入功能

package com.atguigu.dao.impl;

import com.atguigu.utils.JdbcUtils;
import org.apache.commons.dbutils.DbUtils;
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.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;

public abstract class BaseDao {
    //使用dbutils
    private QueryRunner queryRunner = new QueryRunner();

    public int update(String sql, Object... args) {
        Connection conn = null;
        try {
            conn = JdbcUtils.getConnection();
            return queryRunner.update(conn, sql, args);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }
        return -1;
    }

    public <T> T queryForOne(String sql, Class<T> type, Object... args) {
        Connection conn = null;
        try {
            conn = JdbcUtils.getConnection();
            return queryRunner.query(conn, sql, new BeanHandler<T>(type), args);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }
        return null;
    }

    public <T> List<T> queryForList(String sql, Class<T> type, Object... args) {
        Connection conn = null;
        try {
            conn = JdbcUtils.getConnection();
            return queryRunner.query(conn, sql, new BeanListHandler<T>(type), args);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }
        return null;
    }

    public  Object queryForSingleValue(String sql, Object... args) {

        Connection conn = null;
        try {
            conn = JdbcUtils.getConnection();
            return queryRunner.query(conn, sql, new ScalarHandler());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }
        return null;
    }
}

  • 建数据库user表,编写user类,编写userdao规范了用户的行为,查名字是否有注册过,保存注册的用户,根据登录查询用户是否在数据库。

package com.atguigu.dao;

import com.atguigu.pojo.User;

public interface UserDao {
    public User queryUserByUsername(String username);

    public User queryUserByUsernameAndPassword(String username,String password);

    public int  saveUser(User user);


}

  • 编写userdao接口实现类userdaoimpl,继承basedao,因为要用到里面的方法。然后实现userdao接口。

package com.atguigu.dao.impl;

import com.atguigu.dao.UserDao;
import com.atguigu.pojo.User;

public class UserDaoImpl extends BaseDao implements UserDao {

    @Override
    public User queryUserByUsername(String username) {
        String sql="select `id`,`username`,`password`,`email` from t_user where username=?";
        return queryForOne(sql,User.class,username);
    }

    @Override
    public User queryUserByUsernameAndPassword(String username, String password) {
        String sql="select `id`,`username`,`password`,`email` from t_user where username=? and password=?";
        return queryForOne(sql,User.class,username,password);
    }

    @Override
    public int saveUser(User user) {
        String sql="insert into t_user(`username`,`password`,`email`)values(?,?,?)";
        return update(sql,user.getUsername(),user.getPassword(),user.getEmail());
    }
}

  • 编写service层,编写userservice接口规范操作,注册登录,注册的时候第一步验证是否重名。

package com.atguigu.service;

import com.atguigu.pojo.User;

public interface UserService {
    public void registUser(User user);

    public User login(User user);

    public boolean existUsername(String username);

}
  • 编写userserviceimpl

package com.atguigu.service.impl;

import com.atguigu.dao.UserDao;
import com.atguigu.dao.impl.UserDaoImpl;
import com.atguigu.pojo.User;
import com.atguigu.service.UserService;

public class UserServiceImpl implements UserService {
    private UserDao userDao=new UserDaoImpl();

    @Override
    public void registUser(User user) {
        userDao.saveUser(user);
    }

    @Override
    public User login(User user) {
        return userDao.queryUserByUsernameAndPassword(user.getUsername(),user.getPassword());
    }

    @Override
    public boolean existUsername(String username) {
        if (userDao.queryUserByUsername(username)==null){

            return false;
        }
        return true;
    }
}

  • 编写registsevlet处理注册

package com.atguigu.web;

import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RegistServlet extends HttpServlet {
    UserService userService=new UserServiceImpl();
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取表单里的参数  input的name名字获取
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String email = request.getParameter("email");
        String code = request.getParameter("code");

        if (code.equalsIgnoreCase("abcd")) {
            if (userService.existUsername(username)){
                System.out.println("name exist!!!");
                request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response);
            }
            else {
                userService.registUser(new User(username,password,email));
                //跳转注册成功页面
                request.getRequestDispatcher("/pages/user/regist_success.jsp").forward(request,response);
            }
        } else {
            //跳回注册页面
            System.out.println("验证码["+code+"]错误");
            request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response);
        }
    }
}

  • 编写loginservice实现登录

package com.atguigu.web;

import com.atguigu.dao.impl.UserDaoImpl;
import com.atguigu.pojo.User;
import com.atguigu.service.impl.UserServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        UserServiceImpl userService = new UserServiceImpl();

        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = new User(username, password, null);
        if (userService.login(user)!=null){
        //页面跳转
            request.getRequestDispatcher("pages/user/login_success.jsp").forward(request,response);
        }else {
            request.getRequestDispatcher("pages/user/regist.jsp").forward(request,response);
        }
    }
}

  • 测试工具类

package com.atguigu.test;

import com.atguigu.dao.UserDao;
import com.atguigu.dao.impl.UserDaoImpl;
import com.atguigu.pojo.User;
import org.junit.Test;

import static org.junit.Assert.*;

public class UserDaoImplTest {
    UserDao userDao=new UserDaoImpl();
    @Test
    public void queryUserByUsername() {
        User user = new User();
        user=userDao.queryUserByUsername("何艳莹");
        System.out.println(user);
    }

    @Test
    public void queryUserByUsernameAndPassword() {
        System.out.println(userDao.queryUserByUsernameAndPassword("何艳莹","123"));
    }

    @Test
    public void saveUser() {

        System.out.println(userDao.saveUser(new User("何艳莹","123","he@163.com")));
    }
}

代码优化

  • 将所有html页面改成jsp页面并在页面引入jsp标签

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
  • 将所有页面共有的内容用jsp静态包含替换,将共同内容抽取到common文件夹下

在这里插入图片描述
在这里插入图片描述

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div id="bottom">
			<span>
				尚硅谷书城.Copyright &copy;2015
			</span>
</div>

把下面代码到页面原有位置替换

<%@include file="/pages/common/foot.jsp"%>
  • 动态base标签

如果别的ip访问会发现有些css样式还是localhost访问,会产生错误,是因为我们把base标签写死了在这里插入图片描述

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--动态获取base标签值(工程路径)--%>
<%
    String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
%>
<base href="<%=basePath%>">
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
<script type="text/javascript" src="static/script/jquery-1.7.2.js"></script>

<%= %>是jsp规定的jsp页面写java代码的方式

  • 优化错误信息显示,登陆失败和注册重名时错误消息提示,将用户名和邮箱回显在表单。

在这里插入图片描述
将错误消息和回显的内容存在request域中

if (code.equalsIgnoreCase("abcd")) {
            if (userService.existUsername(username)){
                request.setAttribute("msg","用户名已存在");
                request.setAttribute("username",username);
                request.setAttribute("email",email);
                request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response);
            }
            else {
                userService.registUser(new User(username,password,email));
                //跳转注册成功页面
                request.getRequestDispatcher("/pages/user/regist_success.jsp").forward(request,response);
            }


        } else {
            //跳回注册页面
            request.setAttribute("msg","验证码错误");
            request.setAttribute("username",username);
            request.setAttribute("email",email);
            System.out.println("验证码["+code+"]错误");
            request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response);
        }

msg是变量可以重名,会更新值。

<div class="login_form">
	<div class="login_box">
		<div class="tit">
			<h1>注册尚硅谷会员</h1>
			<span class="errorMsg">
				<%=request.getAttribute("msg")==null?"":request.getAttribute("msg")%> 
			</span>
		</div>
		<div class="form">
			<form action="registServlet" method="post">
				<label>用户名称:</label>
				<input class="itxt" type="text" placeholder="请输入用户名"
					   autocomplete="off" tabindex="1" name="username" id="username"
					 
				/>
				<br />
				<br />
				<label>用户密码:</label>
				<input class="itxt" type="password" placeholder="请输入密码"
					   autocomplete="off" tabindex="1" name="password" id="password" />
				<br />
				<br />
				<label>确认密码:</label>
				<input class="itxt" type="password" placeholder="确认密码"
					   autocomplete="off" tabindex="1" name="repwd" id="repwd" />
				<br />
				<br />
				<label>电子邮件:</label>
				<input class="itxt" type="text" placeholder="请输入邮箱地址"
					   autocomplete="off" tabindex="1" name="email" id="email"
					   value="<%=request.getAttribute("msg")==null?"":request.getAttribute("email")%>"
				/>
				<br />
				<br />
				<label>验证码:</label>
				<input class="itxt" type="text" style="width: 150px;" id="code" name="code"/>
				<img alt="" src="static/img/code.bmp" style="float: right; margin-right: 40px">
				<br />
				<br />
				<input type="submit" value="注册" id="sub_btn" />
			</form>
		</div>

	</div>
</div>
  • 通过反射合并loginservlet和registservlet为userservlet

在登录和注册页面上设置一个隐藏域名字叫action,值为方法名字,比如登录页面值是登录和注册页面值为注册。通过获取action值判断应该执行什么操作。但是这样会使页面代码太杂乱,所以在userservlet页面将操作抽取为方法,通过反射调用方法,就避免了很多ifelse语句
在这里插入图片描述
上面是登录页面的隐藏域

package com.atguigu.web;

import com.atguigu.pojo.User;
import com.atguigu.service.impl.UserServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

public class UserServlet extends HttpServlet {
    UserServiceImpl userService = new UserServiceImpl();

    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = new User(username, password, null);
        if (userService.login(user)!=null){
            request.getRequestDispatcher("pages/user/login_success.jsp").forward(request,response);
        }else {
            //将错误信息放到request域中
            request.setAttribute("Msg","用户名或密码错误");
            request.setAttribute("username",username);
            request.getRequestDispatcher("pages/user/login.jsp").forward(request,response);
        }
    }
    protected void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取表单里的参数  input的name名字获取
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String email = request.getParameter("email");
        String code = request.getParameter("code");

        if (code.equalsIgnoreCase("abcd")) {
            if (userService.existUsername(username)){
                request.setAttribute("msg","用户名已存在");
                request.setAttribute("username",username);
                request.setAttribute("email",email);
                request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response);
            }
            else {
                userService.registUser(new User(username,password,email));
                //跳转注册成功页面
                request.getRequestDispatcher("/pages/user/regist_success.jsp").forward(request,response);
            }


        } else {
            //跳回注册页面
            request.setAttribute("msg","验证码错误");
            request.setAttribute("username",username);
            request.setAttribute("email",email);
            request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response);
        }
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取jsp页面隐藏域action值
        String action = request.getParameter("action");
        try {
//            获取action业务鉴别字符串,获取相应的业务方法反射对象
            Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
//            调用目标业务方法
            method.invoke(this,request,response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

action值和调用方法同名,所以反射就可以用。

  • 将userservlet和其他以后可能会有的bookservlet等共同需要的反射的那部分代码抽取成一个抽象类Baseservlet让userservlet继承于Baseservlet

package com.atguigu.web;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

public abstract class BaseServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取jsp页面隐藏域action值
        String action = request.getParameter("action");
        try {
//            获取action业务鉴别字符串,获取相应的业务方法反射对象
            Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
//            调用目标业务方法
            method.invoke(this,request,response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
这样它继承了父类的dopost方法,进入父类dopost执行,之后反射执行子类方法。

  • BeanUtils工具类使用

可以把bean对象一次性注入进来,省去大量使用get和set方法但是表单的name属性必须和类的属性名字一样。
利用beanuntils工具类封装了一个webuntils工具类

package com.atguigu.web;

import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

public class WebUtils {
public  static <T> T copyParamToBean(Map value, T bean){
        try {
            BeanUtils.populate(bean,value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }
}

在这里插入图片描述
可以省去上面那些get方法,直接将map键值对注入到user中。

  • 使用EL修改表单回显

在这里插入图片描述
全部修改

图书模块

  • 建立数据库t_book表,编写Book类,Bookdao以及BookDaoImpl

package com.atguigu.dao.impl;

import com.atguigu.dao.BookDao;
import com.atguigu.pojo.Book;


import java.util.List;

public class BookDaoImpl extends BaseDao implements BookDao {
    @Override
    public int addBook(Book book) {
        String sql="insert into t_book(`name` , `author` , `price` , `sales` , `stock` , `img_path`)values(?,?,?,?,?,?)";
        return update(sql,book.getName(),book.getAuthor(),book.getPrice(),book.getSales(),book.getStock(),book.getImg_path());

    }

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

    @Override
    public int updateBook(Book book) {
        String sql="update t_book set `name`=?,`author`=?,`price`=?,`sales`=?,`stock`=?,`img_path`=?where id=?";
        return update(sql,book.getName(),book.getAuthor(),book.getPrice(),book.getSales(),book.getStock(),book.getImg_path(),book.getId());
    }

    @Override
    public Book queryBookById(Integer id) {
        String sql="select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` from t_book where id=? ";
        return queryForOne(sql,Book.class,id);
    }

    @Override
    public List<Book> queryBooks() {
        String sql= "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` from t_book";
        return queryForList(sql,Book.class);
    }
}

  • 编写bookservice和bookservletimpl

package com.atguigu.service.impl;

import com.atguigu.dao.BookDao;
import com.atguigu.dao.impl.BookDaoImpl;
import com.atguigu.pojo.Book;
import com.atguigu.service.BookService;

import java.util.List;

public class BookServiceImpl implements BookService {
    private BookDao bookDao= new BookDaoImpl();
    @Override
    public void addBook(Book book) {
        bookDao.addBook(book);
    }

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

    @Override
    public void updateBook(Book book) {
        bookDao.updateBook(book);
    }

    @Override
    public Book queryBookById(Integer id) {
        return bookDao.queryBookById(id);
    }

    @Override
    public List<Book> queryBooks() {
        return bookDao.queryBooks();
    }
}

  • 编写bookservlet

  1. 注意先编写list方法,先显示所有图书在页面才能添加删除图书,list方法需要获取数据库所有图书,但是jsp页面无法访问数据库,访问数据库的操作都在dao层,service层可以访问dao层,而servlet可以访问service层,所以我们点击manger.jsp上的图书馆管理不能直接跳book_manger,而是通过servlet的请求转发,因为请求转发共享一个request域,我们可以将数据库图书存到request域,然后在页面上遍历request域的图书。

在这里插入图片描述
common下的manger_menu修改路径

<div>
<%--    action 表示调用bookservlet的哪个方法--%>
    <a href="manager/bookservlet?action=list">图书管理</a>
    <a href="order_manager.jsp">订单管理</a>
    <a href="../../index.jsp">返回商城</a>
</div>

注意action表示调用 bookservlet哪个方法名(和前面登录注册一样通过父类baseservlet的 dopost方法反射调用子类方法),携带上action参数转发

  1. 编写add方法

点击bookmanger上的添加跳转book_edit页面,所以去修改bookedit的表单action并添加隐藏域,修改下面input的book_name等和book类名字一样,否则beanuntils封装失败。

<div id="main">
	<form action="manager/bookservlet" method="get">
		<input type="hidden" name="action" value="add">			

跳转的时候不能使用请求转发,因为请求转发是一次操作,刷新页面会再次执行,书会重复被存两边。所以用请求重定向合适。重定向注意路径。

  1. 删除方法
    在页面删除地方设置action和id以及跳转路径
<c:forEach items="${requestScope.books}" var="book">
			<tr>
				<td>${book.name}</td>
				<td>${book.price}</td>
				<td>${book.author}</td>
				<td>${book.sales}</td>
				<td>${book.stock}</td>
				<td><a href="book_edit.jsp">修改</a></td>
				<td><a href="manager/bookservlet?action=delete&id=${book.id}">删除</a></td>
			</tr>
			</c:forEach>

给删除添加单击事件,弹窗确认

<script type="text/javascript">
	// 给删除绑定单击事件
	$(function () {
		$("a.deleteClass").click(function () {
			return confirm("你确定要删除【"+$(this).parent().parent().find("td:first").text()+"】?");
		})
	})
</script>
  1. 修改方法

思路是,点击删除跳转到book_edit.jsp页面,这个页面显示要修改的图书信息。这个页面如何获得图书的信息,还是要通过servlet,将bookmanager的图书信息传到request域,再转发到book_edit.jsp。然后修改,获取请求参数,封装成bean对象,调用bookservice.update更新数据,重定向回图书列表管理页面list。
有个问题是,添加和修改都要用到book_edit.jsp的隐藏域,那action怎么区别

  • 通过让修改和添加携带method来区分
    在这里插入图片描述
<input type="hidden" name="action" value="${param.method}">
  • 通过是否携带参数有id
    在这里插入图片描述在这里插入图片描述
<input type="hidden" name="action" value="${empty param.id?"add":"update"}">
  • 通过request域book对象是不是空,修改要回显,所以request域有book对象,添加没有。
<input type="hidden" name="action" value="${empty requestScope.book?"add":"update"}">

注意仅仅这样也不能修改,因为bookdaoimpl里update需要id。而bookedit提交给bookservlet的时候没有携带id的值,所以表单再增加一个隐藏域负责传参。

<input type="hidden" name="action" value="${empty requestScope.book?"add":"update"}">
<input type="hidden" name="id" value="${requestScope.book.id}">

点修改跳转回bookservlet时为了在bookedit回显,是携带着id的,所以request域中有id,用requestScope获取request域就能得到id。
在这里插入图片描述
最终bookservice如下

package com.atguigu.web;

import com.atguigu.pojo.Book;
import com.atguigu.service.impl.BookServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

public class BookServlet extends BaseServlet {
    BookServiceImpl bookService = new BookServiceImpl();
   protected void add(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
//    1,获取请求参数,封装成bean对象
       Book book=WebUtils.copyParamToBean(request.getParameterMap(),new Book());
//    2,调用bookservice保存图书
       bookService.addBook(book);
//    3,跳转到图书列表页面,book_manger.jsp
//       request.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(request,response);
       response.sendRedirect(request.getContextPath()+"/manager/bookservlet?action=list");
   }
    protected void delete(HttpServletRequest request,HttpServletResponse response) throws IOException {
        int id =WebUtils.parseInt(request.getParameter("id"),0);
        bookService.deleteBookById(id);
        response.sendRedirect(request.getContextPath()+"/manager/bookservlet?action=list");

    }
    protected void update(HttpServletRequest request,HttpServletResponse response) throws IOException {
    //1,获取请求参数,封装成bean对象\
        Book book=WebUtils.copyParamToBean(request.getParameterMap(),new Book());
    //2,调用bookservice.update更新数据
        bookService.updateBook(book);
    //3,重定向回图书列表管理页面list
        response.sendRedirect(request.getContextPath()+"/manager/bookservlet?action=list");

    }
    //在bookedit回显修改的数据
    protected void getBook(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
        int id =WebUtils.parseInt(request.getParameter("id"),0);
        Book book = bookService.queryBookById(id);
        request.setAttribute("book",book);
        request.getRequestDispatcher("/pages/manager/book_edit.jsp").forward(request,response);
    }

    protected void list(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
//    1,通过bookservice调用dao层从数据库查询全部图书
        List<Book> bookList = bookService.queryBooks();
//    2,将全部图书保存在request域中
        request.setAttribute("books",bookList);
//    3,请求转发到book_manger.jsp
        request.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(request,response);
    }
}

  • 图书分页

思路,架构
在这里插入图片描述

  • 利用session优化登录和注销

session保存登录后用户信息,使韩总处显示登录后用户名,返回index页面时显示登录状态。
在这里插入图片描述
在这里插入图片描述
登录后返回首页显示用户信息,没有登录显示注册等。

<div id="header">
<img class="logo_img" alt="" src="static/img/logo.png" >
	<span class="wel_word">网上书城</span>
	<div>
		<c:if test="${empty sessionScope.loginuser}">
			<a href="pages/user/login.jsp">登录</a> |
			<a href="pages/user/regist.jsp">注册</a> &nbsp;
		</c:if>
		<c:if test="${not empty sessionScope.loginuser}">
			<span>欢迎<span class="um_span">${sessionScope.loginuser.username}</span>光临尚硅谷书城</span>
			<a href="pages/order/order.jsp">我的订单</a>
			<a href="userservlet?action=logout">注销</a>&nbsp;&nbsp;
		</c:if>&nbsp;
		<a href="pages/cart/cart.jsp">购物车</a>
		<a href="pages/manager/manager.jsp">后台管理</a>
	</div>
</div>

userservlet添加注销方法

//    注销
    protected void logout(HttpServletRequest request,HttpServletResponse response) throws IOException {
//        销毁session
        request.getSession().invalidate();
//         重定向
        response.sendRedirect(request.getContextPath());
    }

在这里插入图片描述
在这里插入图片描述

表单重复提交之验证码

在这里插入图片描述

  • 验证码第三方提供了jar包,谷歌kaptcha,在web.xml中配置生成验证码的servlet类,jar包自带。会生成验证码并存在session中。
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
  • 去表单img标签显示。
<br />
<label>验证码:</label>
<input class="itxt" type="text" style="width: 90px;" id="code" name="code"/>
<img alt="" src="kaptcha.jpg" style="float: right; margin-right: 40px"; width="110px"; height="40px">
<br />
  • 在服务器获取谷歌生成的验证码和客户端发送的验证码比较。
 protected void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取session中验证码
        String token = (String) request.getSession().getAttribute(KAPTCHA_SESSION_KEY);
        //删除session
        request.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
        //获取表单里的参数  input的name名字获取
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String email = request.getParameter("email");
        String code = request.getParameter("code");
        User user= WebUtils.copyParamToBean(request.getParameterMap(),new User());

        if (token!=null&&token.equalsIgnoreCase(code)) {
            if (userService.existUsername(username)){
                request.setAttribute("msg","用户名已存在");
  • 再实现看不清验证码刷新
    给验证码图片绑定单击事件
<script>
$(function () {
	$("#code_img").click(function () {
//修改当前dom对象的路径就会刷新,防止浏览器缓存加上时间
		this.src="${basePath}/bookstore/kaptcha.jpg?d="+new Date();
})

});
</script>

购物车模块

在这里插入图片描述
因为这次用session存放购物车,所以没用到数据库dao层,所以方法没写在service层,而是写在了类方法里。

  • 创建购物车里的商品类和购物车类,cartitems和cart

package com.atguigu.pojo;

import java.math.BigDecimal;

/**
 * 购物车的商品项
 */
public class CartItem {
    private Integer id;
    private String name;
    private Integer count;
    private BigDecimal price;
    private BigDecimal totalPrice;

    public CartItem() {
    }

    public CartItem(Integer id, String name, Integer count, BigDecimal price, BigDecimal totalPrice) {
        this.id = id;
        this.name = name;
        this.count = count;
        this.price = price;
        this.totalPrice = totalPrice;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getCount() {
        return count;
    }

    public void setCount(Integer count) {
        this.count = count;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public BigDecimal getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(BigDecimal totalPrice) {
        this.totalPrice = totalPrice;
    }

    @Override
    public String toString() {
        return "CartItem{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", count=" + count +
                ", price=" + price +
                ", totalPrice=" + totalPrice +
                '}';
    }
}

package com.atguigu.pojo;

import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 购物车对象
 */
public class Cart {
//    private Integer totalCount;
//    private BigDecimal totalPrice;

    /**
     * key是商品编号,
     * value,是商品信息
     */
    private Map<Integer,CartItem> items = new LinkedHashMap<Integer,CartItem>();

    /**
     * 添加商品项
     *
     * @param cartItem
     */
    public void addItem(CartItem cartItem) {
        // 先查看购物车中是否已经添加过此商品,如果已添加,则数量累加,总金额更新,如果没有添加过,直接放到集合中即可
        CartItem item = items.get(cartItem.getId());

        if (item == null) {
            // 之前没添加过此商品
            items.put(cartItem.getId(), cartItem);
        } else {
            // 已经 添加过的情况
            item.setCount( item.getCount() + 1 ); // 数量 累加
            item.setTotalPrice( item.getPrice().multiply(new BigDecimal( item.getCount() )) ); // 更新总金额
        }

    }

    /**
     * 删除商品项
     */
    public void deleteItem(Integer id) {
        items.remove(id);
    }


    /**
     * 清空购物车
     */
    public void clear() {
        items.clear();
    }

    /**
     * 修改商品数量
     */
    public void updateCount(Integer id,Integer count) {
        // 先查看购物车中是否有此商品。如果有,修改商品数量,更新总金额
        CartItem cartItem = items.get(id);
        if (cartItem != null) {
            cartItem.setCount(count);// 修改商品数量
            cartItem.setTotalPrice( cartItem.getPrice().multiply(new BigDecimal( cartItem.getCount() )) ); // 更新总金额
        }
    }


    public Integer getTotalCount() {
        Integer totalCount = 0;
//        Map的entrySet()方法返回一个实现Map.Entry接口的对象集合
        for (Map.Entry<Integer,CartItem> entry : items.entrySet()) {
            totalCount += entry.getValue().getCount();
        }

        return totalCount;
    }


    public BigDecimal getTotalPrice() {
        BigDecimal totalPrice = new BigDecimal(0);

        for (Map.Entry<Integer,CartItem>entry : items.entrySet()) {
            totalPrice = totalPrice.add(entry.getValue().getTotalPrice());
        }

        return totalPrice;
    }


    public Map<Integer, CartItem> getItems() {
        return items;
    }

    public void setItems(Map<Integer, CartItem> items) {
        this.items = items;
    }

    @Override
    public String toString() {
        return "Cart{" +
                "totalCount=" + getTotalCount() +
                ", totalPrice=" + getTotalPrice() +
                ", items=" + items +
                '}';
    }
}

这个购物车有点小难难,用map集合来存放购物车里商品。总数量总价直接在get里计算。

filter过滤器防止未登录用户进入后台页面

在这里插入图片描述
新建一个filter包,建一个ManagerFilter类

package com.atguigu.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class ManagerFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest=(HttpServletRequest)servletRequest;
        Object user = httpServletRequest.getSession().getAttribute("loginuser");
        if (user==null){
            httpServletRequest.getRequestDispatcher("/pages/user/login.jsp").forward(servletRequest,servletResponse);
        }else {
            filterChain.doFilter(servletRequest,servletResponse);
        }

    }

    @Override
    public void destroy() {

    }
}

web.xml配置

 <filter>
        <filter-name>ManagerFilter</filter-name>
        <filter-class>com.atguigu.filter.ManagerFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ManagerFilter</filter-name>
        <url-pattern>/pages/manager/*</url-pattern>
        <url-pattern>/manager/bookservlet</url-pattern>
    </filter-mapping>

防止进入后台servlet所以设置了两个拦截路径。

项目做崩了,sorry,我认输。在分页那里,我太难了。。。。。。。。。。。但是还是学到好多呜呜呜呜。。。。。跳图书管理页面是空白的,可能没得到request域的值,但是debug显示存进去了,控制台报错。

java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:542)
at java.lang.Integer.parseInt(Integer.java:615)
at com.atguigu.web.WebUtils.parseInt(WebUtils.java:20)
at com.atguigu.web.BookServlet.page(BookServlet.java:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atguigu.web.BaseServlet.doPost(BaseServlet.java:18)
at com.atguigu.web.BaseServlet.doGet(BaseServlet.java:24)

  • 8
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值