Tmall_JavaEE

技术栈 Servlet + Jsp + Tomcat , 是Java Web入门非常好的练手项目

效果展示:

模仿天猫前台
模仿天猫后台

项目简介

关联项目
github - 天猫 JavaEE 项目
github - 天猫 SSH 项目
github - 天猫 SSM 项目

本项目为Java EE入门练手项目,没有使用 SSH , SSM 框架,而是使用 JavaEE 整套技术来作为解决方案,实现模仿天猫网站的各种业务场景。 之所以不使用框架,就是为了借助这个项目夯实 JavaEE 基础,并且在项目中借助反射等技术。

项目用到的技术如下:
Java:Java SE基础
前端: HTML , CSS , JavaScript , jQuery
J2EE: Tomcat , Servlet , JSP , Filter
数据库: MySQL

表结构

建表sql 已经放在 Github 项目的 /sql 文件夹下

表名 中文含义 介绍
Category 分类表 存放分类信息,如女装,平板电视,沙发等
Property 属性表 存放属性信息,如颜色,重量,品牌,厂商,型号等
Product 产品表 存放产品信息,如LED40EC平板电视机,海尔EC6005热水器
PropertyValue 属性值表 存放属性值信息,如重量是900g,颜色是粉红色
ProductImage 产品图片表 存放产品图片信息,如产品页显示的5个图片
Review 评论表 存放评论信息,如买回来的蜡烛很好用,么么哒
User 用户表 存放用户信息,如斩手狗,千手小粉红
Order 订单表 存放订单信息,包括邮寄地址,电话号码等信息
OrderItem 订单项表 存放订单项信息,包括购买产品种类,数量等

Category-分类 Product-产品
Category-分类 Property-属性
Property-属性 PropertyValue-属性值
Product-产品 PropertyValue-属性值
Product-产品 ProductImage-产品图片
Product-产品 Review-评价
User-用户 Order-订单
Product-产品 OrderItem-订单项
User-用户 OrderItem-订单项
Order-订单 OrderItem-订单项
User-用户 User-评价

以上直接看可能暂时无法完全理解,结合后面具体到项目的业务流程就明白了。


实体类设计

所谓的实体类,就是对于数据库中的表的互相映射的类。 
这是一种 ORM 的设计思想,即一个对象,对应数据库里的一条记录
举个例子,对于 评价 / review 的 实体类 和 表结构 设计如下:

已省略对应的 getter/setter 方法


DAO 类设计

DAO 是 Data Access Object 的缩写,专门用于进行数据库访问的操作。
首先看一下数据库工具类

DBUtil

这个类的作用是初始化驱动,并且提供一个 getConnection 用于获取连接,统一管理连接参数,方便后续操作。

CategoryDAO

利用 DBUtil 获取 Connectoion ,再获取对应的 Statement,利用 JDBC 从数据库取出数据,并构造成 bean 对象返回。


Service 类

作为J2EE web 应用,一般会按照如图所示的设计流程进行
Servlet -> Service(业务类) -> DAO -> database

在本模仿天猫整站 JavaEE 版本中,不使用 Service 这一层。 原因是在 DAO 进行了比较详细的设计,已经提供了很好的支持业务的方法。如果在 DAO 上包裹一层 Service 业务类,不过是在直接调用 DAO 设计好的方法罢了。另外一个使用框架的项目会用到 Service 层。


Filter 配合 Servlet

后台在系统设计的时候,并不是简单的每个功能对应一个 Servlet ,而是使用了反射的技术,结合过滤器Filter 进行了封装,使得开发配置以及维护成本降低了很多。

一个路径对应一个 Servlet 的弊端

这里以分类进行举例:
分类管理需要:增加,删除,编辑,修改,查询 5 个功能,按照传统的在 web.xml 中配置 Servlet 的思路,那么就需要 5 个 Servlet 类,而后台需要做分类,产品,属性,产品图,用户,订单 6 中管理,就一共需要30 个 Servlet,还要配置 web.xml 就会变得很乱。
解决的方法是把所有分类操作放在同一个 Servlet ,对应不同的方法。
让我们来分析,如何做到访问 admin_category_list 的时候,CategoryServlet 的 list() 方法会被调用:

  1. 假设访问路径是 /admin_category_x
  2. 过滤器 BackServletFilter 进行拦截,判断访问的地址是否以/admin_开头
  3. 如果是,那么做如下操作
    3.1 取出两个下划线之间的值 category
    3.2 取出最后一个下划线之后的值 x
    3.3 然后根据这个值,服务端跳转到 categoryServlet,并且把 x 这个值传递过去
  4. categoryServlet 继承了 BaseBackServlet,其 service 方法会被调用。 在 service 中,借助反射技术,根据传递过来的值 x,调用对应 categoryServlet 中的方法 x()
  5. 这样就实现了当访问的路径是 admin_category_list 的时候,就会调用 categoryServlet.x() 方法这样一个效果

换句话说:
如果访问的路径是 admin_category_add,就会调用 categoryServlet.add() 方法
如果访问的路径是 admin_category_delete,就会调用 categoryServlet.delete() 方法

BackServletFilter

Github-BackServletFilter 完整代码

BaseBackServlet

Github-BaseBackServlet 完整代码
BaseBackServlet 继承了 HttpServlet 并重写了 service 方法,其核心代码如下:

另外还定义了增删查改等基础抽象方法,初始化了所有 DAO 对象
上图已经注释的很清楚了,项目全部代码都放在 github 上了,欢迎查看。

CategoryServlet

Github-CategoryServlet 完整代码

  1. 首先 CategoryServlet 继承了 BaseBackServlet,而 BaseBackServlet 又继承了 HttpServlet
  2. 服务端跳转过来之后,会访问 CategoryServlet 会访问 service() 方法
  3. 父类 BaseBackServlet中重写了 service() 方法,所以流程就进入到了 service() 中
    3.1 在 service() 方法中根据反射访问对应的方法
    3.2 根据对应方法的返回值,进行服务端跳转、客户端跳转、或者直接输出字符串。
  4. 取到从 BackServletFilter 中 request.setAttribute() 传递过来的值 list
  5. 根据这个值 list,借助反射机制调用 CategoryServlet 类中的 list() 方法,这样就达到了CategoryServlet.list()方法被调用的效果

而后,list 方法使用 categoryDAO.list 查询出 category 对象集合,并跳转到 listCategory.jsp 显示

完整版的 listCategory.jsp 还包含4个公共文件,分别是 头部,导航,行业,页脚。
分类管理还有增加,编辑,修改,删除,分页,另外后台其他管理页面,前台页面。具体的需要浏览代码,篇幅原因就不展开了。

页面展示

本篇博客所讲不足整个项目的 1/10 ,有兴趣的朋友请移步 github 项目的地址

参考

天猫整站学习教程 里面除了本项目,还有 Java 基础,前端,Tomcat 及其他中间件等教程, 可以注册一个账户,能保存学习记录。

