网上书城项目

  • 第一阶段:使用JavaScript对register.html页面实现表单验证
    • 需求
    • 代码实现
  • 第二阶段 :实现用户的注册和登录
    • 需求1:用户注册
    • 需求2:用户登陆
    • 需要提前掌握的知识
    • 搭建书城项目开发环境
    • 代码实现
      • 2.1 先创建书城需要的数据库和表
      • 2.2 编写数据库对应的JavaBean对象
      • 2.3 编写工具类JDbc.Utils
        • 2.3.1 导入需要的 jar 包(数据库和连接池需要)
        • 2.3.2 在 src 源码目录下编写 jdbc.properties 属性配置文件
        • 2.3.3 编写 JdbcUtils 工具类
        • 2.3.4 JdbcUtils 测试
    • 2.4 编写BaseDao
      • 2.4.1 导入DBUtils的jar包
      • 2.4.2 编写BaseDao
    • 2.5 编写UserDao和测试
      • 2.5.1 UserDao接口
      • 2.5.2 UserDao实现类
      • 2.5.3 UserDao测试
    • 2.6 编写 UserService 和测试
      • 2.6.1 UserService接口
      • 2.6.2 UserService实现类
      • 2.6.3 UserService测试
    • 2.7 编写web层
      • 2.7.1 实现用户注册功能
        • 2.7.1.1 图解用户注册流程
        • 2.7.1.2 修改regist.html和regist_success.html页面
        • 2.7.1.3 编写 RegistServlet 程序
      • 2.7.2 实现用户登录功能
        • 2.7.2.1 图解用户登录流程
        • 2.7.2.2 修改login.html和login_success.html页面
        • 2.7.2.3 编写LoginServlet 程序
  • 第三阶段:代码优化
    • 3.1 页面jsp动态化
    • 3.2 抽取页面中相同的内容
    • 3.3 登录,注册错误提示以及及表单回显
    • 3.4 BaseServlet 的抽取
      • 3.4.1 代码优化一:合并 LoginServlet 和 RegistServlet 程序为 UserServlet
      • 3.4.2 代码优化二:使用反射优化大量 else if 代码
      • 3.4.3 代码优化三:抽取 BaseServlet 程序
    • 3.5 数据的封装和抽取 BeanUtils 的使用

第一阶段:使用JavaScript对register.html页面实现表单验证

需求

  • 验证用户名:必须由字母,数字下划线组成,并且长度为 5 到 12 位
  • 验证密码:必须由字母,数字下划线组成,并且长度为 5 到 12 位
  • 验证确认密码:和密码相同
  • 邮箱验证:xxxxx@xxx.com
  • 验证码:现在只需要验证用户已输入。因为还没讲到服务器。验证码生成

代码实现

<script type="text/javascript">// 页面加载完成之后$(function () {// 给注册绑定单击事件$("#sub_btn").click(function () {// 验证用户名:必须由字母,数字下划线组成,并且长度为5到12位//1 获取用户名输入框里的内容var usernameText = $("#username").val();//2 创建正则表达式对象var usernamePatt = /^\w{5,12}$/;//3 使用test方法验证if (!usernamePatt.test(usernameText)) {//4 提示用户结果$("span.errorMsg").text("用户名不合法!");return false;}// 验证密码:必须由字母,数字下划线组成,并且长度为5到12位//1 获取用户名输入框里的内容var passwordText = $("#password").val();//2 创建正则表达式对象var passwordPatt = /^\w{5,12}$/;//3 使用test方法验证if (!passwordPatt.test(passwordText)) {//4 提示用户结果$("span.errorMsg").text("密码不合法!");return false;}// 验证确认密码:和密码相同//1 获取确认密码内容var repwdText = $("#repwd").val();//2 和密码相比较if (repwdText != passwordText) {//3 提示用户$("span.errorMsg").text("确认密码和密码不一致!");return false;}// 邮箱验证:xxxxx@xxx.com//1 获取邮箱里的内容var emailText = $("#email").val();//2 创建正则表达式对象var emailPatt = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/;//3 使用test方法验证是否合法if (!emailPatt.test(emailText)) {//4 提示用户$("span.errorMsg").text("邮箱格式不合法!");return false;}// 验证码:现在只需要验证用户已输入。因为还没讲到服务器。验证码生成。var codeText = $("#code").val();//去掉验证码前后空格// alert("去空格前:["+codeText+"]")codeText = $.trim(codeText);// alert("去空格后:["+codeText+"]")if (codeText == null || codeText == "") {//4 提示用户$("span.errorMsg").text("验证码不能为空!");return false;}// 去掉错误信息$("span.errorMsg").text("");});});</script>

