docker的使用,renrenfast自动生成代码,spring nacos的使用,spring cloud gateway的使用,跨域的解决办法
概述:最近大致看完了springcloud的基础,就找了个大项目来动手顺便也驱动后续的学习方向,在这总结下项目用到的还不够熟练的知识和工具。
文章目录
- 1.docker的介绍及使用
- 2.商品三级分类-递归树形结构数据获取
- 3.renren开源项目帮助快速搭建后台管理系统
- 4.Spring cloud alibaba nacos
- 5.Spring cloud Gateway
- 6.跨域请求的解决办法
1.docker的介绍及使用
为什么要使用docker?
之前部署模仿的天猫的到阿里云的时候,必须做如下工作:
- 安装 FTP 服务器,配置它,配置FTP用户
- 安装JAVA环境
- 安装数据库,配置数据库
- 安装TOMCAT
- 开放FTP和TOMCAT端口
- 上传 模仿的天猫
- 配置 TOMCAT
- 上传 模仿天猫的 SQL语句
- 导入这个 SQL 语句
- 启动TOMCAT
原因就是你没有运行模仿天猫的环境,搭建环境时间久,还容易出错,一错心态就容易受影响。每次如果都这么去部署的话会很麻烦。使用docker后就不会这么麻烦了,它可以一次构建,到处运行,因为在Docker里装了个小的操作系统 Linux,它相当于能创造出那个运行的环境,然后直接丢给阿里云服务器就可以了。
docker概念简单介绍
镜像,就是持久化后的,安装了各种工具,软件和服务的一个Linux 操作系统,镜像就相当于还没激活的容器。
仓库: 做好的现成的镜像,都放在仓库里
容器: 容器就是跑起来的镜像,就是一个完整的工作环境
例子讲解
docker run -dit --privileged -p21:21 -p80:80 -p8080:8080 -p30000-30010:30000-30010 --name how2jtmall how2j/tmall:latest /usr/sbin/init
docker run 表示运行一个镜像
-dit 是 -d -i -t 的缩写。 -d ,表示 detach,即在后台运行。 -i 表示提供交互接口,这样才可以通过 docker 和 跑起来的操作系统交互。 -t 表示提供一个 tty (伪终端),与 -i 配合就可以通过 ssh 工具连接到 这个容器里面去了
–privileged 启动容器的时候,把权限带进去。 这样才可以在容器里进行完整的操作
-p21:21 第一个21,表示在CentOS 上开放21端口。 第二个21 表示在容器里开放21端口。 这样当访问CentOS 的21端口的时候,就会间接地访问到容器里了
-p80:80 和 21一个道理
-p8080:8080 和21 一个道理,在本例里,访问的地址是 http://192.168.84.128:8080/tmall/, 这个 192.168.84.128 是CentOS 的ip地址,8080是 CentOS 的端口,但是通过-p8080:8080 这么一映射,就访问到容器里的8080端口上的 tomcat了
-p30000-30010 和21也是一个道理,这个是ftp用来传输数据的
–name how2jtmall 给容器取了个名字,叫做 how2jtmall,方便后续管理
how2j/tmall:latest how2j/tmall就是镜像的名称, latest是版本号,即最新版本
/usr/sbin/init: 表示启动后运行的程序,即通过这个命令做初始化
安装docker
1.更新 yum 在虚拟机的Linux中输入yum -y update
2.安装 Docker 同上输入yum install docker -y
每次开机启动Docker后才能使用 输入systemctl start docker
以下是docker 的生命周期管理常用命令:
systemctl stop docker.service
systemctl start docker.service
systemctl restart docker.service
systemctl status docker.service
配置阿里云镜像加速
从官网下载镜像很慢,所以配置阿里云,登录阿里云,进入控制台,进入产品与服务里面的容器镜像服务,再点击镜像加速器,点击CentOs,然后在虚拟机的Linux里面执行这些代码。
安装常用工具
输入yum install iproute ftp bind-utils net-tools wget -y
其中:
iproute 用来执行 ip address 查看本机地址
ftp 用来测试ftp 服务器
bind_utils 用来运行 nslookup
net-tools 用来执行 netstate
这些工具在检验某个服务是否正常工作的时候,会起到很好的作用。
2.商品三级分类-递归树形结构数据获取
@RequestMapping("/list/tree") public R list(){ List<CategoryEntity> entities = categoryService.listWithTree(); return R.ok().put("data", entities); #R继承的Hashmap }
@JsonInclude(JsonInclude.Include.NON_EMPTY) @TableField(exist=false) private List<CategoryEntity> children; #CategoryEntity新加的属性即子分类
@Override public List<CategoryEntity> listWithTree() { #1、查出所有分类 List<CategoryEntity> entities = baseMapper.selectList(null); #2、组装成父子的树形结构 #2.1)、找到所有的一级分类 List<CategoryEntity> level1Menus = entities.stream().filter(categoryEntity -> categoryEntity.getParentCid() == 0 #数据库中category表有Parentid,如果它是零那么就相当于他没有父分类,它就是一级分类 ).map((menu)->{ #2.2一级分类调用方法去找它的子分类 menu.setChildren(getChildrens(menu,entities)); return menu; #.map处理后又进行sort处理再收集为集合后再返回 }).sorted((menu1,menu2)->{ #排序 return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort()); }).collect(Collectors.toList()); return level1Menus; } #递归查找所有分类的子分类 private List<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all){ List<CategoryEntity> children = all.stream().filter(categoryEntity -> { return categoryEntity.getParentCid() == root.getCatId(); }).map(categoryEntity -> { #1、又继续找子菜单 categoryEntity.setChildren(getChildrens(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; }
jdk8新特性stream语法讲解:
1.(.filter)就是过滤元素,括号后面就是过滤的条件,如果过滤的条件不满足,那么就过滤掉这个元素。
2.(.map)就是对刚才过滤的元素进行处理,这里就是找它们的子分类然后赋值。
3.(.sort)就是对刚才过滤的元素进行排序。
4.(.collect)就是对刚才经过所有处理后的元素收集成某种集合,这里是收集成List集合
效果:
3.renren开源项目帮助快速搭建后台管理系统
https://gitee.com/renrenio/renren-generator
先通过git把开源项目clone下来,然后把clone下来的项目添加到复制加入到微服务项目中。
最下面的renren-generator就是clone的项目。然后再gulimall这个项目的pom.xml文件中把renren-generator引入模块,
接下来打开renren-generator里的src-main-resources的application.yml文件,修改url,username(就是你的数据库账号),password(你的数据库密码)。
url就把它的默认ip地址修改成你的mysql的ip地址还有就是第三根/到?之间修改为你想为哪个数据库生成CRUD代码。
接下来打开generator.properties修改mainPath,package,moudleName,author,email,tablePrefix.举个例子我的是这样:
最后生成的代码的结构就是main-java-(com-atguigu-gulimall)(这就是package)-ware(这就是moduleName),tablePrefix是数据库中的表的前缀名,接下来验证是否正确,启动reren-generator的application,然后点击
选择所有表点击生成代码,下载后生成的代码解压后
与预想的路径完全一样,接下来把main文件夹ctrl+c再在idea里面找到对应的微服务ctrl+v,还有些导入的问题,有些不存在的工具类。有些类是在pom文件引入依赖就可以解决的例如引入mabatis plus,就可以解决一些关于mabatis plus相关的类的问题,还有些是工具类,按照下面的方法解决。
https://gitee.com/renrenio/renren-fast?_from=gitee_search
同上一样的方法clone下来,新建一个微服务gulimall-common,看看刚才生成的代码需要哪些类还不存在的,然后就去clone下来的项目里面找,再复制给gulimall-common这个微服务就可以了。这个微服务的作用就是提供工具类等等给其他微服务,如果很多微服务都要用到的东西就在它这添加就可以了,然后让其它微服务依赖它就可以使用需要的东西了。剩下应该就是一些jdk版本的语法小问题了,大家应该就都能解决了
4.Spring cloud alibaba nacos
naco能作为微服务的注册中心和配置中心
官方文档:https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
注册中心
1.首先,在gulimall-common的pom.xml中引入nacos,因为每个微服务都依赖gulimall-common,所以这就相当于每个微服务都引入了nacos.
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
2.下载nacos服务器,地址:https://github.com/alibaba/nacos/releases下载解压后,进入nacos-bin后点击startup.cmd,这样nacos服务器就启动了。
3.在微服务中的application.yml文件中配置nacos和服务名称
4.在微服务的application中加上注解@EnableDiscoveryClient
5.启动微服务的application并在localhost:8848/nacos/#/login后的界面的服务列表观察是否启动(登录的账号和密码都为nacos)
测试成功
使用feign进行远程调用
feign是http客户端,它进行远程调用就相当于发送http请求
1.在微服务中引入openfeign的依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.1.0.RELEASE</version> </dependency>
2.编写一个接口,告诉SpringCloud这个接口需要调用远程服务。
package com.atguigu.gulimall.member.feign; import com.atguigu.common.utils.R; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; /** * 这是一个声明式的远程调用 */ @FeignClient("gulimall-coupon") public interface CouponFeignService { @RequestMapping("/coupon/coupon/member/list") public R membercoupons(); }
第一个注解的参数就是要调用的服务的名称,第二个注解的参数就是你要远程调用的服务的方法的RequestMapping.综合意思就是调用这个接口的方法就是去调用对应的其它的微服务的方法
3.在微服务的Application加入注解@EnableFeignClients(basePackages = “com.atguigu.gulimall.member.feign”)注解的参数是去扫描你的所有远程调用的类所在的包。
配置中心
如果是在编译器配置的话,如果想修改配置的话,那么又只能重新启动,比较麻烦,在配置中心中进行修改就不会有这种问题。
基本概念:
命名空间:默认使用public。创建不同的命名空间进行环境隔离(例如:生产环境,测试环境)或者微服务配置隔离。
配置集ID:配置文件名。
配置分组:默认分组DEFAULT_GROUP。
综合使用:每个微服务创建独立的命名空间,然后又用配置分组来进行环境隔离。
使用步骤
1.导入依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
2.在配置中心创建该微服务的命名空间和数据集(Date id)名字为微服务名称.properties,在resources文件夹创建bootstrap.properties文件,里面写上application-name和配置中心的地址和微服务在nacos配置中的命名空间
(注:bootstrap.properties比其他配置文件优先级更高,它会先被加载)
spring.application.name=gulimall-coupon spring.cloud.nacos.config.server-addr=127.0.0.1:8848 spring.cloud.nacos.config.namespace=8a7b3db7-275c-4a44-b160-c82134113d70 spring.cloud.nacos.config.group=prod #下面是同时加载多个配置集 #微服务任何配置信息,任何配置文件都可以放在配置中心中 #只需要在bootstrap.preperties说明加载配置中心中的哪些配置文件就可以了 spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml spring.cloud.nacos.config.ext-config[0].group=dev spring.cloud.nacos.config.ext-config[0].refresh=true spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml spring.cloud.nacos.config.ext-config[1].group=dev spring.cloud.nacos.config.ext-config[1].refresh=true spring.cloud.nacos.config.ext-config[2].data-id=other.yml spring.cloud.nacos.config.ext-config[2].group=dev spring.cloud.nacos.config.ext-config[2].refresh=true
3.在Application中加入@RefreshScope,在需要的地方使用@Value注解来动态获取值(会优先获取配置中心的值)
5.Spring cloud Gateway
官方文档:https://spring.io/projects/spring-cloud-gateway
例子1讲解:
spring: cloud: gateway: routes: # - id: test_route # uri: https://www.baidu.com # predicates: # - Query=url,baidu # # - id: qq_route # uri: https://www.qq.com # predicates: # - Query=url,qq
id意思是这个路由规则的名字
uri意思是派发到这个网站去(还会加上你http请求的?的前面的内容如果有?的话)
predicates是断言,请求发来后会先通过predicates来判断是否符合断言的规则,如果符合则跳转到uri那个网站去,否则交给下一个路由规则处理如果有的话
(断言使用规则看官方文档)
例子2讲解:
spring: cloud: gateway: routes: - id: product_route uri: lb://gulimall-product #lb的意思是负载均衡,lb后面只需要写服务名 predicates: - Path=/api/product/** #如果不要下面的话,默认的重写效果就是,比如发送的localhost:任意端口号/api/product/**就会转给 #gulimall-product的Ip地址:gulimall-product这个服务的端口号/api/product/** #如果这样的转给不符合自己想要的,那么就可以自定义重写 filters: - RewritePath=/api/(?<segment>.*),/$\{segment} #重写规则参照官方文档
使用步骤
1.网关也需要注册到注册中心中去。所以也需要引入nacos-discovery依赖。
<!-- 服务注册/发现--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- 配置中心来做配置管理--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
这个项目中引入依赖common就可以了。
2.在Application中加入@EnableDiscoveryClient并排除与数据源有关的配置,因为common中有mabatis相关的依赖。
@EnableDiscoveryClient @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) public class GulimallGatewayApplication { public static void main(String[] args) { SpringApplication.run(GulimallGatewayApplication.class, args); } }
3.在application.properties中配置nacos的注册中心地址和网关的服务名称以及网关的端口号,在bootstrap.properties中配置nacos配置中心的地址和网关的服务名称和配置中心的命名空间。
4.在application.yml中编写路由规则。
6.跨域请求的解决办法
跨域:指的是浏览器不能执行其它网站的脚本,它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。(同源策略是指协议,域名,端口都要相同,其中有一个不同都会产生跨域)
浏览器为了安全会默认拒绝跨域请求
参考文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
非简单请求会先发送预检请求,option是探路兵,服务器会给option回答这次能否跨域。
解决方法
1.使用nginx部署为同一个域
2.使用配置来解决,
在网关微服务下建一个包建一个类
package com.atguigu.gulimall.gateway.config; 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; @Configuration #@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。 public class GulimallCorsConfiguration { @Bean#加入到容器中 public CorsWebFilter corsWebFilter(){ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); #1、配置跨域 corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.setAllowCredentials(true);#允许cookie一起跨域 source.registerCorsConfiguration("/**",corsConfiguration); return new CorsWebFilter(source); } }
- SpringBoot学习-如何使用mybatis-generator-maven-plugin自动生成代码
- 通过反射调用的类中使用Spring@Autowired自动装配的成员为空的解决办法不依赖servlet context获取Spring Application Contexts
- SpringBoot系列: 使用MyBatis maven插件自动生成java代码
- springcloud config中使用@value(name)报注入错误的解决办法
- VC6.0下不能自动完成类方法和属性的解决办法(vc6无法使用代码自动完成)
- springboot使用-Mybatis-Plus 的自动生成代码功能
- FastSpring学习笔记二(使用工具MyGeneration生成Model和NHibernate的代码 )
- 使用Eclipse的Generator MyBatis/iBatis Artifacts插件自动生成代码,与spring集成
- [置顶]springmvc+mybatis,在mybatis逆向工程的基础上使用模板自动生成controller层代码
- springboot 整合 MyBatis 使用generator自动生成代码
- Mybatis 优缺点,配置,使用,结合Spring使用,常见错误,代码自动生成(草稿)
- 使用IDEA springboot 如何通过mybatis-generator自动生成代码
- FastSpring学习笔记二(使用工具MyGeneration生成Model和NHibernate的代码 )
- 使用IntelliJ IDEA自动生成Spring Boot代码 根据数据库自动生成Entity、DynamicSql、Dao、Service、Controller各层代码及swagger注解
- 使用Eclipse的Generator MyBatis/iBatis Artifacts插件自动生成代码,与spring集成
- 在Spring Boot中使用MyBatis并且自动生成代码
- 使用Ibatis生成的代码日期中没有时分秒的问题原因和解决办法
- 使用SudzC生成ARC版Obj-C代码出现返回结果为nil的疑问与暂时解决办法
- springcloud项目网关升级:gateway替代zuul以及解决gateway跨域访问问题
- ButterKnife的使用以及不能自动生成代码问题的解决