SpringBoot实战电商项目mall(18k+star)地址:github.com/macrozheng/…html
mall-tiny是从mall项目中抽取出来的项目骨架,保留了mall项目的整个技术栈,对业务逻辑进行了精简,只保留了权限及商品核心表,方便开发使用,能够自由定制业务逻辑。java
技术 | 版本 | 说明 |
---|---|---|
SpringBoot | 2.1.3 | 容器+MVC框架 |
SpringSecurity | 5.1.4 | 认证和受权框架 |
MyBatis | 3.4.6 | ORM框架 |
MyBatisGenerator | 1.3.3 | 数据层代码生成 |
PageHelper | 5.1.8 | MyBatis物理分页插件 |
Swagger-UI | 2.7.0 | 文档生产工具 |
Elasticsearch | 6.2.2 | 搜索引擎 |
RabbitMq | 3.7.14 | 消息队列 |
Redis | 3.2 | 分布式缓存 |
MongoDb | 3.2 | NoSql数据库 |
Docker | 18.09.0 | 应用容器引擎 |
Druid | 1.1.10 | 数据库链接池 |
OSS | 2.5.0 | 对象存储 |
JWT | 0.9.0 | JWT登陆支持 |
Lombok | 1.18.6 | 简化对象封装工具 |
本项目启动须要依赖MySql、Elasticsearch、Redis、MongoDb、RabbitMq等服务,安装依赖服务请参考mall在Windows环境下的部署,数据库中须要导入mall_tiny.sql脚本。git
src
├── common -- 用于存储通用代码及工具类
| ├── api -- 通用结果集封装类
| └── utils -- 工具类
├── component -- 项目中定义的各种组件
├── config -- SpringBoot中的Java配置
├── controller -- 控制器层代码
├── dao -- 数据访问层代码,存放咱们自定义查询的dao接口,以xxxDao命名
├── dto -- 数据传输对象封装
├── mbg -- MyBatisGenerator生成器相关代码
| ├── mapper -- MyBatisGenerator自动生成的mapper接口(请勿改动)
| └── model -- MyBatisGenerator自动生成的实体类及Example对象(请勿改动)
├── nosql -- nosql数据库操做相关类
| ├── elasticsearch -- elasticsearch数据操做相关类
| | ├── document -- elasticsearch中存储文档对象封装
| | └── repository -- elasticsearch数据操做类
| └── mongodb -- mongodb数据操做相关类
| ├── document -- mongodb中存储文档对象封装
| └── repository -- mongodb数据操做类
└── service -- 业务层接口代码
└── impl -- 业务层接口实现类代码
复制代码
res
├── com.macro.mall.tiny.mbg.mapper -- mbg自动生成的mapper.xml文件(请勿改动)
├── mapper -- 自定义的mapper.xml文件,对应dao包中的查询接口,以xxxDao.xml命名
├── application.yml -- SpringBoot的配置文件
├── generator.properties -- 用于配置MyBatisGenerator生成代码时的数据源信息
├── generatorConfig.xml -- MyBatisGenerator生成代码规则配置
└── logback-spring.xml -- 整合ELK实现日志收集时使用的配置
复制代码
具体参数及返回结果定义能够运行代码查看Swagger-UI的Api文档:github
安装完相关依赖之后直接启动com.macro.mall.tiny.MallTinyApplication类的main函数便可。spring
这里以品牌管理功能为例来讲明业务代码开发流程。sql
建立一张pms_brand表,须要注意的是必定要写好表字段的注释,这样在生成代码时,实体类中就会有注释了,并且Swagger-UI生成的文档中也会有注释,不用再重复写注释。mongodb
CREATE TABLE `pms_brand` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(64) DEFAULT NULL,
`first_letter` varchar(8) DEFAULT NULL COMMENT '首字母',
`sort` int(11) DEFAULT NULL,
`factory_status` int(1) DEFAULT NULL COMMENT '是否为品牌制造商:0->不是;1->是',
`show_status` int(1) DEFAULT NULL,
`product_count` int(11) DEFAULT NULL COMMENT '产品数量',
`product_comment_count` int(11) DEFAULT NULL COMMENT '产品评论数量',
`logo` varchar(255) DEFAULT NULL COMMENT '品牌logo',
`big_pic` varchar(255) DEFAULT NULL COMMENT '专区大图',
`brand_story` text COMMENT '品牌故事',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8 COMMENT='品牌表';
复制代码
运行com.macro.mall.tiny.mbg.Generator类的main方法来生成代码,生成完后会有如下几个文件。docker
包含了单表查询的经常使用接口数据库
public interface PmsBrandMapper {
long countByExample(PmsBrandExample example);
int deleteByExample(PmsBrandExample example);
int deleteByPrimaryKey(Long id);
int insert(PmsBrand record);
int insertSelective(PmsBrand record);
List<PmsBrand> selectByExampleWithBLOBs(PmsBrandExample example);
List<PmsBrand> selectByExample(PmsBrandExample example);
PmsBrand selectByPrimaryKey(Long id);
int updateByExampleSelective(@Param("record") PmsBrand record, @Param("example") PmsBrandExample example);
int updateByExampleWithBLOBs(@Param("record") PmsBrand record, @Param("example") PmsBrandExample example);
int updateByExample(@Param("record") PmsBrand record, @Param("example") PmsBrandExample example);
int updateByPrimaryKeySelective(PmsBrand record);
int updateByPrimaryKeyWithBLOBs(PmsBrand record);
int updateByPrimaryKey(PmsBrand record);
}
复制代码
根据数据库表生成的实体类,已添加Swagger-UI的注解。api
package com.macro.mall.tiny.mbg.model;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
public class PmsBrand implements Serializable {
private Long id;
private String name;
@ApiModelProperty(value = "首字母")
private String firstLetter;
private Integer sort;
@ApiModelProperty(value = "是否为品牌制造商:0->不是;1->是")
private Integer factoryStatus;
private Integer showStatus;
@ApiModelProperty(value = "产品数量")
private Integer productCount;
@ApiModelProperty(value = "产品评论数量")
private Integer productCommentCount;
@ApiModelProperty(value = "品牌logo")
private String logo;
@ApiModelProperty(value = "专区大图")
private String bigPic;
@ApiModelProperty(value = "品牌故事")
private String brandStory;
private static final long serialVersionUID = 1L;
//省略getter、setter、toString方法
}
复制代码
用于在复杂查询时构造查询条件。
对应PmsBrandMapper接口中的mapper.xml实现,PmsBrandMapper接口中方法的具体查询实现都在此处。
单表查询推荐使用查询构造器来进行查询,不用手写sql语句,好比如下的按品牌名称进行模糊查询。
@Override
public List<PmsBrand> list(int pageNum, int pageSize, String name) {
PageHelper.startPage(pageNum, pageSize);
PmsBrandExample example = new PmsBrandExample();
if(StrUtil.isNotEmpty(name)){
example.createCriteria().andNameLike("%"+name+"%");
}
return brandMapper.selectByExample(example);
}
复制代码
分页查询使用PageHelper分页插件实现,只需在查询语句前添加如下代码便可。
PageHelper.startPage(pageNum, pageSize);
复制代码
多表查询须要本身编写mapper接口和mapper.xml实现,和MyBatis中用法一致,这里以查询包含属性的商品为例。
public interface EsProductDao {
List<EsProduct> getAllEsProductList(@Param("id") Long id);
}
复制代码
<select id="getAllEsProductList" resultMap="esProductListMap">
select
p.id id,
p.product_sn productSn,
p.brand_id brandId,
p.brand_name brandName,
p.product_category_id productCategoryId,
p.product_category_name productCategoryName,
p.pic pic,
p.name name,
p.sub_title subTitle,
p.price price,
p.sale sale,
p.new_status newStatus,
p.recommand_status recommandStatus,
p.stock stock,
p.promotion_type promotionType,
p.keywords keywords,
p.sort sort,
pav.id attr_id,
pav.value attr_value,
pav.product_attribute_id attr_product_attribute_id,
pa.type attr_type,
pa.name attr_name
from pms_product p
left join pms_product_attribute_value pav on p.id = pav.product_id
left join pms_product_attribute pa on pav.product_attribute_id= pa.id
where delete_status = 0 and publish_status = 1
<if test="id!=null">
and p.id=#{id}
</if>
</select>
复制代码
在com.macro.mall.tiny.controller包中添加PmsBrandController类。
mall-tiny已经集成了docker插件,能够打包成docker镜像后使用docker来部署,具体参考:使用Maven插件为SpringBoot应用构建Docker镜像
因为使用了SpringSecurity来实现认证和受权,部分接口须要登陆才能够访问,访问登陆接口流程以下。
本项目已使用AOP切面记录了全部接口访问日志,同时整合了ELK实现了日志收集。ELK日志收集环境搭建能够参考:SpringBoot应用整合ELK实现日志收集。
oss文件上传使用时须要修改为你本身的配置,须要修改配置以下:
# OSS相关配置信息
aliyun:
oss:
endpoint: oss-cn-shenzhen.aliyuncs.com # oss对外服务的访问域名
accessKeyId: test # 访问身份验证中用到用户标识
accessKeySecret: test # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
bucketName: macro-oss # oss的存储空间
policy:
expire: 300 # 签名有效期(S)
maxSize: 10 # 上传文件大小(M)
callback: http://localhost:8080/aliyun/oss/callback # 文件上传成功后的回调地址(必须公网能够访问)
dir:
prefix: mall/images/ # 上传文件夹路径前缀
复制代码
已经配置了全局的过滤器,容许跨越访问,同时SpringSecurity也放行了跨域的预检OPTIONS请求。
/** * 全局跨域配置 * Created by macro on 2019/7/27. */
@Configuration
public class GlobalCorsConfig {
/** * 容许跨域调用的过滤器 */
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//容许全部域名进行跨域调用
config.addAllowedOrigin("*");
//容许跨愈加送cookie
config.setAllowCredentials(true);
//放行所有原始头信息
config.addAllowedHeader("*");
//容许全部请求方法跨域调用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
复制代码
//SecurityConfig的configure方法中已经添加
.antMatchers(HttpMethod.OPTIONS)//跨域请求会先进行一次options请求
.permitAll()
复制代码
mall项目全套学习教程连载中,关注公众号第一时间获取。