第二阶段 :实现用户的注册和登录

需求1:用户注册

需求如下:

  1. 访问注册页面
  2. 填写注册信息,提交给服务器
  3. 服务器应该保存用户
  4. 当用户已经存在----提示用户注册 失败,用户名已存在
  5. 当用户不存在-----注册成功

需求2:用户登陆

需求如下:

  1. 访问登陆页面
  2. 填写用户名密码后提交
  3. 服务器判断用户是否存在
  4. 如果登陆失败 —>>>> 返回用户名或者密码错误信息
  5. 如果登录成功 —>>>> 返回登录成功信息

需要提前掌握的知识

JavaEE 项目的三层架构:

搭建书城项目开发环境

代码实现

2.1 先创建书城需要的数据库和表

create table t_book(id int primary key auto_increment,name varchar(100) not null,price decimal(11,2) not null,author varchar(100) not null,sales int not null,stock int not null,img_path varchar(200) not null
);
insert into t_book(id , name , author , price , sales , stock , img_path)
values(null , '数据结构与算法' , '严敏君' , 78.5 , 6 , 13 , 'static/img/default.jpg');
...
select id,name,author,price,sales,stock,img_path from t_book;

2.2 编写数据库对应的JavaBean对象

public class User {private Integer id;private String username;private String password;private String email;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", email='" + email + '\'' +'}';}public User() {}public User(Integer id, String username, String password, String email) {this.id = id;this.username = username;this.password = password;this.email = email;}
}

2.3 编写工具类JDbc.Utils

2.3.1 导入需要的 jar 包(数据库和连接池需要)

druid-1.1.9.jar
mysql-connector-java-5.1.7-bin.jar以下是测试需要:
hamcrest-core-1.3.jar
junit-4.12.jar

2.3.2 在 src 源码目录下编写 jdbc.properties 属性配置文件

username=root
password=888
url=jdbc:mysql://localhost:3306/book
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10

2.3.3 编写 JdbcUtils 工具类

