栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > 架构设计

畅购商城一:架构与基本CRUD

架构设计 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

畅购商城一:架构与基本CRUD


layout: pages
title: 项目开发笔记——电商一:项目架构
date: 2021-12-13 09:50:25
categories: 项目开发笔记
tags: 项目


概述

总共做了两套电商系统,从系统的架构到具体的技术栈都有着不同的技术选型,因此整理出这一个电商系列的笔记来进行技术路线的总结技术的对比,以”畅购商城“这一项目作为主线,将”品优购“作为对比,进行分析。

系统设计 技术栈

系统架构 微服务架构

本项目的系统架构如下:

首先从客户端发送请求作为起点出发进行叙述,客户端(PC或手机)发送请求经过路由后首先通过Nginx集群进行限流,而后请求发送到Gateway网关再次进行限流,而后发送到各个微服务,微服务向外提供http接口供给前端使用。各个微服务之间是通过注册中心Eureka组织起来的。关于Hytrix熔断,配置中心会在后面的章节进行叙述。

服务治理

与微服务相对应的还有服务治理的架构,如下图

同样是将服务进行了拆解,只不过与微服务架构存在些许的不同

SOA与微服务架构对比

首先需要说明的一点是,微服务架构是SOA,也就是面向服务架构的一种细粒度的实现

面向服务架构(SOA)强调解耦与拆分业务,并通过接口或协议将各个部分联系起来,微服务架构是满足这一种关系的,因此后续的对比更多的是针对微服务和与之相斥的传统SOA。在架构风格上,微服务与传统SOA主要存在这样几点区别:

  1. SOA喜欢重用,微服务喜欢重写:SOA强调EBS也就是企业服务总线的应用,各个服务之间有着比较高的依赖关系,在品优购的实践中,主要依靠的是dubbox,分别有服务的提供者和消费者(通过配置文件进行约定),而对于微服务架构,每个服务可以单独提供接口给用户使用,不同的服务之间可以采用不同的技术栈。

  2. SOA更偏向分层,而微服务更像是分块。二者的区别如下图

  1. SOA架构在设计开始时会先定义好服务合同(service contract),集中管理所有的服务,预先把每个模块服务接口都定义好。 模块系统间的通讯必须遵守这些接口,各服务是针对他们的调用者。微服务则敏捷得多。只要用户用得到,就先把这个服务挖出来。然后针对性的,快速确认业务需求,快速开发迭代。更方便进行拓展
注册中心 Eureka

Eureka架构图如下图所示

工作原理
  1. 服务启动后向注册中心注册自己的地址
  2. 各个服务端结点进行数据的同步
  3. 消费者调用提供者时会将地址进行缓存,下次直接从本地缓存中获取地址
  4. 服务端周期性发送心跳指令,在一定时间内未收到回复则注销该服务,并通知消费者更新本地缓存
CAP性质

Eureka保证AP,Eureka集群是点对点的方式,一个服务端宕机之后会转发给另一个服务端,保证可用性,不会返回错误,但是数据的一致性上有所损耗。

Zookeeper

Zookeeper保证CP,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪,因此Zookeeper并不是十分适用于当作微服务的注册中心。

其他的注册中心有Consel, Nacos,Nacos支持AP和CP的转换

基本CRUD

以品牌为例

表结构分析

品牌表:tb_brand

字段名称字段含义字段类型字段长度备注
id品牌idINT
name品牌名称VARCHAR
image品牌图片地址VARCHAR
letter品牌的首字母CHAR
seq排序INT
代码实现

上面品牌表对应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用于标识主键属性。

品牌列表

(1)Dao创建

在changgou-service-goods微服务下创建com.changgou.goods.dao.BrandMapper接口,代码如下:

public interface BrandMapper extends Mapper {
}

继承了Mapper接口,就自动实现了增删改查的常用方法。

(2)业务层

创建com.changgou.goods.service.BrandService接口,代码如下:

public interface BrandService {

    
    List findAll();
}

创建com.changgou.goods.service.impl.BrandServiceImpl实现类,代码如下:

@Service
public class BrandServiceImpl {

    @Autowired
    private BrandMapper brandMapper;

    
    public List findAll(){
        return brandMapper.selectAll();
    }
}

(3)控制层

控制层 com.changgou.goods包下创建controller包 ,包下创建类

@RestController
@RequestMapping("/brand")
@CrossOrigin
public class BrandController {

    @Autowired
    private BrandService brandService;

    
    @GetMapping
    public Result findAll(){
        List brandList = brandService.findAll();
        return new Result(true, StatusCode.OK,"查询成功",brandList) ;
    }
}

测试:http://localhost:18081/brand

根据ID查询品牌

(1)业务层

修改com.changgou.goods.service.BrandService接口,添加根据ID查询品牌数据方法,代码如下:

Brand findById(Integer id);

修改com.changgou.goods.service.impl.BrandServiceImpl新增方法,代码如下:

@Override
public Brand findById(Integer id){
    return  brandMapper.selectByPrimaryKey(id);
}

(2)控制层

BrandController新增方法

@GetMapping("/{id}")
public Result findById(@PathVariable Integer id){
    //根据ID查询
    Brand brand = brandService.findById(id);
    return new Result(true,StatusCode.OK,"查询成功",brand);
}
新增品牌

(1)业务层

修改com.changgou.goods.service.BrandService,新增方法

void add(Brand brand);

修改com.changgou.goods.service.impl.BrandServiceImpl,新增增加品牌方法代码如下:

@Override
public void add(Brand brand){
    brandMapper.insertSelective(brand);
}

(2) 控制层

BrandController新增方法

@PostMapping
public Result add(@RequestBody Brand brand){
    brandService.add(brand);
    return new Result(true,StatusCode.OK,"添加成功");
}
修改品牌

(1)业务层

需改com.changgou.goods.service.BrandService,添加修改品牌方法,代码如下:

void update(Brand brand);

修改com.changgou.goods.service.impl.BrandServiceImpl,添加修改品牌方法,代码如下:

@Override
public void update(Brand brand){
    brandMapper.updateByPrimaryKeySelective(brand);
}

(2)控制层

BrandController新增方法

@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,"修改成功");
}
删除品牌

(1)业务层

修改com.changgou.goods.service.BrandService,添加删除品牌方法,代码如下:

void delete(Integer id);

修改com.changgou.goods.service.impl.BrandServiceImpl,新增删除品牌方法,代码如下:

@Override
public void delete(Integer id){
    brandMapper.deleteByPrimaryKey(id);
}

(2)控制层

BrandController新增方法

@DeleteMapping(value = "/{id}" )
public Result delete(@PathVariable Integer id){
    brandService.delete(id);
    return new Result(true,StatusCode.OK,"删除成功");
}
品牌列表条件查询

(1)业务层

修改com.changgou.goods.service.BrandService,增加根据条件搜索品牌方法,代码如下:

List findList(Brand brand);

修改com.changgou.goods.service.impl.BrandServiceImpl,添加根据多条件搜索品牌方法的实现,代码如下:

@Override
public List findList(Brand brand){
    //构建查询条件
    Example example = createExample(brand);
    //根据构建的条件查询数据
    return brandMapper.selectByExample(example);
}



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新增方法

@PostMapping(value = "/search" )
public Result> findList(@RequestBody(required = false) Brand brand){
    List list = brandService.findList(brand);
    return new Result>(true,StatusCode.OK,"查询成功",list);
}
品牌列表分页查询

(1)业务层

修改com.changgou.goods.service.BrandService添加分页方法,代码如下:

PageInfo findPage(int page, int size);

修改com.changgou.goods.service.impl.BrandServiceImpl添加分页方法实现,代码如下:

@Override
public PageInfo findPage(int page, int size){
    //静态分页
    PageHelper.startPage(page,size);
    //分页查询
    return new PageInfo(brandMapper.selectAll());
}

(2)控制层

BrandController新增方法

@GetMapping(value = "/search/{page}/{size}" )
public Result findPage(@PathVariable  int page, @PathVariable  int size){
    //分页查询
    PageInfo pageInfo = brandService.findPage(page, size);
    return new Result(true,StatusCode.OK,"查询成功",pageInfo);
}
品牌列表条件+分页查询

(1)业务层

修改com.changgou.goods.service.BrandService,增加多条件分页查询方法,代码如下:

PageInfo findPage(Brand brand, int page, int size);

修改com.changgou.goods.service.impl.BrandServiceImpl,添加多条件分页查询方法代码如下:

@Override
public PageInfo findPage(Brand brand, int page, int size){
    //分页
    PageHelper.startPage(page,size);
    //搜索条件构建
    Example example = createExample(brand);
    //执行搜索
    return new PageInfo(brandMapper.selectByExample(example));
}

(2)控制层

BrandController新增方法

@PostMapping(value = "/search/{page}/{size}" )
public Result findPage(@RequestBody(required = false) Brand brand, @PathVariable  int page, @PathVariable  int size){
    //执行搜索
    PageInfo pageInfo = brandService.findPage(brand, page, size);
    return new Result(true,StatusCode.OK,"查询成功",pageInfo);
}
公共异常处理

为了使我们的代码更容易维护,我们创建一个类集中处理异常,该异常类可以创建在changgou-common工程中,创建com.changgou.framework.exception.BaseExceptionHandler,代码如下:

@ControllerAdvice
public class BaseExceptionHandler {

    
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result error(Exception e) {
        e.printStackTrace();
        return new Result(false, StatusCode.ERROR, e.getMessage());
    }
}

注意:@ControllerAdvice注解,全局捕获异常类,只要作用在@RequestMapping上,所有的异常都会被捕获。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/911479.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号