畅购商城(一):环境搭建
目录畅购商城(一):环境搭建项目目的:身为4年java开发,为了进一步的提升一下技术能力,寻找了一个视频实战商城项目,来提高开发流程和框架的熟练度。实操一下,整个项目为16天左右,接下来我会记录一下整个项目中开发中碰到的一些问题。项目介绍:该项目为黑马的B2C商城项目,以微服务架构体系进行搭建,采用前后端分离模式进行开发。技术栈:技术使用SpringBoot+SpringCloud+Gateway
目录
项目目的:
身为4年java开发,为了进一步的提升一下技术能力,寻找了一个视频实战商城项目,来提高开发流程和框架的熟练度。
实操一下,整个项目为16天左右,接下来我会记录一下整个项目中开发中碰到的一些问题。
项目介绍:
该项目为黑马的B2C商城项目,以微服务架构体系进行搭建,采用前后端分离模式进行开发。
技术栈:
技术使用SpringBoot+SpringCloud+Gateway+Redis+MQ+FastDFS+ES+微信支付接口
技术角度来说在市面上还是比较新颖的,前沿的技术框架,互联网金融行业目前大多也是微服务架构体系,对于微服务来说有利也有弊吧。最后希望经过努力学习+实践+总结能够让自身的技术能力有所提升。
技术架构
3环境搭建
虚拟机资料
资料:云盘连接 提取码:sb1m
友情链接:https://blog.csdn.net/qq_45455361/article/details/104316395
3.1 环境准备
(1)VMware Workstation Pro安装centos7 镜像
(2)安装docker
(3)拉取mySQL镜像,并创建容器
(4)客户端连接mysql容器,建库建表(建库建表语句在资源文件夹中提供)
虚拟机数据:
1 虚拟机IP:192.168.211.132
2 虚拟机账号:root 密码:123456
3 数据库端口:3306
4 数据库账号:root 密码:123456
数据库脚本:资料\数据库脚本
3.2 项目结构说明
结构说明:
changgou-gateway
网关模块,根据网站的规模和需要,可以将综合逻辑相关的服务用网关路由组合到一起。在这里还可以做鉴权和限流相关操作。
changgou-service
微服务模块,该模块用于存放所有独立的微服务工程。
changgou-service_api
对应工程的JavaBean、Feign、以及Hystrix配置,该工程主要对外提供依赖。
changgou-transaction-fescar
分布式事务模块,将分布式事务抽取到该工程中,任何工程如需要使用分布式事务,只需依赖该工程即可。
changgou-web
web服务工程,对应功能模块如需要调用多个微服务,可以将他们写入到该模块中,例如网站后台、网站前台等
3.3 公共工程搭建
3.3.1 父工程搭建
创建父工程 changgou-parent ,pom.xml文件中增加配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.changgou</groupId>
<artifactId>changgou-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<properties>
<skipTests>true</skipTests>
</properties>
<!--依赖包-->
<dependencies>
<!--测试包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
<!--swagger文档-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
<!--
http://localhost:9011/swagger-ui.html
-->
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
删除src文件夹
3.3.2 其他公共模块搭建
创建changgou-gateway、changgou-service、changgou-service-api、changgou-web工程,工程全部为pom工程,并将所有工程的src文件删除。
pom.xml中打pom包
<packaging>pom</packaging>
项目结构如下:
3.4 Eureka微服务搭建
3.4.1 pom.xml依赖
创建模块changgou-eureka ,pom.xml引入依
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>changgou_parent</artifactId>
<groupId>com.changgou</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>changgou_eureka</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
3.4.2 appliation.yml配置
创建配置文件application.yml
server:
port: 7001 eureka: instance: hostname: 127.0.0.1 client: register-with-eureka: false #是否将自己注册到eureka中 fetch-registry: false #是否从eureka中获取信息 service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
3.4.3 启动类配置
创建包com.changgou 包下创建启动类EurekaApplication,代码如下:
上图代码如下:
@SpringBootApplication
@EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class); } }
测试访问http://localhost:7001/
,效果如下:
3.5 公共模块搭建
3.5.1 pom.xml依赖
创建公共子模块changgou-common,pom.xml引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>changgou-parent</artifactId> <groupId>com.changgou</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>changgou-common</artifactId> <dependencies> <!--web起步依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- redis 使用--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--eureka-client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--openfeign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--微信支付--> <dependency> <groupId>com.github.wxpay</groupId> <artifactId>wxpay-sdk</artifactId> <version>0.0.3</version> </dependency> <!--httpclient支持--> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> </dependencies> </project>
公共子模块引入这些依赖后,其他微服务引入changgou-common后也自动引入了这些依赖
3.5.2 常用对象
创建entity包 ,在entity包下创建返回状态码实体类
/**
* 返回码 */ public class StatusCode { public static final int OK = 20000;//成功 public static final int ERROR = 20001;//失败 public static final int LOGINERROR = 20002;//用户名或密码错误 public static final int ACCESSERROR = 20003;//权限不足 public static final int REMOTEERROR = 20004;//远程调用失败 public static final int REPERROR = 20005;//重复操作 public static final int NOTFOUNDERROR = 20006;//没有对应的抢购数据 }
包下建立类Result用于微服务返回结果给前端
/**
* 返回结果实体类 */ public class Result<T> { private boolean flag;//是否成功 private Integer code;//返回码 private String message;//返回消息 private T data;//返回数据 public Result(boolean flag, Integer code, String message, Object data) { this.flag = flag; this.code = code; this.message = message; this.data = (T) data; } public Result(boolean flag, Integer code, String message) { this.flag = flag; this.code = code; this.message = message; } public Result() { this.flag = true; this.code = StatusCode.OK; this.message = "操作成功!"; } // getter and setter..... }
在entity包下建立类用于承载分页的数据结果
/**
* 分页结果类 */ public class PageResult<T> { private Long total;//总记录数 private List<T> rows;//记录 public PageResult(Long total, List<T> rows) { this.total = total; this.rows = rows; } public PageResult() { } //getter and setter ...... }
当然,我们还可以将其他工具类都一起倒入到工程中,以后会用到,将资料\工具类
中的所有类直接导入到entity包下。
3.6 数据访问工程搭建
创建公共模块changgou-common-db ,pom文件引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>changgou-parent</artifactId> <groupId>com.changgou</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>changgou-common-db</artifactId> <!--依赖--> <dependencies> <!--对changgou-common的依赖--> <dependency> <groupId>com.changgou</groupId> <artifactId>changgou-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--通用mapper起步依赖--> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>2.0.4</version> </dependency> <!--MySQL数据库驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--mybatis分页插件--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.3</version> </dependency> </dependencies> </project>
这个公共模块是连接mysql数据库的公共微服务模块,所以需要连接mysql的微服务都继承自此工程。
3.7 商品微服务搭建
商品微服务主要是实现对商品的增删改查相关操作,以及商品相关信息的增删改查。
3.7.1 公共组件工程搭建
创建changgou-service-api子模块changgou-service-goods-api,并将资料\javabean\changgou-service-goods-api
中的Pojo导入到工程中。
修改父工程changgou-service-api的pom.xml,添加persistence-api
和changgou-common
的依赖,代码如下:
<dependencies>
<!--通用的common--> <dependency> <groupId>com.changgou</groupId> <artifactId>changgou-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--每个工程都有Pojo,都需要用到该包对应的注解--> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0</version> <scope>compile</scope> </dependency> </dependencies>
3.7.2 微服务工程搭建
修改changgou-service的pom.xml引入changgou-common-db
的依赖,代码如下:
<!--依赖-->
<dependencies> <dependency> <groupId>com.changgou</groupId> <artifactId>changgou-common-db</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
在changgou-service中创建changgou-service-goods ,pom.xml引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>changgou-service</artifactId> <groupId>com.changgou</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>changgou-service-goods</artifactId> <!--依赖--> <dependencies> <dependency> <groupId>com.changgou</groupId> <artifactId>changgou-service-goods-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project>
在resources下创建配置文件application.yml
server:
port: 18081
spring:
application:
name: goods
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.211.132:3306/changgou_goods?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: 123456
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:7001/eureka
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
mybatis:
configuration:
map-underscore-to-camel-case: true
mapper-locations: classpath:mapper/*Mapper.xml
type-aliases-package: com.changgou.goods.pojo
在包com.changgou.goods 包下创建启动类GoodsApplication,代码如下:
上图代码如下:
@SpringBootApplication @EnableEurekaClient @MapperScan(basePackages = {"com.changgou.goods.dao"})
public class GoodsApplication { public static void main(String[] args) { SpringApplication.run(GoodsApplication.class); } }
注意 :@MapperScan是tk.mybatis.spring.annotation
包下的,用于扫描Mapper接口
启动changgou-service-goods
再访问<http://localhost:7001/>
效果如下:
==4 商品微服务-品牌增删改查==
4.1 需求分析
创建商品微服务,实现对品牌表的增删改查功能。具体包括
(1)查询全部列表数据
(2)根据ID查询实体数据
(3)增加
(4)修改
(5)删除
(6)条件查询
(7)分页查询
(8)分页+条件查询
(9)公共异常处理
4.2 表结构分析
品牌表:tb_brand
字段名称 | 字段含义 | 字段类型 | 字段长度 | 备注 |
---|---|---|---|---|
id | 品牌id | INT | ||
name | 品牌名称 | VARCHAR | ||
image | 品牌图片地址 | VARCHAR | ||
letter | 品牌的首字母 | CHAR | ||
seq | 排序 | INT |
4.3 代码实现
上面品牌表对应Brand实体类
@Table(name="tb_brand")
public class Brand implements Serializable{ @Id private Integer id;//品牌id private String name;//品牌名称 private String image;//品牌图片地址 private String letter;//品牌的首字母 private Integer seq;//排序 // getter and setter .....(省略) }
@Table和@Id都是JPA注解,@Table用于配置表与实体类的映射关系,@Id用于标识主键属性。
4.3.1 品牌列表
(1)Dao创建
在changgou-service-goods微服务下创建com.changgou.goods.dao.BrandMapper接口,代码如下:
public interface BrandMapper extends Mapper<Brand> { }
继承了Mapper接口,就自动实现了增删改查的常用方法。
(2)业务层
创建com.changgou.goods.service.BrandService接口,代码如下:
public interface BrandService {
/*** * 查询所有品牌 * @return */ List<Brand> findAll(); }
创建com.changgou.goods.service.impl.BrandServiceImpl实现类,代码如下:
@Service
public class BrandServiceImpl { @Autowired private BrandMapper brandMapper; /** * 全部数据 * @return */ public List<Brand> findAll(){ return brandMapper.selectAll(); } }
(3)控制层
控制层 com.changgou.goods包下创建controller包 ,包下创建类
@RestController @RequestMapping("/brand") @CrossOrigin public class BrandController { @Autowired private BrandService brandService; /*** * 查询全部数据 * @return */ @GetMapping public Result<Brand> findAll(){ List<Brand> brandList = brandService.findAll(); return new Result<Brand>(true, StatusCode.OK,"查询成功",brandList) ; } }
测试:http://localhost:18081/brand
4.3.2 根据ID查询品牌
(1)业务层
修改com.changgou.goods.service.BrandService接口,添加根据ID查询品牌数据方法,代码如下:
/** * 根据ID查询 * @param id * @return */ Brand findById(Integer id);
修改com.changgou.goods.service.impl.BrandServiceImpl新增方法,代码如下:
/**
* 根据ID查询 * @param id * @return */ @Override public Brand findById(Integer id){ return brandMapper.selectByPrimaryKey(id); }
(2)控制层
BrandController新增方法
/***
* 根据ID查询品牌数据 * @param id * @return */ @GetMapping("/{id}") public Result<Brand> findById(@PathVariable Integer id){ //根据ID查询 Brand brand = brandService.findById(id); return new Result<Brand>(true,StatusCode.OK,"查询成功",brand); }
测试:http://localhost:18081/brand/14026
4.3.3 新增品牌
(1)业务层
修改com.changgou.goods.service.BrandService,新增方法
/*** * 新增品牌 * @param brand */ void add(Brand brand);
修改com.changgou.goods.service.impl.BrandServiceImpl,新增增加品牌方法代码如下:
/**
* 增加 * @param brand */ @Override public void add(Brand brand){ brandMapper.insert(brand); }
(2) 控制层
BrandController新增方法
/***
* 新增品牌数据 * @param brand * @return */ @PostMapping public Result add(@RequestBody Brand brand){ brandService.add(brand); return new Result(true,StatusCode.OK,"添加成功"); }
测试:http://localhost:18081/brand
4.3.4 修改品牌
(1)业务层
需改com.changgou.goods.service.BrandService,添加修改品牌方法,代码如下:
/***
* 修改品牌数据 * @param brand */ void update(Brand brand);
修改com.changgou.goods.service.impl.BrandServiceImpl,添加修改品牌方法,代码如下:
/** * 修改 * @param brand */ @Override public void update(Brand brand){ brandMapper.updateByPrimaryKey(brand); }
(2)控制层
BrandController新增方法
/***
* 修改品牌数据 * @param brand * @param id * @return */ @PutMapping(value="/{id}") public Result update(@RequestBody Brand brand,@PathVariable Integer id){ //设置ID brand.setId(id); //修改数据 brandService.update(brand); return new Result(true,StatusCode.OK,"修改成功"); }
测试:http://localhost:18081/brand/325415
4.3.5 删除品牌
(1)业务层
修改com.changgou.goods.service.BrandService,添加删除品牌方法,代码如下:
/***
* 删除品牌 * @param id */ void delete(Integer id);
修改com.changgou.goods.service.impl.BrandServiceImpl,新增删除品牌方法,代码如下:
/** * 删除 * @param id */ @Override public void delete(Integer id){ brandMapper.deleteByPrimaryKey(id); }
(2)控制层
BrandController新增方法
/*** * 根据ID删除品牌数据 * @param id * @return */ @DeleteMapping(value = "/{id}" ) public Result delete(@PathVariable Integer id){ brandService.delete(id); return new Result(true,StatusCode.OK,"删除成功"); }
测试:http://localhost:18081/brand/325415
4.3.6 品牌列表条件查询
(1)业务层
修改com.changgou.goods.service.BrandService,增加根据条件搜索品牌方法,代码如下:
/*** * 多条件搜索品牌方法 * @param brand * @return */ List<Brand> findList(Brand brand);
修改com.changgou.goods.service.impl.BrandServiceImpl,添加根据多条件搜索品牌方法的实现,代码如下:
/**
* 条件查询 * @param brand * @return */ @Override public List<Brand> findList(Brand brand){ //构建查询条件 Example example = createExample(brand); //根据构建的条件查询数据 return brandMapper.selectByExample(example); } /** * 构建查询对象 * @param brand * @return */ public Example createExample(Brand brand){ Example example=new Example(Brand.class); Example.Criteria criteria = example.createCriteria(); if(brand!=null){ // 品牌名称 if(!StringUtils.isEmpty(brand.getName())){ criteria.andLike("name","%"+brand.getName()+"%"); } // 品牌图片地址 if(!StringUtils.isEmpty(brand.getImage())){ criteria.andLike("image","%"+brand.getImage()+"%"); } // 品牌的首字母 if(!StringUtils.isEmpty(brand.getLetter())){ criteria.andLike("letter","%"+brand.getLetter()+"%"); } // 品牌id if(!StringUtils.isEmpty(brand.getLetter())){ criteria.andEqualTo("id",brand.getId()); } // 排序 if(!StringUtils.isEmpty(brand.getSeq())){ criteria.andEqualTo("seq",brand.getSeq()); } } return example; }
(2) 控制层
BrandController新增方法
/***
* 多条件搜索品牌数据 * @param brand * @return */ @PostMapping(value = "/search" ) public Result<List<Brand>> findList(@RequestBody(required = false) Brand brand){ List<Brand> list = brandService.findList(brand); return new Result<List<Brand>>(true,StatusCode.OK,"查询成功",list); }
测试:http://localhost:18081/brand/search
4.3.7 品牌列表分页查询
(1)业务层
修改com.changgou.goods.service.BrandService添加分页方法,代码如下:
/*** * 分页查询 * @param page * @param size * @return */ PageInfo<Brand> findPage(int page, int size);
修改com.changgou.goods.service.impl.BrandServiceImpl添加分页方法实现,代码如下:
/**
* 分页查询 * @param page * @param size * @return */ @Override public PageInfo<Brand> findPage(int page, int size){ //静态分页 PageHelper.startPage(page,size); //分页查询 return new PageInfo<Brand>(brandMapper.selectAll()); }
(2)控制层
BrandController新增方法
/*** * 分页搜索实现 * @param page:当前页 * @param size:每页显示多少条 * @return */ @GetMapping(value = "/search/{page}/{size}" ) public Result<PageInfo> findPage(@PathVariable int page, @PathVariable int size){ //分页查询 PageInfo<Brand> pageInfo = brandService.findPage(page, size); return new Result<PageInfo>(true,StatusCode.OK,"查询成功",pageInfo); }
测试:http://localhost:18081/brand/search/1/3
4.3.8 品牌列表条件+分页查询
(1)业务层
修改com.changgou.goods.service.BrandService,增加多条件分页查询方法,代码如下:
/***
* 多条件分页查询 * @param brand * @param page * @param size * @return */ PageInfo<Brand> findPage(Brand brand, int page, int size);
修改com.changgou.goods.service.impl.BrandServiceImpl,添加多条件分页查询方法代码如下:
/** * 条件+分页查询 * @param brand 查询条件 * @param page 页码 * @param size 页大小 * @return 分页结果 */ @Override public PageInfo<Brand> findPage(Brand brand, int page, int size){ //分页 PageHelper.startPage(page,size); //搜索条件构建 Example example = createExample(brand); //执行搜索 return new PageInfo<Brand>(brandMapper.selectByExample(example)); }
(2)控制层
BrandController新增方法
/*** * 分页搜索实现 * @param brand * @param page * @param size * @return */ @PostMapping(value = "/search/{page}/{size}" ) public Result<PageInfo> findPage(@RequestBody(required = false) Brand brand, @PathVariable int page, @PathVariable int size){ //执行搜索 PageInfo<Brand> pageInfo = brandService.findPage(brand, page, size); return new Result(true,StatusCode.OK,"查询成功",pageInfo); }
测试:http://localhost:18081/brand/search/1/3
4.3.9 公共异常处理
为了使我们的代码更容易维护,我们创建一个类集中处理异常,该异常类可以创建在changgou-common工程中,创建com.changgou.framework.exception.BaseExceptionHandler,代码如下:
@ControllerAdvice
public class BaseExceptionHandler { /*** * 异常处理 * @param e * @return */ @ExceptionHandler(value = Exception.class) @ResponseBody public Result error(Exception e) { e.printStackTrace(); return new Result(false, StatusCode.ERROR, e.getMessage()); } }
注意:@ControllerAdvice注解,全局捕获异常类,只要作用在@RequestMapping上,所有的异常都会被捕获。
更多推荐
所有评论(0)