各位小伙伴今天又敲了多少Bug了,今天改Bug又花了多长时间啦,我们每天就是敲Bug,敲完改,改完敲,习惯就好啦,心态摆正。Debug起来!!!
上次是Dubbo整合,今天终结篇Cloud整合,不要废话就是干。整合图片先上,SpringCloud体系的东西,你得先知道
Eureka:注册中心,所有微服务注册到这里
Zuul:网关,所有外部请求先到这里转发给微服务
score_consumer: 微服务(消费),通过Feign远程调用提供方
score_service:微服务(提供),查TScore表(沿用之前数据库)
今天的整合,先把前面的SpringBoot+SSM整合搞定再搞会轻松些
四个微服务,我建议,先score_service,搭建好直接测一把没问题,搭建eureka,然后score_consumer然后通过score_consumer调score_service测一把,再没问题,最后,zuul弄好后,最后测一把,虽然我这么说,我其实就是一把梭!!!
首先cloud_boot_ssm的父工程pom文件
<?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.0modelVersion> <groupId>cn.wfbgroupId> <artifactId>cloud_boot_ssmartifactId> <packaging>pompackaging> <version>1.0-SNAPSHOTversion> <modules> <module>score_consumermodule> <module>score_servicemodule> <module>eurekamodule> <module>zuulmodule> modules> <parent> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-parentartifactId> <version>2.1.6.RELEASEversion> <relativePath/> parent> <properties> <project.build.sourceEncoding>UTF-8project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding> <java.version>1.8java.version> <spring-cloud.version>Greenwich.SR1spring-cloud.version> <mysql.version>5.1.47mysql.version> <pageHelper.starter.version>1.2.5pageHelper.starter.version> properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-dependenciesartifactId> <version>${spring-cloud.version}version> <type>pomtype> <scope>importscope> dependency> <dependency> <groupId>com.baomidougroupId> <artifactId>mybatis-plus-boot-starterartifactId> <version>3.1.2version> dependency> <dependency> <groupId>mysqlgroupId> <artifactId>mysql-connector-javaartifactId> <version>${mysql.version}version> dependency> dependencies> dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-maven-pluginartifactId> plugin> plugins> build>project>
然后eureka注册中心走起
pom
<?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>cloud_boot_ssmartifactId> <groupId>cn.wfbgroupId> <version>1.0-SNAPSHOTversion> parent> <modelVersion>4.0.0modelVersion> <artifactId>eurekaartifactId> <dependencies> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId> dependency> dependencies>project>
application.yml
server: port: 10086spring: application: name: eureka-service #serviceId 微服务的标识eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka #eureka 的注册地址 fetch-registry: false #单台Eureka不拉取服务 register-with-eureka: false #单台Eureka不注册自己 server: enable-self-preservation: false # 关闭自我保护模式(缺省为打开,单台注册中心关闭) eviction-interval-timer-in-ms: 60000 #清理间隔 #默认是60*1000
入口类
package cn.wfb;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@EnableEurekaServer //注册中心必带@SpringBootApplicationpublic class EurekaServer { public static void main(String[] args) { SpringApplication.run(EurekaServer.class,args); }}
其次是score_service这个微服务查数据库并返回数据用
pom
<?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>cloud_boot_ssmartifactId> <groupId>cn.wfbgroupId> <version>1.0-SNAPSHOTversion> parent> <modelVersion>4.0.0modelVersion> <artifactId>score_serviceartifactId> <dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> dependency> <dependency> <groupId>mysqlgroupId> <artifactId>mysql-connector-javaartifactId> dependency> <dependency> <groupId>com.baomidougroupId> <artifactId>mybatis-plus-boot-starterartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId> dependency> dependencies>project>
application.yml
server: port: 8081spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/tests?characterEncoding=utf-8 username: root password: root application: #定义应用名称 name: score-service# EurekaServer相关配置eureka: client: service-url: # EurekaServer地址 defaultZone: http://127.0.0.1:10086/eureka instance: ip-address: 127.0.0.1 # ip地址 prefer-ip-address: true # 更倾向于使用ip,而不是host名 instance-id: ${eureka.instance.ip-address}:${server.port} # 自定义实例的id
入口类
package cn.wfb;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplication@EnableEurekaClient //指定是eurekaClient客户端@MapperScan("cn.wfb.dao") //MyBatisPlus扫描接口指定包名public class ServiceApplication { public static void main(String[] args) { SpringApplication.run(ServiceApplication.class,args); }}
controller
package cn.wfb.web;import cn.wfb.pojo.TScore;import cn.wfb.service.ScoreService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import java.util.List;@RequestMapping("/score")@RestControllerpublic class ScoreController { @Autowired private ScoreService scoreService; @GetMapping public ResponseEntity> findAll() { List scores = scoreService.findAll(); return ResponseEntity.ok(scores); } @PostMapping public void Add(@RequestBody TScore score) { scoreService.Add(score); }}
service
package cn.wfb.service;import cn.wfb.dao.ScoreDao;import cn.wfb.pojo.TScore;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;@Servicepublic class ScoreService { @Autowired private ScoreDao scoreDao; public ListfindAll() { return scoreDao.selectList(null); } public void Add(TScore score) { scoreDao.insert(score); }}
dao
package cn.wfb.dao;import cn.wfb.pojo.TScore;import com.baomidou.mybatisplus.core.mapper.BaseMapper;public interface ScoreDao extends BaseMapper<TScore> {}
pojo
package cn.wfb.pojo;import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;import java.io.Serializable;@TableName("t_score")public class TScore implements Serializable { @TableId(type = IdType.AUTO) private Integer id; private String name; private String subject; private Double fraction; private static final long serialVersionUID = 1L; //我省略了getter/setter方法,节约点篇幅。你别忘写!!!}
score_consumer微服务
pom
<?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>cloud_boot_ssmartifactId> <groupId>cn.wfbgroupId> <version>1.0-SNAPSHOTversion> parent> <modelVersion>4.0.0modelVersion> <artifactId>score_consumerartifactId> <dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-hystrixartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-openfeignartifactId> dependency> dependencies>project>
application.yml
server: port: 8091spring: application: #定义应用名称 name: score-consumereureka: client: service-url: # EurekaServer地址 defaultZone: http://127.0.0.1:10086/eureka instance: ip-address: 127.0.0.1 # ip地址 prefer-ip-address: true # 更倾向于使用ip,而不是host名 instance-id: ${eureka.instance.ip-address}:${server.port} # 自定义实例的idfeign: hystrix: enabled: true # 开启Feign的熔断功能#设置负载均衡的一些参数ribbon: ReadTimeout: 2000 # 读取超时时长,注意提供方的睡眠时间如果是2s肯定会超时,因为服务发请求建立链接也需要时长 ConnectTimeout: 1000 # 建立链接的超时时长 MaxAutoRetries: 0 #每台服务器最多重试次数,但是首次调用不包括在内 MaxAutoRetriesNextServer: 1 #最多重试多少台服务器 OkToRetryOnAllOperations: false # 是否对所有的请求方式都重试,如果接口有幂等可以为true#设置熔断时间hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 6000
入口类
package cn.wfb;import org.springframework.boot.SpringApplication;import org.springframework.cloud.client.SpringCloudApplication;import org.springframework.cloud.openfeign.EnableFeignClients;@SpringCloudApplication@EnableFeignClientspublic class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); }}
pojo:这里不占用篇幅将service微服务的pojo拷贝过来,去掉注解即可
FeignClient
package cn.wfb.client;import cn.wfb.pojo.TScore;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import java.util.List;@FeignClient("score-service")public interface ScoreClient { @GetMapping("/score") List findAll(); @PostMapping("/score") void Add(@RequestBody TScore score);}
ConsumerService
package cn.wfb.service;import cn.wfb.client.ScoreClient;import cn.wfb.pojo.TScore;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;@Servicepublic class ConsumerService { @Autowired private ScoreClient scoreClient; public ListfindAll() { List all = scoreClient.findAll(); return all; } public void Add(TScore score) { scoreClient.Add(score); }}
ConsumerController
package cn.wfb.web;import cn.wfb.pojo.TScore;import cn.wfb.service.ConsumerService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import java.util.List;@RestController@RequestMapping("/consumer")public class ConsumerController { @Autowired private ConsumerService consumerService; @GetMapping public ResponseEntity> findAll() { List scores = consumerService.findAll(); return ResponseEntity.ok(scores); } @PostMapping public void Add(@RequestBody TScore score) { consumerService.Add(score); }}
最后是zuul的搭建
pom
<?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>cloud_boot_ssmartifactId> <groupId>cn.wfbgroupId> <version>1.0-SNAPSHOTversion> parent> <modelVersion>4.0.0modelVersion> <artifactId>zuulartifactId> <dependencies> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-zuulartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId> dependency> dependencies>project>
application.yml
server: port: 10010 #服务端口spring: application: name: api-gateway #指定服务名#以下可以用简写的方式zuul: prefix: /api # 添加路由前缀 routes: score-consumer: /consumer/** #必须和注册的服务名称一致:冒号后是映射路径访问的时候就是这个路径eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka
入口类ZuulApplication
package cn.wfb;import org.springframework.boot.SpringApplication;import org.springframework.cloud.client.SpringCloudApplication;import org.springframework.cloud.netflix.zuul.EnableZuulProxy;@SpringCloudApplication //这个注解包括book包括eurekaclient@EnableZuulProxy //是个网关public class ZuulApplication { public static void main(String[] args) { SpringApplication.run(ZuulApplication.class,args); }}
自定义网关过滤器
package cn.wfb;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;import com.netflix.zuul.exception.ZuulException;import org.apache.commons.lang.StringUtils;import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;import org.springframework.http.HttpStatus;import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;@Componentpublic class LoginFilter extends ZuulFilter { /** * 过滤器四种类型,记不住按着Ctrl+鼠标点下面看!!! * @return */ @Override public String filterType() { return FilterConstants.PRE_TYPE;//pre->route->error->post } /** * 过滤器所在顺序,数值越小越靠前 * @return */ @Override public int filterOrder() { return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1; //过滤器从小到大执行 } /** * 放行白名单可以搞这里 * @return */ @Override public boolean shouldFilter() { return true; //是否启用该过滤器 } /** * 主要逻辑 * @return * @throws ZuulException */ @Override public Object run() throws ZuulException { // 获取请求上下文 RequestContext ctx = RequestContext.getCurrentContext(); // 获取request对象 HttpServletRequest request = ctx.getRequest(); // 获取请求参数,只要参数带个token,值随便就可以访问 String token = request.getParameter("token"); // 判断是否存在,没token就拦截掉请求,演示以下zuul可以起到过滤请求的作用 if(StringUtils.isBlank(token)){ // 不存在,未登录,拦截 ctx.setSendZuulResponse(false); // 设置返回状态码 ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value()); } return null; }}
测试时调用是通过直接发送给zuul,zuul转发到consumer,score_consumer通过Feign远程调用score_service。获取结果返回给客户端
测试查询,记得带上token参数,zuul中自定义过滤器的逻辑看一下
测试新增
压缩狗粮系列时光机:所有看到这里的同学,以下整合必须掌握并实现
第一篇:框架整合战斗压缩粮篇-----SSH(致敬经典)
第二篇:框架整合战斗压缩粮篇------SpringMVC+Spring+MyBatis(SSM)
第三篇:框架整合战斗压缩粮篇------Dubbo+SSM
第四篇: 框架整合战斗压缩粮篇------SpringBoot+SSM
第五篇:框架整合战斗压缩粮篇------SpringCloud+SpringBoot+SSM
整合就到这里
今日论点:
《写个各位新老朋友的的话》
1.分清职责,做好份内之事
经常看到同学拿着公司模糊的开发需求来咨询这个是什么,不理解需求之类的,这里说明一下,我一直强调要分清工作重心,我们是开发人员,不是产品设计,也不是架构师。对我们来讲熟悉手上现有代码逻辑,并能实现功能是工作重点,这里强调我们是实现功能,不是设计功能。所以如果有人提需求,如果不能完全明白或理解所提需求的时候。
个人观点,要去跟提出需求的人,“认真”讨论,这里说认真可能新人害怕问的多了会不会让人厌烦啊,或者确实有些人表现出不耐烦的样子,可你要想明白一个问题,他想要的东西,你本身不去跟他了解清楚,你跑来问另外一个人?他要让你画个马,你说其他人怎么帮助你,马怎么画,太难了。。。抽象画派的?现实的?黑的?白的?奔跑的?静止的?大的?小的?你不问清楚提需求的人,就算你画了,不也是等着要重画的节奏,到时候他还得说,我不是要这个,我要那个,结果是你俩又开始互相伤害,所以,我推荐需求一定跟提出需求的人“细致认真”的沟通,了解他到底要什么,我觉得如果是个明白人,是个有社会工作经验的人,明白你是要跟他沟通需求,是为了更明白他要做什么,你能为他提供什么,他会跟你讲明白的,不用担心,紧张,大胆的问需求。
2.保持良好心态
不要觉得别人写的代码都很烂,只有自己写的最棒。我经常跟同学开玩笑的说,进了公司不要觉得人家美术画的UI丑,产品设计的文档不够细,项目经理安排不合理,测试组人员什么Bug都提,隔壁同事代码写的垃圾,新来的员工什么都不会。
工作上的客观现实,我承认,进度上有压力,可能确实是项目经理安排不合理,产品经理有可能着急效果,没提文档就开始要修改需求,测试组想尽可能的不要漏掉Bug怕被追责使劲的提莫名其妙的Bug,同事着急提交代码写的临时逻辑和注释确实潦草了些,新人跟你当初一样刚进公司,总要给人家熟悉的时间吧,这些可能都是现实存在的,但是我们做好自己该做的,先保证自己是遵守流程的。保证自己不是第一个将玻璃打碎的人。
你要明白良好的沟通,心态首先需要是平衡的。
3.经常多运动,保持身体的健康
这个道理我觉得不必多说了,干了这行,因为工作压力问题,身体需要多注意锻炼。还有一句话就是,工作不是生活,而生活包括了工作,我们努力工作是为了改变生活,为了更好的体验生活,并不是为了更好的体验工作吧?人生是为了体验这个存在的时间,是要自己去体验的,追求自己的理性,身体首先是重要的,我们的生活不要被工作改变,即使某些时候我们妥协了,但是我们要记得工作不是生活的全部,人生很精彩,要珍惜时间,珍惜自己。要会平衡生活和工作和家人朋友间的关系。