public class JdbcUtils {private static DruidDataSource dataSource;static {try {Properties properties = new Properties();// 读取 jdbc.properties属性配置文件InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");// 从流中加载数据properties.load(inputStream);// 创建 数据库连接 池dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}/*** 获取数据库连接池中的连接* @return 如果返回null,说明获取连接失败<br/>有值就是获取连接成功*/public static Connection getConnection(){Connection conn = null;try {conn = dataSource.getConnection();} catch (Exception e) {e.printStackTrace();}return conn;}/*** 关闭连接,放回数据库连接池* @param conn*/public static void close(Connection conn){if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}}

2.3.4 JdbcUtils 测试

public class JdbcUtilTest {@Testpublic void testJdbcUtils(){//        for(int i = 0; i < 100; i++){//            Connection conn = JdbcUtils.getConnection();
//            System.out.println(conn);
//            JdbcUtils.close(conn);
//        }}}

2.4 编写BaseDao

2.4.1 导入DBUtils的jar包

commons-dbutils-1.3.jar

2.4.2 编写BaseDao

public abstract class BaseDao {//使用DbUtils操作数据库private QueryRunner queryRunner = new QueryRunner();/*** update() 方法用来执行:Insert\Update\Delete语句** @return 如果返回-1,说明执行失败<br/>返回其他表示影响的行数*/public int update(String sql, Object... args) {Connection connection = JdbcUtils.getConnection();try {return queryRunner.update(connection, sql, args);} catch (SQLException e) {e.printStackTrace();} finally {JdbcUtils.close(connection);}return -1;}/*** 查询返回一个javaBean的sql语句** @param type 返回的对象类型* @param sql  执行的sql语句* @param args sql对应的参数值* @param <T>  返回的类型的泛型* @return*/public <T> T queryForOne(Class<T> type, String sql, Object... args) {Connection con = JdbcUtils.getConnection();try {return queryRunner.query(con, sql, new BeanHandler<T>(type), args);} catch (SQLException e) {e.printStackTrace();} finally {JdbcUtils.close(con);}return null;}/*** 查询返回多个javaBean的sql语句** @param type 返回的对象类型* @param sql  执行的sql语句* @param args sql对应的参数值* @param <T>  返回的类型的泛型* @return*/public <T> List<T> queryForList(Class<T> type, String sql, Object... args) {Connection con = JdbcUtils.getConnection();try {return queryRunner.query(con, sql, new BeanListHandler<T>(type), args);} catch (SQLException e) {e.printStackTrace();} finally {JdbcUtils.close(con);}return null;}/*** 执行返回一行一列的sql语句* @param sql   执行的sql语句* @param args  sql对应的参数值* @return*/public Object queryForSingleValue(String sql, Object... args){Connection conn = JdbcUtils.getConnection();try {return queryRunner.query(conn, sql, new ScalarHandler(), args);} catch (Exception e) {e.printStackTrace();} finally {JdbcUtils.close(conn);}return null;}}

2.5 编写UserDao和测试

2.5.1 UserDao接口

public interface UserDao {/*** 根据用户名查询用户信息* @param username* @return 如果返回null,说明没有这个用户。*/public User queryUserByUsername(String username);/*** 保存用户信息* @param user* @return 返回-1表示操作失败,其他是sql语句影响的行数*/public int saveUser(User user);/*** 根据用户名和密码查询用户信息* @param username* @param password* @return 如果返回null,说明用户名或密码错误。*/public User queryUserByUsernameAndPwd(String username, String password);
}

2.5.2 UserDao实现类

public class UserDaoImpl extends BaseDao implements UserDao {@Overridepublic User queryUserByUsername(String username) {String sql = "select `id`,`username`,`password`,`email` from t_user where username = ?";return queryForOne(User.class, sql, username);}@Overridepublic User queryUserByUsernameAndPassword(String username, String password) {String sql = "select `id`,`username`,`password`,`email` from t_user where username = ? and password = ?";return queryForOne(User.class, sql, username,password);}@Overridepublic int saveUser(User user) {String sql = "insert into t_user(`username`,`password`,`email`) values(?,?,?)";return update(sql, user.getUsername(),user.getPassword(),user.getEmail());}
}

2.5.3 UserDao测试

public class UserDaoTest {public UserDao userDao = new UserDaoImpl();@Testpublic void queryUserByUsername() {if(userDao.queryUserByUsername("admin12") == null){System.out.println("用户名可用!");} else{System.out.println("用户名已存在!");}}@Testpublic void saveUser() {System.out.println(userDao.saveUser(new User(null, "lisi", "111", "lisi@163.com")));}@Testpublic void queryUserByUsernameAndPwd() {if(userDao.queryUserByUsernameAndPwd("admin", "admin") == null){System.out.println("您输入的用户名或密码有误,登录失败");} else{System.out.println("登录成功!");}}
}

2.6 编写 UserService 和测试

2.6.1 UserService接口

public interface UserService {/*** 注册用户* @param user*/public void registUser(User user);/*** 登录* @param user* @return 如果返回null,说明登录失败,返回有值,是登录成功*/public User login(User user);/*** 检查 用户名是否可用* @param username* @return 返回true表示用户名已存在,返回false表示用户名可用*/public boolean existsUsername(String username);
}

2.6.2 UserService实现类

public class UserServiceImpl implements UserService {private UserDao userDao = new UserDaoImpl();@Overridepublic void registUser(User user) {userDao.saveUser(user);}@Overridepublic User login(User user) {return userDao.queryUserByUsernameAndPassword(user.getUsername(), user.getPassword());}@Overridepublic boolean existsUsername(String username) {if (userDao.queryUserByUsername(username) == null) {// 等于null,说明没查到,没查到表示可用return false;}return true;}
}

2.6.3 UserService测试

public class UserServiceTest {UserService userService = new UserServiceImpl();@Testpublic void registUser() {userService.registUser(new User(null, "admin", "666", "zs@168.com"));}@Testpublic void login() {System.out.println(userService.login(new User(null, "zs", "666", null)));}@Testpublic void existsUsername() {if(userService.existsUsername("88")){System.out.println("用户名已存在");} else{System.out.println("用户名可用!");}}
}

2.7 编写web层

2.7.1 实现用户注册功能

2.7.1.1 图解用户注册流程

2.7.1.2 修改regist.html和regist_success.html页面

  • 添加base标签
<!--写 base 标签,永远固定相对路径跳转的结果--><base href="http://localhost:8080/book/">
  • 修改base标签对页面中所有相对路径的影响(浏览器F12,哪个报红,改哪个)
  • 修改regist.html表单的提交地址和请求方式

2.7.1.3 编写 RegistServlet 程序

public class RegistServlet extends HttpServlet {private UserService userService = new UserServiceImpl();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//  1、获取请求的参数String username = req.getParameter("username");String password = req.getParameter("password");String email = req.getParameter("email");String code = req.getParameter("code");//        2、检查 验证码是否正确  === 写死,要求验证码为:abcdeif ("abcde".equalsIgnoreCase(code)) {//        3、检查 用户名是否可用if (userService.existsUsername(username)) {System.out.println("用户名[" + username + "]已存在!");
//        跳回注册页面req.getRequestDispatcher("/pages/user/regist.html").forward(req, resp);} else {//      可用
//                调用Sservice保存到数据库userService.registUser(new User(null, username, password, email));
//
//        跳到注册成功页面 regist_success.htmlreq.getRequestDispatcher("/pages/user/regist_success.html").forward(req, resp);}} else {System.out.println("验证码[" + code + "]错误");req.getRequestDispatcher("/pages/user/regist.html").forward(req, resp);}}
}

2.7.2 实现用户登录功能

2.7.2.1 图解用户登录流程

2.7.2.2 修改login.html和login_success.html页面

  • 添加base标签
<!--写 base 标签,永远固定相对路径跳转的结果--><base href="http://localhost:8080/book/">
  • 修改base标签对页面中所有相对路径的影响(浏览器F12,哪个报红,改哪个)
  • 修改login.html表单的提交地址和请求方式

2.7.2.3 编写LoginServlet 程序

public class LoginServlet extends HttpServlet {private UserService userService = new UserServiceImpl();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//  1、获取请求的参数String username = req.getParameter("username");String password = req.getParameter("password");// 调用 userService.login()登录处理业务User loginUser = userService.login(new User(null, username, password, null));// 如果等于null,说明登录 失败!if (loginUser == null) {//   跳回登录页面req.getRequestDispatcher("/pages/user/login.html").forward(req, resp);} else {// 登录 成功//跳到成功页面login_success.htmlreq.getRequestDispatcher("/pages/user/login_success.html").forward(req, resp);}}
}

第三阶段:代码优化

3.1 页面jsp动态化

  • 在 html 页面顶行添加 page 指令

    <%@pagecontentType="text/html;charset=UTF-8"language="java"%>
    
  • 修改所有的.html文件后缀名为:.jsp
  • 使用 IDEA 搜索替换原html文件中包含.html 的地方为.jsp(快捷键:Ctrl+Shift+R)

3.2 抽取页面中相同的内容

  • head 中 css、jquery、base 标签

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%String basePath = request.getScheme()+ "://"+ request.getServerName()+ ":"+ request.getServerPort()+ request.getContextPath()+ "/";
    %><!--写base标签,永远固定相对路径跳转的结果-->
    <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>
    
  • 每个页面的页脚

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <div id="bottom"><span>小刘书城.Copyright &copy;2020</span>
    </div>
    
  • 登录成功后的菜单

    <%@ page contentType="text/html;charset=UTF-8" language="java" %><div><span>欢迎<span class="um_span">x总</span>光临小刘书城</span><a href="../order/order.jsp">我的订单</a><a href="../../index.jsp">注销</a>&nbsp;&nbsp;<a href="../../index.jsp">返回</a>
    </div>
    
  • manager 模块的菜单

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <div><a href="book_manager.jsp">图书管理</a><a href="order_manager.jsp">订单管理</a><a href="../../index.jsp">返回商城</a>
    </div>
    

3.3 登录,注册错误提示以及及表单回显

public class LoginServlet extends HttpServlet {private UserService userService = new UserServiceImpl();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//  1、获取请求的参数String username = req.getParameter("username");String password = req.getParameter("password");// 调用 userService.login()登录处理业务User loginUser = userService.login(new User(null, username, password, null));// 如果等于null,说明登录 失败!if (loginUser == null) {// 把错误信息,和回显的表单项信息,保存到Request域中req.setAttribute("msg","用户或密码错误!");req.setAttribute("username", username);//   跳回登录页面req.getRequestDispatcher("/pages/user/login.jsp").forward(req, resp);} else {// 登录 成功//跳到成功页面login_success.htmlreq.getRequestDispatcher("/pages/user/login_success.jsp").forward(req, resp);}}
}
<span class="errorMsg">${ empty requestScope.msg ? "请输入用户名和密码":requestScope.msg }
</span>
<label>用户名称:</label>
<input class="itxt" type="text" placeholder="请输入用户名"autocomplete="off" tabindex="1" name="username"value="${requestScope.username}" />
<br />
<br />

3.4 BaseServlet 的抽取

在实际的项目开发中,一个模块,一般只使用一个 Servlet

3.4.1 代码优化一:合并 LoginServlet 和 RegistServlet 程序为 UserServlet