JavaWeb入门_模仿天猫整站Tmall_JavaEE实践项目的更多相关文章

  1. JavaWeb入门_模仿天猫整站Tmall_SSM实践项目

    Tmall_SSM 技术栈 Spring MVC+ Mybatis + Spring + Jsp + Tomcat , 是 Java Web 入门非常好的练手项目 效果展示: 模仿天猫前台 模仿天猫后 ...

  2. JavaWeb入门_模仿天猫整站Tmall_SSH实践项目

    Tmall_SSH 技术栈 Struts2 + Hibernate + Spring + Jsp + Tomcat , 是 Java Web 入门非常好的练手项目 效果展示: 模仿天猫前台 模仿天猫后 ...

  3. scrapy进阶(CrawlSpider爬虫__爬取整站小说)

    # -*- coding: utf-8 -*- import scrapy,re from scrapy.linkextractors import LinkExtractor from scrapy ...

  4. 前端到后台ThinkPHP开发整站--php开发案例

    前端到后台ThinkPHP开发整站--php开发案例 总结 还是需要做几个案例,一天一个为佳,那样才能做得快. 从需求分析着手,任务体系要构建好,这样才能非常高效. 转自: 前端到后台ThinkPHP ...

  5. 网站seo整站优化有什么优势

    http://www.wocaoseo.com/thread-314-1-1.html       现在很多企业找网络公司做网站优化,已经不再像以前那样做目标关键词,而是通过整站优化来达到企业营销目的 ...

  6. DEDE整站动态化或整站静态化设置方法,织梦栏目批量静态/动态方法

    跟版网建站接到一个朋友提问,100多各栏目全部要从动态变成静态,里面的文章也要静态化,如何更快捷的设置dede的静态化或者动态化呢? 直接用DEDE后台的SQL命令行工具, SQL语句: DEDE整站 ...

  7. [参考]wget下载整站

    wget -m -e robots=off -U "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) Gecko/200 ...

  8. java开发_模仿百度文库_OpenOffice2PDF_注意事项

    在模仿百度文库的操作过程中,有很多朋友反映出来的一些问题,是我想起了写这篇blog. 主要是让大家在做的过程中注意一些东西,否则达不到想要的效果. 第一步:我们先从 java开发_模仿百度文库_Ope ...

  9. 09_android入门_采用android-async-http开源项目的GET方式或POST方式实现登陆案例

    根据08_android入门_android-async-http开源项目介绍及使用方法的介绍,我们通过最常见的登陆案例进行介绍android-async-http开源项目中有关类的使用.希望对你学习 ...

随机推荐

  1. iOS开展block说明

    源代码下载 浅谈block使用方法 对于block他用着确实方便,好多人都非常迷茫,这里写了一个Demo解说block的使用方法 好多人都觉得block是用于后一个界面向前一个界面传值用的,事实上更详 ...

  2. Android 项目框架功能整理记录

    用来记录自己在项目用到的框架工具等,新人新记录,希望能对你搭建项目有所帮助 常用框架整理 视图绑定注解框架: butterKnife 网络请求框架: OKHttp 图片加载缓存:Gilde 数据格式解 ...

  3. 在asp.net core中使用cookie认证

    以admin控制器为要认证的控制器举例 1.对控制器设置权限特性 //a 认证命名空间 using Microsoft.AspNetCore.Authorization; using Microsof ...

  4. 张量(tensor)的理解

    1. 从标量到矢量:携带更丰富的信息 矢,是箭的意思,突出的特点是其指向性. 袋子里有几个球? 3 个,magnitude(幅度,没有单位): 从这到你家多远?3 km(denominate),3 称 ...

  5. STM32处理器AD难度整理

    1.STM32的AD变化,任务组可以转换成两组:规则组和注射组.随机序列按随机顺序变换多种渠道构成了一组转换.例如.能够完成转换中,例如按照以下顺序:通道3.通道8.通道2.通道2.通道0.通道2.通 ...

  6. Linux 系统安装(5分钟)

    安装版本:CentOS 6.5 minimal 虚拟机工具:VMware 虚拟机配置:1核2线程 2G内存 50G硬盘 步骤: 一.虚拟机配置 1.打开VMware,创建新的虚拟机,选择典型安装: 2 ...

  7. 如何完全备份android在系统system分区和data分

    安德鲁斯系统备份是非常的情况下,可以使用.下面的这个python脚本.它可以用来备份整个data分:所有data分区的文件和文件夹打包data.zip.并产生recovery专用edify脚本upda ...

  8. 从Header中获得信息

    /// <summary> /// 获得header信息 /// </summary> /// <param name="response">& ...

  9. Html 空格与换行

    空格   换行 <br/>   调行距 <div style="line-height:10px"></div>

  10. Delphi中返回类型为string的函数的一个陷阱(不是很懂)

    如果类的一个成员函数的返回值是string类型,需要注意一个问题 其返回值可能是错误的 例如函数的实现如下 function GetString( s: string ): string;begin  ...