大家好啊,明天就是国庆节了,今天再发一篇博客。
其实本篇博客,是连接上一篇博客来的。
手把手搭建springCloud框架(二)——eureka客户端+swagger+mybatisPlus: juejin.im/post/5d8e07…
因此,本篇博文,是从上一篇博文创建的项目发展而来,请先搭建上一篇博文所有的项目后,再来搭建本项目。
因此,需要注意的是以下内容,我将一一贴出来,给到大家。
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.blog</groupId> <artifactId>permission-service</artifactId> <version>0.0.1-permissionService-SNAPSHOT</version> <packaging>jar</packaging> <name>permission-service</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--引入mybatis依赖--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.2.0</version> </dependency> <!--引入mybatisPlus依赖--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatisplus-spring-boot-starter</artifactId> <version>1.0.5</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>2.1.8</version> </dependency> <!-- 模板引擎 代码生成 --> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> </dependency> <!-- mysql驱动器依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <!--springboot的web依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--Herbnate实体依赖--> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0.2</version> </dependency> <!--常用基础Jar包,构建自己的thrift连接池--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!-- 引入Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <!--spring默认使用yml中的配置,但有时候要用传统的xml或properties配置--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <!-- 解析json数据的依赖--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.1.41</version> </dependency> <!-- jwt认证协议依赖,token授权依赖 --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency> <!--这是权限认证依赖,这个需要屏蔽,不然使用eureka到swagger会需要登录--> <!--<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>--> <!-- 这三个依赖,是为了序列化对象转换为json --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> </dependency> <!--********************************************************************************--> <!--springCloud启动依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> </dependency> <!--srpingCloud的eureka服务注册依赖,client端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.0.0.RELEASE</version> </dependency> <!--srpingCloud的eureka服务注册依赖,server端,是因为本服务既要充当生产者,又要充当消费者--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>2.0.0.RELEASE</version> </dependency> <!--springCloud的fiegn依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> <!--springCloud的ribbon依赖--> <dependency> <groupId>com.netflix.ribbon</groupId> <artifactId>ribbon</artifactId> <version>2.2.2</version> </dependency> <!--histrix依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> <!--Hystrix 的一个类库--> <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-javanica</artifactId> </dependency> <!--新增依赖,swaggerUI--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version> </dependency> </dependencies> <!-- 引入spring cloud的依赖,不能少,主要用来管理Spring Cloud生态各组件的版本 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <resources> <resource> <!--需要打包的目录--> <directory>src/main/resources</directory> <!--目录中的文件类型--> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> <finalName>permission</finalName> </build> </project> 复制代码
#服务名 spring.application.name=permission #端口 server.port=3333 ################################################################################################################ #数据库信息 spring.datasource.url: jdbc:mysql://localhost:3306/myblog?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username: root spring.datasource.password: 123456 spring.datasource.driver-class-name: com.mysql.jdbc.Driver ################################################################################################################# spring.jmx.default-domain=${spring.application.name} spring.jpa.open-in-view=false # springframework.web日志以DEBUG级别输出 logging.level.org.springframework.web=info ############################################################################################################### # 如果是放在src/main/java目录下 classpath:/com/blog/*/mapper/*Mapper.xml # 如果是放在resource目录 classpath:/mapper/*Mapper.xml mybatis-plus.mapper-locations=classpath:/mapper/*Mapper.xml #实体扫描,多个package用逗号或者分号分隔 mybatis-plus.type-aliases-package=com.blog.*.entity #驼峰下划线转换 mybatis-plus.global-config.db-column-underline=true #刷新mapper 调试神器 mybatis-plus.global-config.refresh-mapper=false #数据库大写下划线转换 mybatis-plus.global-config.capital-mode=true ################################################################################################################# #配置Swagger相关信息(从eureka跳到swagger页面) eureka.instance.prefer-ip-address=true eureka.instance.hostname=:${spring.cloud.client.ipAddress} eureka.instance.status-page-url:http://${spring.cloud.client.ipAddress}:${server.port}/swagger-ui.html #################################################################################################################### #eureka注册中心路径 eureka.client.service-url.defaultZone=http://localhost:1111/eureka/ #表示本服务发送给eureka服务端的心跳时间,设置时间不能太长,不然会导致eureka检测不到服务从而会驱逐服务下线 eureka.instance.leaseRenewalIntervalInSeconds: 2 #当本服务掉线后,eureka服务端取掉本服务的缓存的时间 eureka.instance.leaseExpirationDurationInSeconds: 4 #注册到eureka上的服务的名字 eureka.instance.instance-id=http://${spring.cloud.client.ipAddress}:${server.port}/${spring.application.name} ####################################################################################################################### #逻辑删除配置(下面3个配置),不是真实删除数据,只是逻辑删除数据 mybatis-plus.global-config.logic-delete-value=1 mybatis-plus.global-config.logic-not-delete-value=0 mybatis-plus.global-config.sql-injector=com.baomidou.mybatisplus.mapper.LogicSqlInjector ############################################################################################################## mybatis-plus.global-config.meta-object-handler=com.blog.permission.mabatisPlus.MyMetaObjectHandler mybatis-plus.configuration.map-underscore-to-camel-case=true mybatis-plus.configuration.cache-enabled=false mybatis-plus.configuration.jdbc-type-for-null=null mybatis-plus.typeAliasesPackage=com.blog.permission.entity mybatis-plus.global-config.id-type=3 mybatis-plus.global-config.field-strategy=2 mybatis-plus.global-config.key-generator=com.baomidou.mybatisplus.incrementer.OracleKeyGenerator ############################################################################################################## #默认的超时时间设置 hystrix.metrics.polling-interval-ms=60000 #启动Hystrix hystrix.metrics.enabled=true ############################################################################################################## #将日志放到项目里面的logs文件夹的permission.log文件中 logging.file=logs/permission.log ############################################################################################################## 复制代码
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.SpringCloudApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import springfox.documentation.swagger2.annotations.EnableSwagger2; @EnableFeignClients //feign注解 @ComponentScan(basePackages = "com.blog.permission") @EnableAsync //支持多线程 @EnableSwagger2 //swagger注解 @EnableWebMvc //配合WebMvcConfig配置文件,目的是为了使用webMVC @SpringBootApplication @EnableEurekaClient //注册到eureka上的注解 @EnableCircuitBreaker //Hystrix熔断机制的注解 public class PermissionApplication { public static void main(String[] args) { SpringApplication.run(PermissionApplication.class, args);; } } 复制代码
接下来,是要添加一个测试Feign和Hystrix的接口:
代码:
@ApiOperation(value = "测试feign的接口") @PostMapping("/testForFeign") public Result testForFeign(@ApiParam(value = "用户id")@RequestParam(required = false) String userId){ return userService.testForFeign(userId); } 复制代码
@Override public Result testForFeign(String userId) { Result result=perimissionFallback.get(userId); return result; } 复制代码
import com.blog.permission.feign.PermissionClient; import com.blog.permission.method.Result; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service public class PerimissionFallback { @Resource private PermissionClient permissionClient; private static final Logger logger = LoggerFactory.getLogger(PerimissionFallback.class); @HystrixCommand(fallbackMethod = "getFallBack") public Result get(String userId) { Result result=permissionClient.get(userId); return result; } public Result getFallBack(String userId) { logger.info("调用接口:permission/login/get 失败,降级处理"); return new Result().fallBack("permission/login/get",userId); } } 复制代码
代码里面的注解:@HystrixCommand(fallbackMethod = "getFallBack"),这个就是引入了Hystrix的方法降级,降级的方法就是getFallBack这个方法,图片中我用红色箭头标出来了,很容易理解。
import com.blog.permission.method.Result; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.*; @Component @FeignClient(value = "permission") public interface PermissionClient { //这是跨服务调用permission服务的“permission/login/get”接口 @RequestMapping(value = "/login/get", method = RequestMethod.GET) public Result get(@RequestParam("userId") String userId); } 复制代码
可以看一下,这个跨服务想要调用的方法是这样的:
对比一下上面的代码,会发现有什么不同的地方呢?
好的,现在可以开始启动服务了。
表示服务已经启动成功,打开网页,输入网址:localhost:1111,如果不知道这个网址是怎么了,请查看我之前的一篇系列博文:
手把手搭建springCloud框架(一)——eureka的服务端(server)的搭建: juejin.im/post/5d8dd6…
点击: http://192.168.2.92:3333/permission ,进入到swagger页面。
调用接口,开始测试:
可以看到,我测试Feign跨服务是成功了的,当然,我这次测试是自己跨服务调用自己,当然会有问题,不过这里暂且不提。
接下来,我们开始测试Hystrix的熔断机制。 在接口:login/get里的service层打断点
然后再在swagger上调用接口,我们发现,当打上断点到一点的时间点(其实就是我们设置的Hystrix的熔断时间,仔细看一下我们的配置文件,application.properties),然后再去掉断点,让程序运行,那么调用接口就会失败,返回的内容也是我们自己定义的返回内容:
这个返回内容,不就是我们自己定义的fallBack方法吗?
讲到这里,我们已经将Feign和Hystrix讲了,那么Ribbon在哪里呢?当你开始使用Feign的时候,只要你的依赖里面有Ribbon,那么springCloud会默认使用Ribbon来进行分发Feign的请求,所以我们无须关心这一点。