  • 给 login.jsp 添加隐藏域和修改请求地址

  • 给 regist.jsp 添加隐藏域和修改请求地址

  • UserServlet 程序

    public class UserServlet extends BaseServlet {private UserService userService = new UserServiceImpl();/*** 处理登录的功能** @param req* @param resp* @throws ServletException* @throws IOException*/protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//  1、获取请求的参数String username = req.getParameter("username");String password = req.getParameter("password");// 调用 userService.login()登录处理业务User loginUser = userService.login(new User(null, username, password, null));// 如果等于null,说明登录 失败!if (loginUser == null) {// 把错误信息,和回显的表单项信息,保存到Request域中req.setAttribute("msg", "用户或密码错误!");req.setAttribute("username", username);//   跳回登录页面req.getRequestDispatcher("/pages/user/login.jsp").forward(req, resp);} else {// 登录 成功//跳到成功页面login_success.htmlreq.getRequestDispatcher("/pages/user/login_success.jsp").forward(req, resp);}}/*** 处理注册的功能** @param req* @param resp* @throws ServletException* @throws IOException*/protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//  1、获取请求的参数String username = req.getParameter("username");String password = req.getParameter("password");String email = req.getParameter("email");String code = req.getParameter("code");User user = WebUtils.copyParamToBean(req.getParameterMap(), new User());//        2、检查 验证码是否正确  === 写死,要求验证码为:abcdeif ("abcde".equalsIgnoreCase(code)) {//        3、检查 用户名是否可用if (userService.existsUsername(username)) {System.out.println("用户名[" + username + "]已存在!");// 把回显信息,保存到Request域中req.setAttribute("msg", "用户名已存在!!");req.setAttribute("username", username);req.setAttribute("email", email);//        跳回注册页面req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);} else {//      可用
    //                调用Sservice保存到数据库userService.registUser(new User(null, username, password, email));
    //
    //        跳到注册成功页面 regist_success.jspreq.getRequestDispatcher("/pages/user/regist_success.jsp").forward(req, resp);}} else {// 把回显信息,保存到Request域中req.setAttribute("msg", "验证码错误!!");req.setAttribute("username", username);req.setAttribute("email", email);System.out.println("验证码[" + code + "]错误");req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);}}}
    

3.4.2 代码优化二:使用反射优化大量 else if 代码

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

3.4.3 代码优化三:抽取 BaseServlet 程序


同3.4.2

3.5 数据的封装和抽取 BeanUtils 的使用

BeanUtils 工具类,它可以一次性的把所有请求的参数注入到 JavaBean 中。
BeanUtils 工具类,经常用于把 Map 中的值注入到 JavaBean 中,或者是对象属性值的拷贝操作。

BeanUtils 它不是 Jdk 的类。而是第三方的工具类。所以需要导包。

  1. 导入需要的jar包
    commons-beanutils-1.8.0.jar
    commons-logging-1.1.1.jar

  2. 编写 WebUtils 工具类使用:

    public class WebUtils {/*** 把Map中的值注入到对应的JavaBean属性中。* @param value* @param bean*/public static <T> T copyParamToBean( Map value , T bean ){try {System.out.println("注入之前:" + bean);/*** 把所有请求的参数都注入到user对象中*/BeanUtils.populate(bean, value);System.out.println("注入之后:" + bean);} catch (Exception e) {e.printStackTrace();}return bean;}}
    

网上书城项目——前三阶段(Java实现)相关推荐

  1. day09 书城项目第三阶段

    day09 书城项目第三阶段 1. 项目准备工作 1.1 创建Module 1.2 拷贝jar包 数据库jar包 Thymeleaf的jar包 1.3 从V2版本项目迁移代码 1.3.1 迁移src目 ...

  2. 【Java - 项目开发】网上书城项目

