目录标题
- 一,什么是电商?
- 二,需求分析和系统设计
- 三,框架搭建
- 四,商品微服务(后端)
- 五,后台管理前端项目
- 五,前台管理前端项目
- 六,其他
- 六,搜索部分
- 六,商品详情页
- 六,微服务网关
- 六,RBAC简介
- 六,购物⻋与订单
- 六,⽀付微服务
- 六,秒杀微服务
- 六,高并发微服务
- 11问题集合
- 补充:之前画的图
一,什么是电商?
这部分没有什么好解释的,直接放资料了。
1.1 电商行业分析
近年来,世界经济正向数字化转型,大力发展数字经济成为全球共识。党的十九大报告明确提出要建设“数字中国”“网络强国”,我国数字经济发展进入新阶段,市场规模位居全球第二,数字经济与实体经济
深度融合,有力促进了供给侧结构性改革。电子商务是数字经济的重要组成部分,是数字经济最活跃、
最集中的表现形式之一。
2017年,在政府和市场共同推动下,我国电子商务发展更加注重效率、质量和创新,取得了一系列新的进展,在壮大数字经济、共建“一带一路”、助力乡村振兴、带动创新创业、促进经济转型升级等诸多方面发挥了重要作用,成为我国经济增长的新动力。 2017年,我国电子商务交易规模继续扩大,并保持高速增长态势。国家统计局数据显示,2017年全国电子商务交易额达29.16万
亿元,同比增长11.7%;网上零售额7.18万亿元,同比增长32.2%。
我国电子商务优势进一步扩大,网络零售规模全球最大、产业创新活力世界领先。数据显示,截止2017年底,全国网络购物用户规模达5.33亿,同比增长14.3%;非银行支付机构发生网络支付金额达143.26万亿元,同比增长44.32%;全国快递服务企业业务量累计完成400.6亿件,同比增长28%;电子商务直接从业人员和间接带动就业达4250万人。
2018天猫全天成交额记录
1.2 电商系统技术特点
技术新
技术范围广
分布式
高并发、集群、负载均衡、高可用
海量数据
业务复杂
系统安全
1.3 主要电商模式
B2B
B2B ( Business to Business)是指进行电子商务交易的供需双方都是商家(或企业、公司),她
(他)们使用了互联网的技术或各种商务网络平台,完成商务交易的过程。电子商务是现代 B2Bmarketing的一种具体主要的表现形式。
案例:阿里巴巴、慧聪网
C2C
C2C即 Customer(Consumer) to Customer(Consumer),意思就是消费者个人间的电子商务行为。比如一个消费者有一台电脑,通过网络进行交易,把它出售给另外一个消费者,此种交易类型就称为C2C电子商务。
案例:淘宝、易趣、瓜子二手车
B2C
B2C是Business-to-Customer的缩写,而其中文简称为“商对客”。“商对客”是电子商务的一种模式,也就是通常说的直接面向消费者销售产品和服务商业零售模式。这种形式的电子商务一般以网络零售业为主,主要借助于互联网开展在线销售活动。B2C即企业通过互联网为消费者提供一个新型的购物环境——网上商店,消费者通过网络在网上购物、网上支付等消费行为。
案例:唯品会、乐蜂网
C2B
C2B(Consumer to Business,即消费者到企业),是互联网经济时代新的商业模式。这一模式改变了原有生产者(企业和机构)和消费者的关系,是一种消费者贡献价值(Create Value), 企业和机构消费价值(Consume Value)。
C2B模式和我们熟知的供需模式(DSM, Demand SupplyModel)恰恰相反,真正的C2B 应该先有消费者需求产生而后有企业生产,即先有消费者提出需求,后有生产企业按需求组织生产。通常情况为消费者根据自身需求定制产品和价格,或主动参与产品设计、生产和定价,产品、价格等彰显消费者的个性化需求,生产企业进行定制化生产。
案例:海尔商城、 尚品宅配
O2O
O2O即Online To Offline(在线离线/线上到线下),是指将线下的商务机会与互联网结合,让互联网成为线下交易的平台,这个概念最早来源于美国。O2O的概念非常广泛,既可涉及到线上,又可涉及到线下,可以通称为O2O。主流商业管理课程均对O2O这种新型的商业模式有所介绍及关注。
案例:美团、饿了吗
F2C
F2C指的是Factory to customer,即从厂商到消费者的电子商务模式。
B2B2C
B2B2C是一种电子商务类型的网络购物商业模式,B是BUSINESS的简称,C是CUSTOMER的简称,第一个B指的是商品或服务的供应商,第二个B指的是从事电子商务的企业,C则是表示消费者。
案例:京东商城、天猫商城
我们《畅购电商系统开发》课程采用B2C模式。
二,需求分析和系统设计
2.1 需求分析
在docker中启动容器
启动后台服务
启动前台门户
#进入目录legou-portal-ui,执行如下命令
npm run dev
启动后台管理
# 进入legou-manager-ui
npm run dev
2.2系统设计
新职课商城属于B2C电商模式,运营商将自己的产品发布到网站上,会员注册后,在网站上将商品添加到购物车,并且下单,完成线上支付,用户还可以参与秒杀抢购。
2.2.1 前后端分离
商城项目采用前后端分离方式。
以前的JavaWeb项目大多数都是java程序员又当爹又当妈,又搞前端,又搞后端。随着时代的发展,渐渐的许多大中小公司开始把前后端的界限分的越来越明确,前端工程师只管前端的事情,后端工程师只管后端的事情。正所谓术业有专攻,一个人如果什么都会,那么他毕竟什么都不精。
对于后端java工程师:
把精力放在设计模式,spring+springmvc,linux,mysql事务隔离与锁机制,mongodb,http/tcp,
多线程,分布式架构,弹性计算架构,微服务架构,java性能优化,以及相关的项目管理等等。
对于前端工程师:
把精力放在html5,css3,vuejs,webpack,nodejs,Google V8引擎,javascript多线程,模块化,
面向切面编程,设计模式,浏览器兼容性,性能优化等等。
我们在本课程中提供与项目课程配套的管理后台的前端代码,但是不深入讲解前端的内容。这样我们会
将更多的精力放在后端代码的开发上!
2.2.2 技术架构
2.2.3 系统架构图
三,框架搭建
3.1 环境准备
(1)VMware Workstation Pro安装centos7 镜像
(2)安装docker
(3)拉取mySQL镜像,并创建容器
(4)客户端连接mysql容器,建库建表(建库建表语句在资源文件夹中提供)
虚拟机数据:
虚拟机IP:192.168.220.110
虚拟机账号:root 密码:1
数据库端口:3306
数据库账号:root 密码:root
数据库脚本: 资料\数据库脚本
注:现成的虚拟机环境我放在网盘资料里了。直接使用既可。注意配置一下虚拟机的网络设置。
3.2 项目结构说明
结构说明:
gateway
网关模块,根据网站的规模和需要,可以将综合逻辑相关的服务用网关路由组合到一起。在这里还可以做鉴权和限流相关操作。
config
配置中心微服务
registry
注册中心
3.3 公共工程搭建
3.3.1 父工程搭建
创建父工程 legou-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.lxs</groupId>
<artifactId>legou-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<!--这里的可以先注释了,等到创建对应模块再引入
<module>registry</module>
<module>config</module>
<module>auth-center</module>
<module>legou-admin</module>
<module>gateway</module>
<module>legou-security</module>
<module>legou-route</module>
<module>legou-upload</module>
<module>legou-item</module>
<module>legou-search</module>-->
<module>legou-core</module><!--基类-->
<module>legou-common</module><!--公共类-->
</modules><!---->
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency><!--apache的工具类-->
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.3.2创建通用工程
通用工程里放入一些基本的工具类。
3.3.3基类(legou-core)
3.3.3.1pom.xml
legou-core工程中存放dao,service,controller的基类,其他具体dao,service,controller都是继承自此工
程的类,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>legou-parent</artifactId>
<groupId>com.lxs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>legou-core</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
-->
<!--mybatis pulus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.11</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.core.Starter</mainClass>
<layout>ZIP</layout>
<classifier>exec</classifier>
<includeSystemScope>true</includeSystemScope>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
3.3.3.2实体类基类
普通实体类基类
package com.lxs.legou.core.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
/**
* @file BaseEntity.java
* @Copyright (C) http://www.lxs.com
* @author lxs
* @email lxosng77@163.com
* @date 2018/7/12
*/
@Data
@JsonIgnoreProperties(value = {
"handler"})
public abstract class BaseEntity implements Serializable {
/**
* 实体编号(唯一标识)
*/
@TableId(value = "id_", type = IdType.AUTO)
protected Long id;
}
树形结构实体类基类
package com.lxs.legou.core.po;
HTTP响应返回结果实体类
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* 树状结构实体类父类
*
* @author lxs
* @file BaseTreeEntity.java
* @Copyright (C) http://www.lxs.com
* @email lxosng77@163.com
* @date 2018/7/13
*/
@Data
@JsonIgnoreProperties(value = {
"handler"}) //避免懒加载,json转换报错
public class BaseTreeEntity extends BaseEntity {
@TableField("order_")
private Integer order; //排序字段
@TableField("parent_id_")
private Long parentId; //父节点id
@TableField("title_")
private String title; //节点名称
@TableField("expand_")
private Boolean expand = false; //是否展开节点
}
HTTP响应返回结果实体类
package com.lxs.legou.core.po;
import java.io.Serializable;
/**
* @Title: Controller响应实体
* @Description:
*
* @Copyright 2019 lxs - Powered By 雪松
* @Author: lxs
* @Date: 2019/10/3
* @Version V1.0
*/
public class ResponseBean implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 成功标记
*/
private boolean success = true;
/**
* 提示信息
*/
private String msg = "操作成功";
/**
* 添加,修改的实体类
*/
private Object model;
/**
* http状态码
*/
private int code = 200;
/**
* session id
*/
private String token;
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getModel() {
return model;
}
public void setModel(Object model) {
this.model = model;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
3.3.3.3dao基类
package com.lxs.legou.core.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lxs.legou.core.po.BaseEntity;
import java.util.List;
public interface ICrudDao<T extends BaseEntity> extends BaseMapper<T> {
/**
* 一般要是用动态sql语句查询
* @param entity
* @return
*/
public List<T> selectByPage(T entity);
}
3.3.3.4 service基类
接口:
package com.lxs.legou.core.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.github.pagehelper.PageInfo;
import com.lxs.legou.core.po.BaseEntity;
import java.util.List;
public interface ICrudService<T extends BaseEntity> extends IService<T> {
public PageInfo<T> listPage(T entity, int pageNum, int pageSize);
public List<T> list(T entity);
}
实现类:
package com.lxs.legou.core.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lxs.legou.core.dao.ICrudDao;
import com.lxs.legou.core.po.BaseEntity;
import com.lxs.legou.core.service.ICrudService;
import java.util.List;
public class CrudServiceImpl<T extends BaseEntity> extends
ServiceImpl<ICrudDao<T>, T> implements ICrudService<T> {
@Override
public PageInfo<T> listPage(T entity, int pageNum, int pageSize) {
return PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(() -> {
baseMapper.selectByPage(entity);
});
}
@Override
public List<T> list(T entity) {
return getBaseMapper().selectList(Wrappers.emptyWrapper());
}
}
3.3.3.5 controller基类
package com.lxs.legou.core.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageInfo;
import com.lxs.legou.core.po.BaseEntity;
import com.lxs.legou.core.po.ResponseBean;
import com.lxs.legou.core.json.JSON;
import com.lxs.legou.core.service.ICrudService;
import com.lxs.legou.core.utils.GenericUtil;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author lxs
* @file BaseController.java
* @Copyright (C) http://www.lxs.com
* @email lxosng77@163.com
* @date 2018/7/13
*/
public abstract class BaseController<S extends ICrudService<T>, T extends
BaseEntity> {
@Autowired
protected S service;
protected Logger LOG = LoggerFactory.getLogger(this.getClass());
/**
* 域对象类型
*/
protected Class<T> entityClass;
public BaseController() {
this.entityClass = GenericUtil.getSuperGenericClass2(this.getClass());
}
/**
* 加载
*
* @param id
* @return
* @throws Exception
*/
@ApiOperation(value="加载", notes="根据ID加载")
@GetMapping("/edit/{id}")
public T edit(@PathVariable Long id) throws Exception {
T entity = service.getById(id);
afterEdit(entity);
return entity;
}
/**
* 分页查询
* @param entity
* @param page
* @param rows
* @return
*/
@ApiOperation(value="分页查询", notes="分页查询")
@PostMapping("/list-page")
@JSON(type = BaseEntity.class ,filter = "desc") //无效
public PageInfo<T> listPage(T entity,
@RequestParam(name = "page", defaultValue = "1",
required = false) int page,
@RequestParam(name = "rows", defaultValue = "10",
required = false) int rows) {
PageInfo<T> result = service.listPage(entity, page, rows);
return result;
}
/**
* 根据实体条件查询
* @return
*/
@ApiOperation(value="查询", notes="根据实体条件查询")
@RequestMapping(value = "/list", method = {
RequestMethod.POST,
RequestMethod.GET})
@JSON(type = BaseEntity.class ,filter = "desc")
public List<T> list(T entity) {
List<T> list = service.list(entity);
return list;
}
/**
* 增加,修改
*/
@ApiOperation(value="保存", notes="ID存在修改,不存在添加")
@PostMapping("/save")
public ResponseBean save(T entity) throws Exception {
ResponseBean rm = new ResponseBean();
try {
beforeSave(entity); //保存前处理实体类
service.saveOrUpdate(entity);
rm.setModel(entity);
} catch (Exception e) {
e.printStackTrace();
rm.setSuccess(false);
rm.setMsg("保存失败");
}
return rm;
}
/**
* 删除
*/
@ApiOperation(value="删除", notes="根据ID删除")
@GetMapping("/delete/{id}")
public ResponseBean delete(@PathVariable Long id) throws Exception {
ResponseBean rm = new ResponseBean();
try {
service.removeById(id);
rm.setModel(null);
} catch (Exception e) {
e.printStackTrace();
rm.setSuccess(false);
rm.setMsg("保存失败");
}
return rm;
}
/**
* 批量删除
*/
@ApiOperation(value="删除", notes="批量删除")
@RequestMapping(value = "/delete", method = {
RequestMethod.POST,
RequestMethod.GET})
public ResponseBean delete(@RequestParam List<Long> ids) {
ResponseBean rm = new ResponseBean();
try {
service.removeByIds(ids);
} catch (Exception e) {
e.printStackTrace();
rm.setMsg("删除失败");
rm.setSuccess(false);
}
return rm;
}
/**
* 保存前执行
* @param entity
* @throws Exception
*/
public void beforeSave(T entity) throws Exception {
}
/**
* 模板方法:在加载后执行
* @param entity
*/
public void afterEdit(T entity) {
}
}
3.3.3.6 工具类
(1)ApplicationContextProvider:获得spring容器中的对象的工具类
spring 容器产生时产生ApplicationContextProvider,因为实现了ApplicationContextAware调用setApplicationContext后,可以直接使用ApplicationContextProvider获得spring容器中的对象
package com.lxs.legou.core.support;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* @file ApplicationContextProvider.java
* @Copyright (C) http://www.lxs.com
* @author lxs
* @email lxosng77@163.com
* @date 2018/7/13
*/
@Component
public class ApplicationContextProvider
implements ApplicationContextAware {
/**
* 上下文对象实例
*/
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 获取applicationContext
*
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通过name获取 Bean.
*
* @param name
* @return
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/**
* 通过class获取Bean.
*
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
/**
* 通过name,以及Clazz返回指定的Bean
*
* @param name
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
(2)DateConverterConfig:日期转换器
package com.lxs.legou.core.support;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @file DateConverterConfig.java
* @Copyright (C) http://www.lxs.com
* @author lxs
* @email lxosng77@163.com
* @date 2018/7/13
*/
@Component
public class DateConverterConfig implements Converter<String, Date> {
private static final List<String> formarts = new ArrayList<>(4);
static{
formarts.add("yyyy-MM");
formarts.add("yyyy-MM-dd");
formarts.add("yyyy-MM-dd hh:mm");
formarts.add("yyyy-MM-dd hh:mm:ss");
}
@Override
public Date convert(String source) {
String value = source.trim();
if ("".equals(value)) {
return null;
}
if(source.matches("^\\d{4}-\\d{1,2}$")){
return parseDate(source, formarts.get(0));
}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")){
return parseDate(source, formarts.get(1));
}else if(source.matches("^\\d{
4}-\\d{
1,2}-\\d{
1,2}
{
1}\\d{
1,2}:\\d{
1,2}$")){
return parseDate(source, formarts.get(2));
}else if(source.matches("^\\d{
4}-\\d{
1,2}-\\d{
1,2}
{
1}\\d{
1,2}:\\d{
1,2}:\\d{
1,2}$")){
return parseDate(source, formarts.get(3));
}else {
throw new IllegalArgumentException("Invalid boolean value '" +
source + "'");
}
}
/**
* 格式化日期
* @param dateStr String 字符型日期
* @param format String 格式
* @return Date 日期
*/
public Date parseDate(String dateStr, String format) {
Date date=null;
try {
DateFormat dateFormat = new SimpleDateFormat(format);
date = dateFormat.parse(dateStr);
} catch (Exception e) {
}
return date;
}
}
(3)GenericUtil:得到父类声明的泛化类型
package com.lxs.legou.core.utils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* @file GenericUtil.java
* @Copyright (C) http://www.lxs.com
* @author lxs
JSON工具类(拷贝即可)
支持使用@JSON(type = Post.class ,filter = "desc"),过滤不序列化的字段等操作,因为Jackson注解,
要么全部序列化,要么全部不序列化
* @email lxosng77@163.com
* @date 2018/7/13
*/
public class GenericUtil {
public static <T> Class<T> getSuperGenericClass(Class<?> clz) {
Class<T> result = null;
//得到当前对象的父类"泛型类型"(也叫参数化类型)
//superclass == GenericDao<Dept>成为参数化类型
//superclass == BaseDao不是参数化类型
Type superclass = clz.getGenericSuperclass();
//判断类型是否为参数化类型
if (superclass instanceof ParameterizedType) {
//把父类类型转换成参数化类型(泛型类型)
//只有ParameterizedType才能通过getActualTypeArguments得到参数
ParameterizedType parameterizedType = (ParameterizedType) superclass;
//得到参数化类型类型的参数
//types == GenericDao<Dept>的"<Dept>"参数
Type[] types = parameterizedType.getActualTypeArguments();
//返回子类传递的类型
result = (Class<T>) types[0];
}
return result;
}
public static <T> Class<T> getSuperGenericClass2(Class<?> clz) {
Class<T> result = null;
//得到当前对象的父类"泛型类型"(也叫参数化类型)
//superclass == GenericDao<Dept>成为参数化类型
//superclass == BaseDao不是参数化类型
Type superclass = clz.getGenericSuperclass();
//判断类型是否为参数化类型
if (superclass instanceof ParameterizedType) {
//把父类类型转换成参数化类型(泛型类型)
//只有ParameterizedType才能通过getActualTypeArguments得到参数
ParameterizedType parameterizedType = (ParameterizedType) superclass;
//得到参数化类型类型的参数
//types == GenericDao<Dept>的"<Dept>"参数
Type[] types = parameterizedType.getActualTypeArguments();
//返回子类传递的类型
result = (Class<T>) types[1];
}
return result;
}
}
(4)JSON工具类(拷贝即可)
支持使用@JSON(type = Post.class ,filter = “desc”),过滤不序列化的字段等操作,因为Jackson注解,要么全部序列化,要么全部不序列化
示例:
/**
* @Title:
* @Description:
*
* @Copyright 2019 lxs - Powered By 雪松
* @Author: lxs
* @Date: 2019/10/3
* @Version V1.0
*/
@RestController
@RequestMapping("/post")
public class PostController extends BaseController<IPostService, Post> {
/**
* 演示使用JSON注解过滤属性
* @return
*/
@ApiOperation(value="查询", notes="查询所有")
@RequestMapping(value = "/list", method = {
RequestMethod.POST,
RequestMethod.GET})
@JSON(type = Post.class ,filter = "desc")
public List<Post> list(Post post) {
List<Post> list = service.list(post);
return list;
}
3.4Eureka微服务搭建
3.4.1 pom.xml依赖
创建模块registry,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>legou-parent</artifactId>
<groupId>com.lxs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>registry</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
3.4.2 配置
配置文件bootstrap.yml
spring:
application:
name: registry
application.yml
server:
port: 8761
eureka:
server:
enable-self-preservation: false # 关闭自我保护模式(缺省为打开)
eviction-interval-timer-in-ms: 1000 # 扫描失效服务的间隔时间(缺省为60*1000ms)
instance:
hostname: localhost
prefer-ip-address: true
client:
register-with-eureka: false # 是否注册自己的信息到EurekaServer,默认是true
fetch-registry: false # 是否拉取其它服务的信息,默认是true
service-url:
defaultZone: http://${
eureka.instance.hostname}:${
server.port}/eureka/
bootstrap.yml与application.yml配置文件:
1,先加载bootstrap.yml后加载application.yml
2,以后的application.yml文件是要放在配置中心微服务的。
3,bootstrap.yml里放当前微服务工程里的具体的配置,主要就是名称。
3.4.3 启动类配置
package com.lxs.legou.registry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class RegistryApplication {
public static void main(String[] args) {
SpringApplication.run(RegistryApplication.class, args);
}
}
测试访问 http://localhost:8761/ ,效果如下:
3.5 配置中心微服务
配置中心微服务为其他微服务工程,提供统一的配置文件的管理,这里我们采用两种方式管理配
置文件
native:本地配置文件
git:远程配置文件
3.5.1 pom.xml
创建config微服务工程,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>legou-parent</artifactId>
<groupId>com.lxs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>config</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>可以引入,也可以不引入
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
</project>
3.5.2 配置文件
bootstrap.yml
spring:
application:
name: config
application.yml
server:
port: 8888
eureka:
client:
registry-fetch-interval-seconds: 5 #Server服务的列表只读备份,然后缓存在本地。默认30秒
service-url:
defaultZone: http://${
eureka.instance.hostname}:8761/eureka/
instance:
hostname: localhost
prefer-ip-address: true
lease-expiration-duration-in-seconds: 10 # 10秒即过期
lease-renewal-interval-in-seconds: 5 # 5秒一次心跳
spring:
profiles:
active: composite,default # 如果要使用本地配置文件,此处需增加composite。多profile时,谁在前面谁的配置优先级就高
cloud:
config:
server:
bootstrap: true # 提前加载配置文件,保证后续数据库连接正常启动
default-profile: default
default-label: master
composite: # 此配置为使用本地文件,与git脱离关系
- type: native
search-locations: file:D:\eclipse-workspace\Z_XM_shizhan\project\legou-parent\config-repo
git: #git配置
uri: https://gitee.com/wang-yu-hui/config-repo.git
username: xxxxxxxxxxx
password: xxxxxx
search-paths: config-repo
3.5.3 启动器
package com.lxs.legou.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}
3.5.4 微服务配置
/config-repo/application.yml:所有配置文件都从此配置文件继承。
application.yml:
server:
port: 8888
eureka:
client:
registry-fetch-interval-seconds: 5 #Server服务的列表只读备份,然后缓存在本地。默认30秒
service-url:
defaultZone: http://${
eureka.instance.hostname}:8761/eureka/
instance:
hostname: localhost
prefer-ip-address: true
lease-expiration-duration-in-seconds: 10 # 10秒即过期
lease-renewal-interval-in-seconds: 5 # 5秒一次心跳
spring:
profiles:
active: composite,default # 如果要使用本地配置文件,此处需增加composite。多profile时,谁在前面谁的配置优先级就高
cloud:
config:
server:
bootstrap: true # 提前加载配置文件,保证后续数据库连接正常启动
default-profile: default
default-label: master
composite: # 此配置为使用本地文件,与git脱离关系
- type: native
search-locations: file:D:\eclipse-workspace\Z_XM_shizhan\project\legou-parent\config-repo
git: #git配置
uri: https://gitee.com/wang-yu-hui/config-repo.git
username: 13766540206
password: 123654qw
search-paths: config-repo
配置admin-service.yml如下:(之后用到的配置,见名知意)
server:
port: 9001
mybatis-plus:
mapper-locations: classpath*:mybatis/*/*.xml
type-aliases-package: com.lxs.legou.*.po
configuration:
# 下划线驼峰转换
map-underscore-to-camel-case: true
lazy-loading-enabled: true
aggressive-lazy-loading: false
logging:
#file: demo.log
pattern:
console: "%d - %msg%n"
level:
org.springframework.web: debug
com.lxs: debug
security:
oauth2:
resource:
jwt:
key-uri: http://localhost:9098/oauth/token_key #如果使用JWT,可以获取公钥用于 token 的验签
启动配置中心微服务:
访问http://localhost:8888/admin-service.yml显示如下:
四,商品微服务(后端)
4.1品牌管理
这个是最为简单的功能,用这个功能熟悉一下这个模板的使用。
4.1.1 需求分析
创建商品微服务,实现对品牌表的增删改查功能(单表操作)
其中要注意商品分类和品牌是多对多的关系。(双表多对多操作)
4.1.2 表结构分析
这个看上面的图片就差不多猜到了。
品牌表:brand_
4.1.3 创建工程
创建legou-item父工程,聚合管理两个子工程legou-item-instance和legou-item-service
legou-item-instance:存放fegin调用的接口和实体类
legou-item-service:存放实际商品微服务
结构如下
4.1.3.1 legou-item
<?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>legou-parent</artifactId>
<groupId>com.lxs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>legou-item</artifactId>
<packaging>pom</packaging>
<modules>
<module>legou-item-instance</module>
<module>legou-item-service</module>
</modules>
</project>
4.1.3.2legou-item-instance
<?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>legou-item</artifactId>
<groupId>com.lxs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>legou-item-instance</artifactId>
<dependencies>
<dependency>
<groupId>com.lxs</groupId>
<artifactId>legou-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.core.Starter</mainClass>
<layout>ZIP</layout>
<classifier>exec</classifier>
<includeSystemScope>true</includeSystemScope>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
4.1.3.3 legou-item-service
4.1.3.3.1 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>legou-item</artifactId>
<groupId>com.lxs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>legou-item-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId><!--这个可以不用写-->
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId><!--测试-->
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId><!--eureka-->
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId><!--可能会引入其他微服务-->
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId><!--熔断-->
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId><!--配置中心-->
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId><!--重复连接配置中心-->
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>com.lxs</groupId>
<artifactId>legou-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql