人之所以痛苦,那是因为你在成长。--------magic_guo
在分布式系统中,数据库的设计尤为重要,关系着系统性能;在高可用的概念中,数据库的设计和优化被单独划分为一个模块来叙述,由此可见其重要性;
其中有分库分表、字段设计、索引选择、数据库引擎、主键策略、表之间的关联等,都属于这一范畴;
商品模块数据库搭建:
阐述:
商品的基本信息:id、价格、描述、类型、商品图片等;
在一些真实业务场景中,商品图片是一个表(一般商品图片都存放于分布式文件存储系统中,如fastFDS和OSS)、商品描述是一个表;三个表之间是根据商品id来维护关系,而不是通过主键强关联的方式来维护关系(因为这样,做增删改查的时候容易),而且主键策略一般是根据一些算法(如雪花算法等)来生成id,而不是直接主键自增等;
本文只是做一个案列,只是将商品图片做了一个分表;图片存放fastFDS中;后续优化在后文中会写出来;
商品表创建:
商品图片创建:
创建商品模块:
还是老步骤:整理pom文件,写mapper、sevice、controller层,配置文件,启动类;
目录结构:
pom文件(shop-common模块在下面叙述):
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.guo</groupId>
<artifactId>shop-common</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
其他层都不再说了,跟前面的shop-user模块一样,不同的是controller层:
说一下多条件查询,这里使用一个mapo来传递参数,因为后面要使用feign来调用此模块,在feign的接口中,多参数出传递或者list传递很不方便;
大多数条件查询都是以下几个步骤:
1.接收参数;2.创建page对象;3.创建EntityWrapper对象;4.查询
@Slf4j
@RestController
@RequestMapping("/goods")
public class GoodsController {
@Autowired
IGoodsService goodsService;
@Autowired
IGoodsPngService goodsPngService;
@RequestMapping("/addGoods")
public ResultEntity addGoods(@RequestBody Goods goods) {
return ResultEntity.responseClient(goodsService.insert(goods));
}
@RequestMapping("/getGoodsPage")
public ResultEntity getGoodsPage(@RequestBody Map<String, Object> map) {
// 1.获取请求的数据
Object current = map.get("current");
Object size = map.get("size");
Object gname = map.get("gname");
Object gtype = map.get("gtype");
Object gprice = map.get("gprice");
// 2.创建分页对象
Page<Goods> page = new Page<>();
if (!StringUtils.isEmpty(current.toString())) {
page.setCurrent(Integer.parseInt(current.toString()));
}
if (!StringUtils.isEmpty(size.toString())) {
page.setSize(Integer.parseInt(size.toString()));
}
// 3.创建EntityWrapper
EntityWrapper<Goods> entityWrapper = new EntityWrapper<>();
if (!StringUtils.isEmpty(gname.toString())) {
entityWrapper.like("gname", gname.toString());
}
if (!StringUtils.isEmpty(gtype.toString())) {
entityWrapper.like("gtype", gtype.toString());
}
if (!StringUtils.isEmpty(gprice.toString())) {
entityWrapper.like("gprice", gprice.toString());
}
// 4.查询
return ResultEntity.success(goodsService.selectPage(page, entityWrapper));
}
}
启动此模块,查看端口和注册中心,访问接口:
数据库:
这里说一下@RequestBody注解:
@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交;
一个请求,只有一个RequestBody;一个请求,可以有多个RequestParam
后台模块以feign的方式调用商品模块和调用user模块是一样的,上一篇已经写过,不再作重复描述;
公共模块shop-common搭建:
此模块以maven工程的形式来构建,用于存放各个模块共同用到的资源:如全局异常类、工具类等
全局异常:异常处理分为两类,一种是非IO型异常,则可直接抛出做处理;另一种是IO型异常,要直接在代码里作资源关闭的处理,不能单靠此全局异常来处理;
@ControllerAdvice 是一个增强的 Controller。使用这个 Controller ,可以实现三个方面的功能:
1.全局异常处理(最常用)
2.全局数据绑定
3.全局数据预处理
// @ControllerAdvice 表明这是一个全局异常
// @ExceptionHandler 注解用来指明异常的处理类型
@ControllerAdvice
@Slf4j
public class ShopExceptionHandler {
// 处理系统异常
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ResultEntity systemException(Exception e) {
log.error("系统异常", e);
return ResultEntity.error("系统正在维护,请联系管理员.........");
}
// 处理业务异常
@ExceptionHandler(value = ShopException.class)
@ResponseBody
public ResultEntity businessException(ShopException e) {
log.error("业务异常", e);
return ResultEntity.error(e.getMsg());
}
}
ShopException实例:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ShopException extends RuntimeException{
private String msg;
private Integer code;
}
今天就到这儿吧。。。。。
本文章教学视频来自:https://www.bilibili.com/video/BV1tb4y1Q74E?p=3&t=125
静下心,慢慢来,会很快!