项目简介

**项目地址:**https://github.com/newbee-ltd/newbee-mall

**项目介绍:**newbee-mall 项目是一套电商系统,包括 newbee-mall 商城系统及 newbee-mall-admin 商城后台管理系统,基于 Spring Boot 2.X 及相关技术栈开发。 前台商城系统包含首页门户、商品分类、新品上线、首页轮播、商品推荐、商品搜索、商品展示、购物车、订单结算、订单流程、个人订单管理、会员中心、帮助中心等模块。 后台管理系统包含数据面板、轮播图管理、商品管理、订单管理、会员管理、分类管理、设置等模块。

经笔者验证,是一个值得一看的Spring项目!

项目运行

想要运行该项目需要进行相应的配置:

  • 安装Mysql

如果是Mac电脑可以参考:Mac电脑安装mysql。

安装好Mysql后新建一个数据库,并运行项目文件夹下的newbee-mall-schema.sql文件,将数据插入数据库,可参考:如何执行sql文件插入数据库。

  • 配置Mysql

修改application.properties文件中的mysql数据库名为自己的数据库名:

spring.datasource.name=newbee(自己的数据库名)
spring.datasource.username=root
spring.datasource.password=12345678
  • 解压img,修改路径

将项目路径下的upload.zip解压,并记录下路径;

在common/constansts中修改路径:

//public final static String FILE_UPLOAD_DIC = "/opt/image/upload/";//上传文件的默认url前缀,根据部署设置自行修改public final static String FILE_UPLOAD_DIC = "/Users/xiuyi/Desktop/javaer/newbee-mall/src/main/resources/upload/";
  • 运行、访问

运行成功之后,打开网页,访问:localhost:28089即可。

项目中还出现问题可以参考:如何运行new-bee。

项目框架

项目整体框架如下:

其中,

  • common:定义一些公用字段名;
  • util:提供一些静态帮助方法。如邮箱格式验证、MD5码生成等;
  • config:WebMvcConfigure的配置,主要设置拦截器以及资源文件;
  • dao跟数据层的交互接口,获取货品信息、用户信息、订单信息等;项目使用的数据库是Mybatis,通过XML配置dao接口跟数据库的映射关系;
  • Interceptor:拦截器的具体实现,完成身份验证、购物车数量实时更新;
  • controller:MVC框架中的控制器,根据web端的请求调用相应的service层进行逻辑处理;
  • entity:项目中的常用字段类;
  • service:服务层,由控制器进行调用;

功能细分

这个部分对项目的各个功能进行进一步的分析,捋清楚调用关系并补充一些细节。

其实这是一个典型的MVC项目,即Model-View-Controller,根据对应的客户端请求,由Spring MVC调度相应的Controller进行处理,Controller调用service进行业务逻辑处理,而后交给Thymeleaf模板引擎对结果Entity进行渲染,将处理结果返回给用户,从而显示在浏览器上,整个流程如下:

商城首页

首页,即访问:网页地址/index(或/,或/),获取新蜂商城首页。

在IndexController中,当接收到来自客户端“/”的请求时,访问数据库去获取分类数据、轮播图、新品、推荐数据,经由模板引擎(用的是thymeleaf)生成html返回给客户端:

@GetMapping({"/index", "/", "/index.html"})
public String indexPage(HttpServletRequest request) {List<NewBeeMallIndexCategoryVO> categories = newBeeMallCategoryService.getCategoriesForIndex();if (CollectionUtils.isEmpty(categories)) {return "error/error_5xx";}List<NewBeeMallIndexCarouselVO> carousels = newBeeMallCarouselService.getCarouselsForIndex(Constants.INDEX_CAROUSEL_NUMBER);List<NewBeeMallIndexConfigGoodsVO> hotGoodses = newBeeMallIndexConfigService.getConfigGoodsesForIndex(IndexConfigTypeEnum.INDEX_GOODS_HOT.getType(), Constants.INDEX_GOODS_HOT_NUMBER);List<NewBeeMallIndexConfigGoodsVO> newGoodses = newBeeMallIndexConfigService.getConfigGoodsesForIndex(IndexConfigTypeEnum.INDEX_GOODS_NEW.getType(), Constants.INDEX_GOODS_NEW_NUMBER);List<NewBeeMallIndexConfigGoodsVO> recommendGoodses = newBeeMallIndexConfigService.getConfigGoodsesForIndex(IndexConfigTypeEnum.INDEX_GOODS_RECOMMOND.getType(), Constants.INDEX_GOODS_RECOMMOND_NUMBER);request.setAttribute("categories", categories);//分类数据request.setAttribute("carousels", carousels);//轮播图request.setAttribute("hotGoodses", hotGoodses);//热销商品request.setAttribute("newGoodses", newGoodses);//新品request.setAttribute("recommendGoodses", recommendGoodses);//推荐商品return "mall/index";
}

注意到上述Controller的返回值是“mail/index”——这是因为Spring Boot集成的Thymeleaf默认配置会自动渲染**classpath:templates/网页名。**Thymeleaf的详细教程可参考Thymeleaf语法,Thymeleaf详解。

因此在使用Thymeleaf模板引擎时,编写Controller只需要返回指定的网页名即可,而不用想WebMVC一样,通过ModelView来进行渲染:

@RequestMapping(value = "/greeting")
public ModelAndView test(ModelAndView mv) { mv.setViewName("/greeting"); mv.addObject("title","欢迎使用Thymeleaf!"); return mv;
}

用户注册、登录

点击注册按钮,即跳转至用户登录界面:

这两个按钮对应的路径为/rigister和/login,处理请求的是mall/PersonalController,如果是获取登录、注册页面,则调用相应的模板引擎进行渲染:

     @GetMapping({"/login", "login.html"})public String loginPage() {return "mall/login";}@GetMapping({"/register", "register.html"})public String registerPage() {return "mall/register";}

如果是获取登录、注册的表单,则应该调用相应的post方法,以登录为例:

@PostMapping("/login")
@ResponseBody
public Result login(@RequestParam("loginName") String loginName,@RequestParam("verifyCode") String verifyCode,@RequestParam("password") String password,HttpSession httpSession) {if (StringUtils.isEmpty(loginName)) {return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_NAME_NULL.getResult());}if (StringUtils.isEmpty(password)) {return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_PASSWORD_NULL.getResult());}if (StringUtils.isEmpty(verifyCode)) {return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_VERIFY_CODE_NULL.getResult());}String kaptchaCode = httpSession.getAttribute(Constants.MALL_VERIFY_CODE_KEY) + "";if (StringUtils.isEmpty(kaptchaCode) || !verifyCode.toLowerCase().equals(kaptchaCode)) {return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_VERIFY_CODE_ERROR.getResult());}String loginResult = newBeeMallUserService.login(loginName, MD5Util.MD5Encode(password, "UTF-8"), httpSession);//登录成功if (ServiceResultEnum.SUCCESS.getResult().equals(loginResult)) {//删除session中的verifyCodehttpSession.removeAttribute(Constants.MALL_VERIFY_CODE_KEY);return ResultGenerator.genSuccessResult();}//登录失败return ResultGenerator.genFailResult(loginResult);
}

值得注意的是,在处理登录时,会先对用户名和密码进行基本的格式验证,而后交由数据库进行验证。

商品详情页

以HUAWEI mate30 Pro为例:

其控制器为mail/GoodsController,通过访问数据库获取商品数据,放进模板引擎进行渲染:

@GetMapping("/goods/detail/{goodsId}")
public String detailPage(@PathVariable("goodsId") Long goodsId, HttpServletRequest request) {if (goodsId < 1) {return "error/error_5xx";}NewBeeMallGoods goods = newBeeMallGoodsService.getNewBeeMallGoodsById(goodsId);if (goods == null) {NewBeeMallException.fail(ServiceResultEnum.GOODS_NOT_EXIST.getResult());}if (Constants.SELL_STATUS_UP != goods.getGoodsSellStatus()) {NewBeeMallException.fail(ServiceResultEnum.GOODS_PUT_DOWN.getResult());}NewBeeMallGoodsDetailVO goodsDetailVO = new NewBeeMallGoodsDetailVO();BeanUtil.copyProperties(goods, goodsDetailVO);goodsDetailVO.setGoodsCarouselList(goods.getGoodsCarousel().split(","));request.setAttribute("goodsDetail", goodsDetailVO);return "mall/detail";
}

商品搜索

商品搜索时,其控制器也是mail/GoodsController,通过关键词去数据库中搜索属性对应的商品

并显示。这里还有分页设计,限制每一页的显示货品个数,同时还有排序属性:

另外,可以看出这里的搜索栏目与首页的分类栏目所用的接口是一样,只不过搜索时是借助keyword,而分类使用的是category。