    网上书城项目 创作日期:2021-12-23 第一阶段 登录注册的验证(表单验证) 技术方法: 使用 jQuery 技术对登录中的用户名.密码进行非空验证 使用 jQuery 技术和正则表达式对注册中 ...

  3. 网上书城java负责_网上书城项目总结(servlet_jsp+javaBean)

    网上书城项目总结 1 项目大纲设计: 需求分析 系统设计 详细设计 权限设计 2 技术选型: Servlet+jsp+javaBean Listener+Filter+jstl+fileupload+ ...

  4. java web网上书城_javaweb网上书城项目

    [实例简介] javaweb网上书城项目,采用ssh框架,mysql数据库. [实例截图] [核心代码] bookstore └── ssh_book ├── WebContent │   ├── M ...

  5. day10 会话书城项目第四阶段

    day10 会话&书城项目第四阶段 1.会话 1.1 为什么需要会话控制 保持用户登录状态,就是当用户在登录之后,会在服务器中保存该用户的登录状态,当该用户后续访问该项目中的其它动态资源(Se ...

  6. 网上书城项目的书籍分类列表展示及新书上架和热销书籍效果展示功能(项目进度四)

    网上书城项目的书籍分类列表展示及新书上架和热销书籍效果展示功能(项目进度四) 前言 需实现的目标(效果图) 书籍分类展示 新书上架展示 热销书籍展示 1.书籍分类展示(实现动态加载数据) 1.1 加载 ...

  7. 网上书城项目之后台实现书籍分类、新书上架、热销图书

    网上书城项目 前言 书籍分类 效果演示 新书上架 效果演示 热销图书 效果演示 注意要点 总结 前言 嘿,今天为大家分享的知识点呢,是后台编码实现前端页面上的书籍分类.新书上架.热销图书这三个主要功能 ...

  8. 叮当网上书城项目简介

    叮当网上书城项目 一.项目功能 1.前台功能 图书基本展示,包括推荐图书展示和类图书类型展示. 推荐图书包括条幅推荐,热销推荐和新品推荐. 按照图书类型展示商品. 图书详细信息展示. 图书加入购物车. ...

  9. java-net-php-python-springboot网上书城项目计算机毕业设计程序

    java-net-php-python-springboot网上书城项目计算机毕业设计程序 java-net-php-python-springboot网上书城项目计算机毕业设计程序 本源码技术栈: ...

最新文章

  1. 关于在SVG中如何实现gif动画的问题?
  2. 实验:交换机生成树协议STP--功能验证
  3. 学习笔记(3.23)
  4. php vimrc配置文件,vim技巧:我的 .vimrc 配置文件,详解每一个配置项的作用
  5. 开发优秀产品的六大秘诀
  6. 微信支付PKIX path building failed
  7. 中专生计算机教案,[定稿]计算机基础教案中专V8.1(全文完整版)
  8. 大数据的说法 正确的是_数据量——让数据分析师永远头疼的指标
  9. jieba库统计出现词语次数
  10. 与context的关系_Go中的Context超时和关闭是如何实现的呢?
  11. Xshel和Xftp免费版
  12. 博客网页配色表+流行色系
  13. ATmega328P和ATmega328PB之间的差异
  14. tiny6410裸机实验第0章--------------开发环境的搭建(USB转串口)
  15. unity3d摄像机的透视有些夸张怎么办?
  16. 计算机无法加载这个项目,Windows系统中出现无法加载这个硬件的设备驱动程序(代码39)的解决方法介绍 win7...
  17. sysbench 压力测试工具(实战)
  18. 兔子数列 - C语言
  19. Unity实现摄像头录像功能
  20. 相机视频展示开源平台ISpy

热门文章

  1. HBase架构解析二
  2. 什么是Vue?什么又是vue指令?
  3. 基于优化智能算法(粒子群灰狼)的非侵入式负荷识别(NILM)建模(提供代码下载)
  4. 深入了解区块链中的挖矿过程及其意义
  5. 留学美国计算机专业被拒签,去美国留学这五大拒签率极高的专业 你敢挑战吗?...
  6. 计算机专业512g固态硬盘够吗,只有一块512G固态硬盘的电脑,需不需要分区?不存数据可以不分...
  7. 【Java】多线程与高并发
  8. CSS3制作七巧板动画
  9. 【wpf】Bingding的方向和触发的时机
  10. vue中自定义全局指令报错