后端 SpringBoot+SpringCloud+Docker
前端 Vue Element UI
vagrant box add my_first_box E:\imagebox\vagrant-centos-7.box
vagrant box list
vagrant init my_first_box
vagrant up
在有vagrantFile文件的目录输入命令:
vagrant ssh
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' {
"registry-mirrors": ["https://gaqicnpb.mirror.aliyuncs.com"] } EOF
重新加载守护文件
sudo systemctl daemon-reload
重启docker
sudo systemctl restart docker
将mysql安装在容器里,端口号映射、文件挂载目录都配置好
sudo docker run -p 3306:3306 --name mysql \ -v /mydata/mysql/conf:/etc/mysql \ -v /mydata/mysql/log:/var/log/mysql \ -v /mydata/mysql/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=root \ -d mysql:5.7
启动一个容器
docker run 镜像名
进入容器
docker exec -it 容器id /bin/bash
创建my.cnf文件
vi /mydata/mysql/conf/my.cnf
my.cnf文件配置如下:
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
docker container update --restart=always 容器名字
mkdir -p /mydata/redis/conf
touch /mydata/redis/conf/redis.conf
docker run -p 6379:6379 --name redis -v /mydata/redis/data:/data \
-v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \
-d redis redis-server /etc/redis/redis.conf
进入redis客户端
docker exec -it redis redis-cli
跟着官网一步一步配置
git config --global user.name "hezekun"
git config --global user.email "[email protected]"
ssh-keygen -t rsa -C "[email protected]"
cat ~/.ssh/id_rsa.pub
密钥
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDY2e1xVWqjldKL38rxW55CxFAEVcmPyPc8syPfp57gs5Fz+hS7z96khDAOZ9FKn75M9v8mSKz46kWqOf6GEKB9U832qP1uVs5ZLRfy4J+T7GmnNWQTpF1w+3O1+Pc5QVpTx7PalrQtlyTIeHoja9lnSm4lzacvNhM/V8Mfa+U1lGP2LSG3OM5pd3Ih5N36P7vCNK7Re7eomZwM2kwmYwipgvxUCDACTGQ6JhVMlO1erSqoQYajPqVpPSfoxMUnQ7XcngD/kbAlKjBuFSELuAffa7TELNrMkVmZtoeg8UaOGbQ0OgGePst76DkdinCMv64sn/4gKl5Eg+uR3W1HWAzF 自己的邮箱
ssh -T git@gitee.com
后台renren-fast
前端开发Node.js
NPM是随同NodeJS一起安装的包管理工具,JavaScript Java-Maven
①官网下载node.js
②配置npm使用淘宝镜像
npm config set registry http://registry.npm.taobao.org/
npm install -g mirror-config-china --registry=http://registry.npm.taobao.org
npm install node-sass
renren-generator
公共模块依赖和工具
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.12</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<!--导入数据库驱动-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
操作步骤
1.修改application.yml里的数据源的数据库连接
2.修改generator.properties文件里的 mainPath package author email tablePrefix
3.运行renren-generator -> 访问页面 -> 全选表 -> 生成代码
将压缩包放在一个文件夹里解压,将生成的main文件夹 粘贴到 对应的模块的src目录下
4.引入公共依赖
<dependency>
<groupId>com.hzk.gulimall</groupId>
<artifactId>gulimall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
5.在resources文件夹下创建application.yml文件,并修改数据源和端口
spring:
datasource:
username: root
password: root
url: jdbc:mysql://192.168.56.10:3306/gulimall_wms?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
server:
port: 11000
6.在入口Application类里加上包扫描
@MapperScan("com.hzk.gulimall.ware.dao")
在common的pom.xml里导入依赖管理
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2.下载nacos server 1.2
3. 在各个服务里的application.yml文件里加上服务名和nacos地址
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: gulimall-coupon
4. 加上注解@EnableDiscoveryClient
5. 访问http://127.0.0.1:8848/nacos/ 即可看到可视化界面的服务列表
1.引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.在入口处加上注解,开启feign功能
@EnableFeignClients(basePackages = “com.hzk.gulimall.coupon.feign”)
3.声明远程接口
先用@FeignClient(“服务注册名”)声明想要调用的服务,再将想要调用的方法去controller里整个签名复制出来,粘贴到对应的feign服务接口里
4.在本服务的controller层里调用feign服务接口,就可以实现跨服务调用
/**
* feign 远程调用服务
* @return
*/
@RequestMapping("/member")
public R test(){
Map<String,Object> map = new HashMap<>();
R list = memberFeignService.list(map);
return R.ok().put("list",list);
}
1. 添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2. 在resources文件夹下创建bootstrap.properties文件,添加如下内容
bootstrap.properties
spring.application.name=example
nacos.config.server-addr=127.0.0.1:8848
datasource.yml
spring:
datasource:
username: root
password: root
url: jdbc:mysql://192.168.56.10:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis.yml
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
other.yml
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: gulimall-coupon
server:
port: 7000
3.使用spring.cloud.nacos.config.extension-configs
1.在application.properties里添加服务注册nacos
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.application.name=gulimall-gateway
server.port=88
2.在nacos配置中心创建命名空间,添加gulimall-gateway.yml配置
3.在bootstrap.properties里添加配置中心地址,所属服务和分组
spring.application.name=gulimall-gateway
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=03fdf9c2-ac6d-4191-baf4-86681151fa91
4.在application.yml里添加网关的断言规则
spring:
cloud:
gateway:
routes:
- id: baidu_route
uri: https://www.baidu.com
predicates:
- Query=url,baidu
- id: qq_route
uri: https://www.qq.com
predicates:
- Query=url,qq
public List<CategoryEntity> listWithTree() {
//1.查出所有分类
List<CategoryEntity> categoryEntities = baseMapper.selectList(null);
//2.组装成父子的树形结构
//2.1)找到所有的一级分类
/*List level1Menu = categoryEntities.stream().filter((categoryEntity) -> {
return categoryEntity.getParentCid() == 0;
}).collect(Collectors.toList());*/
//2.2)找到一级分类和子菜单
List<CategoryEntity> level1Menu = categoryEntities.stream().filter((categoryEntity) -> {
return categoryEntity.getParentCid() == 0;
}).map((menu)->{
menu.setChildren(getChildrenTree(menu,categoryEntities));
return menu;
}).sorted((menu1,menu2)->{
return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
}).collect(Collectors.toList());
return level1Menu;
}
/**
* 递归查找所有菜单的子菜单
* @param root
* @param all
* @return
*/
private List<CategoryEntity> getChildrenTree(CategoryEntity root,List<CategoryEntity> all){
List<CategoryEntity> children = all.stream().filter((categoryEntity) -> {
//传入根节点和菜单实体集合,过滤得到父id = 根节点的id 的菜单all
return categoryEntity.getParentCid() == root.getCatId();
}).map((categoryEntity) -> {
//每个菜单打包成map,递归添加子菜单
categoryEntity.setChildren(getChildrenTree(categoryEntity, all));
return categoryEntity;
}).sorted((menu1, menu2) -> {
//菜单排序
return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
}).collect(Collectors.toList());
return children;
}
这样就可以拿到三级菜单分类的数据
前段发请求失败,需要解决跨域问题
跨域:指的是浏览器不能执行其他网站的脚本,他是本浏览器的同源策略造成的,是浏览器对javaScript施加的安全限制。
同源策略:是指协议,域名,端口都要相同,其中有一个不同就会产生跨域。
跨域解决方案一
如上,可以将前端vue和后台都部署到同一台nginx下,这样浏览器访问就不需要访问项目的真实路径,而只需要访问nginx的路径就可以了。
跨域解决方案二
如上,可以对跨域进行这些配置,但是不能每个跨域都来进行这样的配置,太麻烦,所以写一个Filter,所有的请求进来之后,放行,执行完之后返回给浏览器,在响应中添加上这几个字段。在网关里面统一配置跨域就可以了。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
/**
* @author fuzq
* @create
*/
@Configuration
public class XigumallCorsConfiguration {
@Bean
public CorsWebFilter corsWebFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//所有跟跨域有关的配置都写在以下里面
CorsConfiguration corsConfiguration = new CorsConfiguration();
//配置跨域
corsConfiguration.addAllowedHeader("*");//允许哪些头通过
corsConfiguration.addAllowedMethod("*");//允许哪些请求方式进行跨域
corsConfiguration.addAllowedOrigin("*");//允许哪些请求来源进行跨域
corsConfiguration.setAllowCredentials(true);//是否允许携带cookie进行跨域
source.registerCorsConfiguration("/**", corsConfiguration);//任意路径都进行,注册跨域的配置
return new CorsWebFilter(source);
}
}
比如说在前端点击一个查询服务,他会触发请求,但是这个请求却是提交给了renren-fast/…但是我们实际上是想调用我们的产品模块的方法,而产品的接口配置的是10000,如下所示,定义了API的基准路径地址,难道要改成10000吗,当然不是,以后还有10001,10002…所以我们统一提交给网关,交给网关来进行路由。改成网关的地址:‘http://localhost:88/api’,这里所有前台发来的请求都加上了/api;
但是在将路径修改为"http://localhost:88/api"后,我们要加载验证码的请求,确实发送给网关了,但是网关并处理不了这个问题,还应该路由给指定的要解决问题的服务,所以讲网关注册进注册中心,然后由网关来进行路由到指定的处理地址。
spring:
cloud:
gateway:
routes:
- id: admin_route
uri: lb://renren-fast
predicates:
- Path=/api/**
如上所示,在网关中进行配置,将所有前台发来的请求路由到renren-fast,但是这样仍然会存在问题,因为他会路由到renren-fast也就是8001,但是实际请求的路径并不是这样的,所以这里就需要我们网关对路径进行重写。官网参考如下:
https://www.springcloud.cc/spring-cloud-greenwich.html#_spring_cloud_gateway
spring:
cloud:
gateway:
routes:
- id: admin_route
uri: lb://renren-fast
predicates:
- Path=/api/**
filters:
- RewritePath=/api/(?.*),/renren-fast/$\{segment}
##前端项目发来的请求统一加前缀 ,/api
##将地址:http://localhost:88/api/captcha.jpg?
##路由成 :http://localhost:8080/renren-fast/captcha.jpg
这样就可以实现访问了,验证码就出来了。
前端负责收集数据,组装好各种数据,发送后台,后台将前端组装好的数据转换成自己想要的数据,然后调用Service,整个期间用的最多的方式是Http,而且发送的是post方式,将所有的数据直接转为json,然后后台通过@RequestBody注解将json转换成自己需要的格式
前台发来的所有请求全部路由到renren-fast了,但是我们想要请求的实际是product模块,所以就要对网关添加一个断言,也将product模块注册进注册中心。如下,因为网关是从上向下执行的,所有断言的顺序是要注意的。
spring:
cloud:
gateway:
routes:
- id: product_route
uri: lb://gulimall-product
predicates:
- Path=/api/product/**
##http://localhost:8888/api/product/category/list/tree 重写成 http://localhost:10000/product/category/list/tree
filters:
- RewritePath=/api/(?.*),/$\{segment}
- id: admin_route
uri: lb://renren-fast
##前端项目发来的请求统一加前缀 ,/api
predicates:
- Path=/api/**
filters:
##http://localhost:88/api/captcha.jpg? 重写成 http://localhost:8080/renren-fast/captcha.jpg
- RewritePath=/api/(?.*),/renren-fast/$\{segment}
到这里网关的路由转发已经配置完毕。