@GetMapping({"/search", "/search.html"})
public String searchPage(@RequestParam Map<String, Object> params, HttpServletRequest request) {if (StringUtils.isEmpty(params.get("page"))) {params.put("page", 1);}params.put("limit", Constants.GOODS_SEARCH_PAGE_LIMIT);//封装分类数据if (params.containsKey("goodsCategoryId") && !StringUtils.isEmpty(params.get("goodsCategoryId") + "")) {Long categoryId = Long.valueOf(params.get("goodsCategoryId") + "");SearchPageCategoryVO searchPageCategoryVO = newBeeMallCategoryService.getCategoriesForSearch(categoryId);if (searchPageCategoryVO != null) {request.setAttribute("goodsCategoryId", categoryId);request.setAttribute("searchPageCategoryVO", searchPageCategoryVO);}}//封装参数供前端回显if (params.containsKey("orderBy") && !StringUtils.isEmpty(params.get("orderBy") + "")) {request.setAttribute("orderBy", params.get("orderBy") + "");}String keyword = "";//对keyword做过滤 去掉空格if (params.containsKey("keyword") && !StringUtils.isEmpty((params.get("keyword") + "").trim())) {keyword = params.get("keyword") + "";}request.setAttribute("keyword", keyword);params.put("keyword", keyword);//搜索上架状态下的商品params.put("goodsSellStatus", Constants.SELL_STATUS_UP);//封装商品数据PageQueryUtil pageUtil = new PageQueryUtil(params);request.setAttribute("pageResult", newBeeMallGoodsService.searchNewBeeMallGoods(pageUtil));return "mall/search";
}

其实这几个环节中商品搜索部分是我最感兴趣的:它是怎么实现搜索的呢?

笔者测试了一下搜索系统,结果比较准确,难不成还集成了搜索引擎?好奇心驱使之下遂继续往下面挖,直到:

<select id="findNewBeeMallGoodsListBySearch" parameterType="Map" resultMap="BaseResultMap">select<include refid="Base_Column_List"/>from tb_newbee_mall_goods_info<where><if test="keyword!=null and keyword!=''">and (goods_name like CONCAT('%',#{keyword},'%') or goods_intro like CONCAT('%',#{keyword},'%'))</if><if test="goodsCategoryId!=null and goodsCategoryId!=''">and goods_category_id = #{goodsCategoryId}</if><if test="goodsSellStatus!=null">and goods_sell_status = #{goodsSellStatus}</if></where><if test="orderBy!=null and orderBy!=''"><choose><when test="orderBy == 'new'"><!-- 按照发布时间倒序排列 -->order by goods_id desc</when><when test="orderBy == 'price'"><!-- 按照售价从小到大排列 -->order by selling_price asc</when><otherwise><!-- 默认按照库存数量从大到小排列 -->order by stock_num desc</otherwise></choose></if><if test="start!=null and limit!=null">limit #{start},#{limit}</if>
</select>

从上述的Mybatis的动态Sql语句可以看出,整个商品搜索系统其实都是由底层的Mysql数据库提供的,而所谓的商品搜索也只是通过Like加%通配符的方式与商品名和商品简介进行匹配而已。

而这种搜索方式遇到模糊名词或者错误名词就难过了,什么都搜不出来,而且以通配符的方式进行搜索当数据量大的场景下,效率极其低。在真实的电商场景中,商品搜索是一个极其重要的组件,一般是基于倒排索引数据库(ES、OpenSearch等)的搜索引擎来提供商品搜索服务。

订单系统

购物车相关的逻辑控制都在mall/shoppingcartController中,暂不赘述:

顺带一提,支付的时候还会进行地址的验证,很棒!

PS:在一个健壮的系统中,在合适的地方进行数据验证能够有效地防止错误。

后台管理系统

后台管理系统可以看让商家对自己商品进行管理(用户名:admin,密码:123456),诸如增加商品、设置轮播图、修改排序等等:

后台管理系统可以进行商品管理、订单管理、会员管理等等,如果说之前的系统是对数据库的查询动手的话,那么这个环节主要是实现对数据库的修改。(现在的开发只要会CRUD就不怕没饭吃啊)

这个后台管理系统简直神了!

可以说前端、数据库、动态网页等技术全都用上了,很有必要仔细的学习!

总结

这个开源项目的内容包含了太多可以学习的知识:

  • Spring Boot的配置
  • Spring MVC的使用
  • Thymeleaf模板引擎
  • Mybatis的使用
  • Mysql的配置
  • Interceptot拦截器
  • 身份验证
  • kaptcha验证码生成
  • AdminLTE仪表盘****等知识

可以说要完全吃透这一个项目需要的准备知识很多,但是收获也多!

这个开源项目确实很不错,谢谢十三老师的分享!

【Java Spring开源项目】新蜂(NeeBee)商城项目运行、分析、总结相关推荐

  1. Vue+Spring Boot 前后端分离的商城项目开源啦!

    1 新蜂商城 Vue 移动端版本开源啦! 去年开源新蜂商城项目后,就一直在计划这个项目 Vue 版本的改造,2020 年开始开发并且自己私下一直在测试,之前也有文章介绍过测试过程和存在的问题,修改完成 ...

  2. M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档

    M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档 分布式基础篇 一.环境搭建 各种开发软件的安装 虚拟机: docker,mysql,redis 主机: Maven, idea(后端),Vs ...

  3. 开源项目新蜂商城在Linux上部署,mysql+nginx

    newbee-mall是一项基于Spring Boot的在线商城系统,非常适合新手了解学习Spring Boot框架 源码新蜂商城后端接口 newbee-mall-api 新蜂商城 Vue3 版本 n ...

  4. 一款开源的微信小程序商城项目,接外包直接拿去改改,就能用(附源码)。。。...

    大家好,今天,推荐一个小程序商城项目. 上次是谁要小程序商城项目啊,猿哥帮你找到了. 这是我目前见过的最好的小程序商城项目.功能完整,代码结构清晰.值得推荐. 后端部分虽然是PHP的,但是建议有研究精 ...

  5. java商城项目_javaweb实战之商城项目开发(一)

    这篇文章主要针对javaweb商城项目开发进行实战演习,对javaweb商城项目开发进行详细分析,感兴趣的小伙伴们可以参考一下 一.项目功能结构 1.功能 2.实体 3.对应sql语句 CREATE ...

  6. java b2b 开源_springcloud微服务多用户商城系统java_代码开源_B2B电商系统_B2C电商系统...

    Spring Cloud是一系列框架的有序集合.利用Spring Boot的开发模式简化了分布式系统基础设施的开发,如服务发现.注册.配置中心.消息总线.负载均衡.断路器.数据监控等(这里只简单的列了 ...

  7. php商城项目视频,thinkphp5.0商城项目实战视频教程

    Thinkphp作为开源的PHP框架发展到今天,无疑是国内最适合PHP学员学习和使用的框架,除了简单容易上手,更大的优点是开发文档完善.插件丰富.满足作为开发大中型网站框架的条件,此课程将以开发一个中 ...

  8. java怎么添加商品信息_Javaweb网上商城项目实战(20)添加商品到购物车

    原理分析 具体实现 准备工作 有些准备工作在之前已经实现了,这里强调一下,如果没改的自己改一下,已经完成了的也检查一下. 1.在product_list.jsp中修改链接 2.product_info ...

  9. Java项目:仿天猫网上商城项目(java+jsp+servlet+mysql+ajax)

    源码获取:博客首页 "资源" 里下载! 一.项目简述 功能: 前台: * 用户模块 * 分类模块 * 商品模块 * 购物车模块 * 订单模块 后台: * 管理员模块 * 分类管理模 ...

最新文章

  1. C#调用C++dll
  2. 博易大师 行情服务器文件,博易大师目录
  3. 图解YU12、I420、YV12、NV12、NV21、YUV420P、YUV420SP、YUV422P、YUV444P的区别
  4. 【新年礼物】pmcaff会员大放送!
  5. python教程:循环(while和for)
  6. C语言试题三十九之将s所指字符串中除了下标为奇数、同时ascii值也为奇数的字符外,其余的全都删除;串中剩余字符所形成的一个新串放在t所指的一个数组中。
  7. Leetcode--84. 柱状图中最大的矩形
  8. 架构师Jack专访:全面认识软件测试架构师
  9. 潜移默化学会WPF(安全篇二)--C#对称加密算法
  10. uc手机浏览器 手机模拟_在PC上测试移动端网站和模拟手机浏览器的5大方法
  11. 比特鹏哥网课笔记(结构体,枚举,联合体,通讯录项目)
  12. 毕业设计-基于SSM医院信息管理系统
  13. java 阶梯_Java if-else-if阶梯语句
  14. java课程设计---绘图板
  15. Sandy Bridge架构首款赛扬悄然发布
  16. 【物理应用】大气湍流相位屏仿真matlab源码
  17. 利用CVE-2021-40444漏洞钓鱼执法上线MSF
  18. ios面试准备 - 网络篇
  19. C#SerialPort详细用法
  20. 人工智能及其应用(一)

热门文章

  1. Python-Django毕业设计好又多百货商业广场有限公司自助收银操作系统(程序+Lw)
  2. linux 查看进程和终止进程
  3. 模拟实现strcat
  4. integer java关键字,integer是关键字吗 integer在c语言中是什么意思
  5. C# TreeView
  6. 【Python 百练成钢】灯光模拟
  7. netframework4 分32 64位吗_手机微信有两个版本,32位和64位,你的微信是多少位?...
  8. Sort Colors
  9. 初闻噩耗... ...
  10. 新疆计算机博士就业,逆袭 新疆大专毕业生就业率比博士还高