文章目录
2、项目架构图
1)、微服务项目架构图
这张图为我们介绍了项目的技术整合方案和技术架构;该项目是前后端分离的项目,在外网可以部署我们的前端页面,内网则部署我们的后端服务器;
项目的正常流程是前端通过任意客户端访问我们的Nginx集群服务,Nginx把
3、谷粒商城-VirtualBox+Vagrant快速搭建linux环境
3.1.搭建linx环境
3.2.软件
-
安装Virtual Box
访问:VirtualBox 官网
-
安装Vagrant
访问:Vagrant
安装vagrant
安装完毕后需要重启电脑。 -
cmd中输入vagrant有版本代表成功了
3.3 初始化一个centos7系统
-
输入vagrant init centos/7,即可初始化一个centos7系统。(注意这个命令在哪个目录下执行的,他的Vagrantfile就生成在哪里)
可以看到用户/1目录下生成了Vagrantfile。
-
此时virtualbox还没有虚拟机
-
vagrant up启动虚拟机环境
-
出现错误
2023/3/21
7. clone renren-generator
使用代码生成器生成最基本的crud;
7.1 修改配置
模块:gulimall-product —— gulimall_pms
模块:gulimall-order —— gulimall_oms
模块:gulimall-ware —— gulimall_wms
模块:gulimall-coupon —— gulimall_sms
模块:gulimall-member —— gulimall_ums
- 在配置文件里指定数据库的连接:
server:
port: 8088
# mysql
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
#MySQL配置
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/gulimall_pms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 136818
- renren-generator/src/main/resources/generator.properties
#代码生成器,配置信息
mainPath=com.dh,gulimall
#包名
package=com.dh.gulimall
moduleName=product/order/ware/coupon/member
#作者
author=dh
#Email
email=1737441779@qq.com
#表前缀(类名不会包含表前缀)
tablePrefix=pms_
- 运行RenrenApplication,访问http://127.0.0.1:8088
- product模块:
common
- 然后在项目上右击(在项目上右击很重要)new modules— maven—然后在name上输入gulimall-common。
- 在父项目的pom.xml中也自动添加了gulimall-common
<modules>
<module>gulimall-product</module>
<module>gulimall-order</module>
<module>gulimall-ware</module>
<module>gulimall-coupon</module>
<module>gulimall-member</module>
<module>renren-fast</module>
<module>renren-generator</module>
<module>gulimall-common</module>
</modules>
- 在common项目的pom.xml中添加依赖
<!-- mybatisPLUS-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
<!--简化实体类,用@Data代替getset方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
<!-- httpcomponent包。发送http请求 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.13</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
- 我们把每个微服务里公共的类和依赖放到common里
然后在product项目中的pom.xml中加入下面内容,作为common的子项目
<dependency>
<groupId>com.dh</groupId>
<artifactId>gulimall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
- 复制renren-fast项目utils包下的类Query、PageUtils、R、Constant到common项目的java/com.dh.gulimall.common.utils下,再接着复制xss包下的HTMLFilter和SQLFilter到common项目的java/com.dh.gulimall.common.xss下.原来的Constant文件可能会有未使用到的变量,可以点击删除。项目结构如下:
修改逆向工程的Controller模板
因为原先生成的增删改查代码有些暂时用不到的代码以及引用指定的位置出错,所以我们需要重新生成:
- 暂时注释掉@RequiresPermissions(“ m o d u l e N a m e : {moduleName}: moduleName:{pathName}:update”)和删除掉对注解的引用。
import org.apache.shiro.authz.annotation.RequiresPermissions;
- 这里我们来看它生成增删改查代码的模板定义是怎样的:这里截取Controller.vim下的一段展示
import ${package}.${moduleName}.entity.${className}Entity;
import ${package}.${moduleName}.service.${className}Service;
import ${mainPath}.common.utils.PageUtils;
import ${mainPath}.common.utils.R;
/**
* ${comments}
*
* @author ${author}
* @email ${email}
* @date ${datetime}
*/
@RestController
@RequestMapping("${moduleName}/${pathName}")
public class ${className}Controller {
可以看到我们之前在配置文件generator.properties写下的代码作用原来是这样的。
重新配置generator.properties,这里重新生成模块product的代码:
# 主目录
mainPath=com.dh.gulimall
#包名
package=com.dh.gulimall
#模块名
moduleName=product
#作者
author=hh
#email
email=xxx@qq.com
#表前缀(类名不会包含表前缀) # 我们的pms数据库中的表的前缀都pms
# 如果写了表前缀,每一张表对于的javaBean就不会添加前缀了
tablePrefix=pms_
下载后请务必确认生成的代码的正确性。
P18 快速开发-配置&测试微服务基本CRUD功能
18.1 product模块
整合mybatis-plus
- 导入依赖
<!-- mybatisPLUS-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
- 配置mybatis-plus,快速配置可以访问mybatis-plus官网
# 配置数据源:在common模块下导入mysql驱动,这里mysql的版本用的是8.0
<!-- mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
# 在application.yml配置数据源相关信息
spring:
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/gulimall-pms
driver-class-name: com.mysql.cj.jdbc.Driver
- 配置mybatis-plus
# 使用@MapperScan
# 告诉mybatis-plus sql的映射文件
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
- 然后在主启动类上加上注解@MapperScan(“com.dh.gulimall.product.dao”)
@MapperScan("com.dh.gulimall.product.dao")
@SpringBootApplication
public class GulimallProductApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallProductApplication.class, args);
}
}
- 在测试类中测试方法:
@Autowired
BrandService brandService;
@Test
void contextLoads() {
BrandEntity brandEntity = new BrandEntity();
brandEntity.setDescript("wqwqwq");
brandEntity.setName("华为wqwwqwqwq");
brandService.save(brandEntity);
System.out.println("保存成功");
}
18.2 coupon模块
- 逆向工程生成coupon的增删改查代码;
- 添加配置文件application.yml
# 端口号
server:
port: 7000
# 配置数据源
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 136818
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: gulimall-coupon
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
logic-delete-value: 1
logic-not-delete-value: 0
- 添加请求测试是否能正常接收到请求:http://localhost:7000/coupon/coupon/list
18.3 member模块
- 逆向工程生成coupon的增删改查代码;
- 添加配置文件application.yml
spring:
datasource:
username: root
password: 136818
url: jdbc:mysql://127.0.0.1:3306/gulimall_ums?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
application:
name: gulimall-member
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
logic-delete-value: 1
logic-not-delete-value: 0
server:
port: 8000
8. 微服务注册中心
8.1修改原有的父项目和子项目的管理关系;
- 在父项目下管理所有的子项目依赖:
9.使用openfeign
9.1 在coupon模块引入open-feign依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
注意
使用openfeign还要加上loadbalance(负载均衡)的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
9.2 编写一个接口,告诉SpringCloud这个接口需要调用远程服务。
- 修改coupon模块controller下的CouponController,添加一下controller方法。
@RequestMapping("/member/list")
public R memberCoupons(){
CouponEntity couponEntity = new CouponEntity();
couponEntity.setCouponName("discount 20%");
return R.ok().put("coupons",Arrays.asList(couponEntity));
}
9.3 在member模块下新建feign文件夹,新建CouponFeignService接口。
@FeignClient("gulimall_coupon")
public interface CouponFeignService {
@RequestMapping("/coupon/coupon/member/list")
public R memberCoupons();
}
9.4 修改启动类GulimallMemberApplication,添加注解@EnableFeignClients
/**
* 添加Gulimall成员启动类.
*/
@MapperScan("com.dh.gulimall.member.dao")
@EnableFeignClients(basePackages = "com.dh.gulimall.member.feign")
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallMemberApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallMemberApplication.class, args);
}
}
声明接口的每一个方法都是调用哪个远程服务的哪个请求。
9.5 开启远程调用功能:在member模块下新建请求test,调用coupon模块的请求。
/**
* 远程调用.
* @return
*/
@RequestMapping("/coupons")
public R test() {
MemberEntity memberEntity = new MemberEntity();
memberEntity.setNickname("zhangsan");
R memberCoupons = couponFeignService.memberCoupons();
return memberCoupons.put("member",memberEntity).put("coupons", memberCoupons.get("coupons"));
}
9.6 访问http://localhost:9000/member/member/coupons。加上断点,看后端能否正常接收到请求。(我觉得写得很烂,不是一件坏事,这事是我第一次做,烂是正常的,我觉得烂是因为我想变得更好,我有上进心;再说它在别人的眼里不一定很烂;烂也是我成长,是我为梦想行动的证明,这比别人那发光的笔记还要珍贵)
停止gulimall-coupon服务,再次访问请求http://localhost:9000/member/member/coupons可以看到:
重新启动gulimall-coupon服务,访问请求:http://localhost:9000/member/member/coupons。
可以看到重新启动gulimall-coupon服务后,恢复了正常。
10. 配置中心
10.1 修改“gulimall-coupon”模块
- 添加pom依赖:因为指定过alibaba-nacos的版本,这里config的版本会与其保持一致。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
- 创建bootstrap.properties文件,该配置文件会优先于“application.yml”加载。
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
10.2 传统方式
- 为了详细说明config的使用方法,来看下原始的方式,创建application.properties的配置文件,添加如下的配置内容:
coupon.user.name="zhangsan"
coupon.user.age=30
- 修改coupon模块下的CouponController文件,添加如下内容:
@Value("${coupon.user.name}")
private String name;
@Value("${coupon.user.age}")
private Integer age;
@RequestMapping("/test")
public R getConfigInfo(){
return R.ok().put("name",name).put("age",age);
}
- 启动gulimall-coupon服务,访问:http://localhost:7000/coupon/coupon/test
传统方式存在的一个问题,如果频繁的修改application.properties,在需要频繁重新打包部署。下面我们将采用Nacos的配置中心来解决这个问题。
10.3 nacos config
- 在Nacos注册中心中,点击“配置列表”,添加配置规则。
新建配置页面配置如下信息。
DataID:gulimall-coupon
配置格式:properties
文件的命名规则为:
spring.application.name−{spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
${spring.application.name}:为微服务名
${spring.profiles.active}:指明是哪种环境下的配置,如dev、test或info
${spring.cloud.nacos.config.file-extension}:配置文件的扩展名,可以为properties、yml等
所以按照规则我们应该起名为gulimall.dev.properties
- 查看配置
- 修改coupon模块下的CouponController类,添加@RefreshScope注解
@RefreshScope
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
- 启动成功后可以看到。
- 访问:http://localhost:7000/coupon/coupon/test
10.4 Nacos支持三种配置加载方案
Nacos支持“Namespace + group + data ID”的配置解决方案。
Namespace方案:通过命名空间实现环境区分
下面是配置实例:
- 1、创建命名空间:分别为dev(开发),test(测试)和prop(正式)
- 2、回到配置列表,可以看到我们创建的三个命名空间
- 3、在dev命名空间下,创建“gulimall-coupon.properties”配置规则
dev下我们提供的值是:
coupon.user.name="zhangsan"
coupon.user.age=30
- 4、 访问:http://localhost:7000/coupon/coupon/test
结果依然是public下的配置信息,并没有使用我们在dev命名空间下配置的规则,而是使用public命名空间下的配置规则。 - 5、指定命名空间
如果想要使得我们自定义的命名空间生效,需要在“bootstrap.properties”文件中,指定使用哪个命名空间:
spring.cloud.nacos.config.namespace=4a7f8d0e-4322-46f8-9b36-007a468e9758
这个命名空间ID来源于我们在第一步所创建的命名空间。重新启动服务后,访问:http://localhost:7000/coupon/coupon/test;可以看到是我们在dev命名空间下的规则。
10.5 同时加载多个配置集
微服务数量很大时,所有的配置都书写到一个配置文件中,显然不是很合适。对此我们可以将配置按照功能的不同,拆分成不同的配置文件。
- 将数据源有关的配置写到一个配置文件里
- 将框架有关的配置写到一个配置文件里
实例:将“gulimall-coupon”的“application.yml”文件拆分成多个配置,并放置到nacos配置中心。
1、创建datasource.yml,用于存储和数据源有关的配置,
在coupon命名空间下,创建datasource.yml配置
多个配置集的加载总是失败;
11. 网关
11.1 创建gulimall-gateway模块,添加gulimall-common和gateway依赖到该模块下的pom文件里。
- 创建gulimall-gateway模块。
- 在父项目的pom文件里添加对网关的版本号依赖管理。
<gateway.version>3.0.7</gateway.version>
<!-- SpringCloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>${gateway.version}</version>
</dependency>
- 在gateway模块下的pom文件里添加gulimall-common,gateway的依赖。
<dependencies>
<!-- gulimall-common -->
<dependency>
<groupId>com.dh</groupId>
<artifactId>gulimall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- SpringCloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>${gateway.version}</version>
</dependency>
</dependencies>
别导错了。
11.2 GulimallGatewayApplication类上加上“@EnableDiscoveryClient”注解
/**
* 网关的启动类.
*/
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallGatewayApplication.class, args);
}
}
11.3 在Nacos中创建“gateway”命名空间,同时在该命名空间中创建“gulimall-gateway.yml”
11.4 创建“bootstrap.yml”文件,添加如下配置,指明配置中心地址和所属命名空间
spring:
application:
name: gulimall-gateway
cloud:
nacos:
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 所属命名空间
namespace: 036dda71-93f2-4e5c-bfe6-45cca28e07cb
11.5 创建“application.yml”文件,指定服务名和注册中心地址
spring:
application:
name: gulimall-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
server:
port: 88
11.6 启动“gulimall-gateway”
- 启动报错
- 解决方法:在启动类上添加排除和数据源相关的配置
@EnableDiscoveryClient
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class GulimallGatewayApplication {
- 重新启动,可以看到该服务已经注册到nacos里了;
- 实例:实现针对于“http://localhost:88/hello?url=baidu”,转发到“https://www.baidu.com”,针对于“http://localhost:88/hello?url=qq”的请求,转发到“https://www.qq.com/”
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
启动“gulimall-gateway”,测试:
访问:http://localhost:88/?url=baidu;
![在这里插入图片描述](https://img-blog.csdnimg.cn/147f2dca4f0a438382997aec01f40d3b.png
访问:http://localhost:88/?url=qq
![在这里插入图片描述](https://img-blog.csdnimg.cn/b4f3fe3e61bd47a6a5c2813bd836f0d7.png