springcloud 入门笔记-1


1.安装sts(spring tool suite)

1.安装后项目前有[boot],yml文件中编码会有提示,不可不用
安装参考:
http://www.itxxz.com/a/gaoji/2015/0120/eclipse_spring_tools.html
2.springboot中,最方便的是配置了热部署

<!-- 热部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

部署后项目前有[devtools],修改无需重启
3.boot封装了json,返回的对象都是json格式

2.依赖和集成

1.查看eureka依赖树,euraka下有ribbon
eureka搭建完成后可以使用如下url查看
http://172.x.x.x:9080/eureka/apps
http://172.x.x.x:9080/eureka/apps/service-name
2.feign下有ribbon和hystrix,已经集成,只需要在feign中配置fallback即可

3.自定义封装

可以是重复的类,也可是重复的feign接口

4.ribbon默认的负载均衡策略

默认是轮询测略,可自定义为随机策略

microservice-provider:  ##config ribbon   
  ribbon:   
    eureka:   
      enabled: false   
    listOfServers: localhost:8000, localhost:8002,localhost:8003 #假设provider有3台instance端口分别是8000 8002 8003  
    ServerListRefreshInterval: 15000  #设置服务列表刷新时间间隔

注意:
1.自定义配时,@Configuration包和@ComponentsScan包不应重叠
2.使用RestTemplate时,想要获得一个List时,应使用数组,而不应该直接使用List

5.feign集成了ribbon和hystrix

1.feign是webservice的客户端,
2.默认@FeignClient(name=”“)不写默认为name,
不建议用service-id,看源码知过时了,

    @Deprecated
    String serviceId() default "";

其中参数还有个属性为url,注意有url时必须有name
最重要的话: (官文原话)
springcloud根据需要使用FeignClientConfiguration为每个命名的客户端创建一个新的整体作为ApplicationContext.包含feign Decoder,feign Encoder,feign Contract
即@FeignClient(“”)创建了一个子容器 ,包含日志,解码器,编码器,契约(是springmvcContract,故可以支持mvc注解)
这里写图片描述
3.有6个坑
3.1.接口中的方法必须用@RequestMapping(value= method=…),不能使用@GetMaping(不支持),否则无法启动
3.2.接口中的方法中往往有参数,一定不能省了@PathVariable(“”)设置value,否则报参数为0
3.3.接口中的方法中参数如果是对象,只能设置为Post方法,设置为get方法报错:需要get方法,即使你设置的就是get.
如果一定要用get,只能将对象属性全设置为参数,使用@RequestParam(“id”) int id,@RequestParam(“name”) string name…
3.4.在controller类中的注解上,如果不使用thymeleaf,则可用@RestController,对应方法上使用@GetMapping、@PostMapping;
如果使用thymeleaf,必须用@Controller,对应@RequestMaping…否则返回无法跳转到页面,只会返回对象
3.5.使用@Configuration时不要同时注解@ComponentsScan,有冲突
3.6 .启动应用报timeout错误时配置:

解决第一次请求报错超市异常(ms)
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
或者
hystrix.command.default.execution.timout.enabled: false

6.自定义feign

使用@FeignClient的configuration属性,指定feign的配置类:

@FeignClient(name = "microservice-provider-user", configuration = FeignConfiguration.class)
public interface UserFeignClient {
  /**
   * 使用feign自带的注解@RequestLine
   * @see https://github.com/OpenFeign/feign
   * @param id 用户id
   * @return 用户信息
   */
  @RequestLine("GET /{id}")
  public User findById(@Param("id") Long id);
}

注意其中的注解格式,然后是配置类:

/**
 * 该类为Feign的配置类
 * 注意:该不应该在主应用程序上下文的@ComponentScan中。
 */
@Configuration
public class FeignConfiguration {
  /**
   * 将契约改为feign原生的默认契约。这样就可以使用feign自带的注解了。
   * @return 默认的feign契约
   */
  @Bean
  public Contract feignContract() {
    return new feign.Contract.Default();
  }
}

目录结构为:
这里写图片描述
上面的方式只是为UserFeignClient 接口设置了feign的配置类,如果还有其他的接口怎么办?
目前的方法是创建第二个接口类,对应设置第二个配置类。
feign的功能很多
1.压缩GZIP
feign.compression.request.enabled=true
feign.compression.response.enabled=true
2.日志: yml中配置,使用接口类全类名:

logging:
  level:
    com.xx.UserFeignClient: DEBUG

同时在配置类中添加,四个级别NONE,BASIC,HEADERS,FULL

@Configuration
public class FooConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

更多功能看官文
详细https://github.com/OpenFeign/feign
cloud文档http://cloud.spring.io/spring-cloud-static/Dalston.SR1/

7.eureka常见问题

7.1 eureka界面的enviroment和datacenter配置

eureka:
  enviroment: product #eureka中环境
  datacenter: cloud #eureka中datacenter,使用cloud,这样eureka将会知道是在AWS云上

7.2 eureka的自我保护提示
eureka的自我保护模式主要用于在一组客户端和eureka服务器之间存在网络分区的情况下的保护,在这些情况下,服务器尝试保护其已有的信息。就是说即使某个服务停止了,注册中心依然不剔除它。但是在开发阶段,这个不是我们需要的。
注意的是使用sts,则保护模式会失效,因为在点击停止的时候,sts会调用springboot的shundown hook,这个钩子会向eureka server主动下线。
如果要配置关闭自我保护,如下:

server端:
    eureka.server.enable-self-preservation  #设为false,关闭自我保护模式
    eureka.server.eviction-interval-timer-in-ms #清理间隔(ms,默认60*1000)
client端:
    eureka.client.healthcheck.enabled = true    #开启健康检查(actuator)
    eureka.instance.lease-renewal-interval-in-seconds=10   #租期更新时间间隔(默认30s)
    eureka.instance.lease-expiration-duration-in-seconds =30  #租期到期时间(默认90s)

示例如下:

eureka: 
  instance: 
    ip-address: 172.x.x.x
    prefer-ip-address: true
    lease-renewal-interval-in-seconds: 10 # 租期更新时间间隔(默认30s)
    lease-expiration-duration-in-seconds: 30 #租期到期时间(默认90s)
  client: 
    serviceUrl: 
      defaultZone: http://172.x.x.x:9079/eureka/
    register-with-eureka: true
    fetch-registry: true
    healthcheck: 
      enabled: true #开启健康检查(actuator)
  server:
    enable-self-preservation: false #设为false,关闭自我保护模式
    eviction-interval-timer-in-ms: 4000 #清理间隔(ms,默认60*1000)

注意
1.更改eureka更新频率将打破服务器的自我保护功能
2.生产阶段不要更改eureka的配置,否则保护模式失效

8.feign的hystrix支持

Hystrix支持回退的概念:当断路器打开或者出现错误时执行的默认代码路径,要为给定的@FeignClient启用回退,请将fallback属性设置为实现回退的类名。
全局打开或禁用hystrix:

feign.hystrix.enabled = false

前面提到feign下集成有ribbon和hystrix,已经集成,只需要在feign中配置fallback即可

/**
 * Feign的fallback测试
 * 使用@FeignClient的fallback属性指定回退类
 */
@FeignClient(name = "microservice-provider-user", fallback = FeignClientFallback.class)
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
}
/**
 * 回退类FeignClientFallback需实现Feign Client接口
 * FeignClientFallback也可以是public class,没有区别
 */
@Component
class FeignClientFallback implements UserFeignClient {
  @Override
  public User findById(Long id) {
    User user = new User();
    user.setId(-1L);
    user.setUsername("默认用户");
    return user;
  }
}

注意使用@Component时,不用配@ComponentScan,启动类有集成

怎样禁用单个FeignClient的Hystrix?
如同上面提到的,当有多个FeignClient接口类,怎么禁用某个的hystrix呢?
在configuration类中加入:

  @Bean
  @Scope("prototype")
  public Feign.Builder feignBuilder(){
      return Feign.builder();
  }

之所以可以如此是因为

Feign.Builder feignBuilder: HystrixFeign.Builder

默认就是使用Feign.Builder 支持hystrixFeign。

9.feign的hystrix fallbacks

如果你需要在触发fallback触发器时返回一个错误原因,你可以使用fallbackFactory:

@FeignClient(name = "microservice-provider-user", fallbackFactory = FeignClientFallbackFactory.class)
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
}
/**
 * UserFeignClient的fallbackFactory类,该类需实现FallbackFactory接口,并覆写create方法
 */
@Component
class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
  private static final Logger LOGGER = LoggerFactory.getLogger(FeignClientFallbackFactory.class);
  @Override
  public UserFeignClient create(Throwable cause) {
    return new UserFeignClient() {
      @Override
      public User findById(Long id) {
        // 日志最好放在各个fallback方法中,而不要直接放在create方法中。
        // 否则在引用启动时,就会打印该日志。
        // 详见https://github.com/spring-cloud/spring-cloud-netflix/issues/1471
        FeignClientFallbackFactory.LOGGER.info("fallback; reason was:", cause);
        User user = new User();
        user.setId(-1L);
        user.setUsername("默认用户");
        return user;
      }
    };
  }
}
前端参数为:var jsonData = { "id":id, "jsonDateForDetail":jsonDateForDetail, "contractCode":contractCode, "contractName":contractName, "contractType":contractType, "signingDate":signingDate, "shipperId":shipperId, "shipperName":shipperName, "companyAbbreviation":companyAbbreviation, "carrierId":carrierId, "carrierName":carrierName, "shipperContactPerson":shipperContactPerson, "shipperContactNumber":shipperContactNumber, "carrierContactPerson":carrierContactPerson, "carrierContactNumber":carrierContactNumber, "cashOnDeliveryRatio":cashOnDeliveryRatio, "settlementMethod":settlementMethod, "departureAddress":departureAddress, "arrivalAddress":arrivalAddress, "consignmentPeriod":consignmentPeriod, "shippingType":shippingType, "deliveryMode":deliveryMode, "numConfirmationMethod":numConfirmationMethod, "qaConfirmationMethod":qaConfirmationMethod, "remark":remark, "status":status, "contractProvision":contractProvision, "auditPerson":auditPerson, "auditTime":auditTime, "auditOpinion":auditOpinion, //后加的 "flag":flag }; Wb.request({ url:reqUrl , params: jsonData, success: function(resp) { app.appwin.hide(); app.appwinAudit.hide(); app.appgrid.store.reload(); if(oprType=="audit"){ Ext.Msg.alert('{#app_alert#}', "审核通过"); }else{ Ext.Msg.alert('{#app_alert#}', "保存成功"); } } }); 我新增的实体类: public class TransportVo extends RmValueObject{ private static final long serialVersionUID = 1L; private String id; private String contractCode; private String contractType; private String contractName; private Timestamp signingDate; private String shipperId; private String shipperName; private String companyAbbreviation; private String carrierId; private String carrierName; private String shipperContactPerson; private String shipperContactNumber; private String carrierContactPerson; private String carrierContactNumber; private BigDecimal cashOnDeliveryRatio; private String settlementMethod; private String departureAddress; private String arrivalAddress; private String consignmentPeriod; private String shippingType; private String deliveryMode; private String numConfirmationMethod; private String qaConfirmationMethod; private String remark; private String status; private String auditPerson; private Timestamp auditTime; private String auditOpinion; private String usableStatus; private Timestamp createTime; private String createIp; private String createUserId; private String createUserName; private Timestamp modifyTime; private String modifyIp; private String modifyUserId; private String modifyUserName; private Timestamp deleteTime; private String deleteIp; private String deleteFlag; private String deleteUserId; private String deleteUserName; private String orderCode; private String attribute1; private String attribute2; private String attribute3; private String attribute4; private String contractProvision; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getContractCode() { return contractCode; } public void setContractCode(String contractCode) { this.contractCode = contractCode; } public String getContractType() { return contractType; } public void setContractType(String contractType) { this.contractType = contractType; } public String getContractName() { return contractName; } public void setContractName(String contractName) { this.contractName = contractName; } public Timestamp getSigningDate() { return signingDate; } public void setSigningDate(Timestamp signingDate) { this.signingDate = signingDate; } public String getShipperId() { return shipperId; } public void setShipperId(String shipperId) { this.shipperId = shipperId; } public String getShipperName() { return shipperName; } public void setShipperName(String shipperName) { this.shipperName = shipperName; } public String getCompanyAbbreviation() { return companyAbbreviation; } public void setCompanyAbbreviation(String companyAbbreviation) { this.companyAbbreviation = companyAbbreviation; } public String getCarrierId() { return carrierId; } public void setCarrierId(String carrierId) { this.carrierId = carrierId; } public String getCarrierName() { return carrierName; } public void setCarrierName(String carrierName) { this.carrierName = carrierName; } public String getShipperContactPerson() { return shipperContactPerson; } public void setShipperContactPerson(String shipperContactPerson) { this.shipperContactPerson = shipperContactPerson; } public String getShipperContactNumber() { return shipperContactNumber; } public void setShipperContactNumber(String shipperContactNumber) { this.shipperContactNumber = shipperContactNumber; } public String getCarrierContactPerson() { return carrierContactPerson; } public void setCarrierContactPerson(String carrierContactPerson) { this.carrierContactPerson = carrierContactPerson; } public String getCarrierContactNumber() { return carrierContactNumber; } public void setCarrierContactNumber(String carrierContactNumber) { this.carrierContactNumber = carrierContactNumber; } public BigDecimal getCashOnDeliveryRatio() { return cashOnDeliveryRatio; } public void setCashOnDeliveryRatio(BigDecimal cashOnDeliveryRatio) { this.cashOnDeliveryRatio = cashOnDeliveryRatio; } public String getSettlementMethod() { return settlementMethod; } public void setSettlementMethod(String settlementMethod) { this.settlementMethod = settlementMethod; } public String getDepartureAddress() { return departureAddress; } public void setDepartureAddress(String departureAddress) { this.departureAddress = departureAddress; } public String getArrivalAddress() { return arrivalAddress; } public void setArrivalAddress(String arrivalAddress) { this.arrivalAddress = arrivalAddress; } public String getConsignmentPeriod() { return consignmentPeriod; } public void setConsignmentPeriod(String consignmentPeriod) { this.consignmentPeriod = consignmentPeriod; } public String getShippingType() { return shippingType; } public void setShippingType(String shippingType) { this.shippingType = shippingType; } public String getDeliveryMode() { return deliveryMode; } public void setDeliveryMode(String deliveryMode) { this.deliveryMode = deliveryMode; } public String getNumConfirmationMethod() { return numConfirmationMethod; } public void setNumConfirmationMethod(String numConfirmationMethod) { this.numConfirmationMethod = numConfirmationMethod; } public String getQaConfirmationMethod() { return qaConfirmationMethod; } public void setQaConfirmationMethod(String qaConfirmationMethod) { this.qaConfirmationMethod = qaConfirmationMethod; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getAuditPerson() { return auditPerson; } public void setAuditPerson(String auditPerson) { this.auditPerson = auditPerson; } public Date getAuditTime() { return auditTime; } public void setAuditTime(Timestamp auditTime) { this.auditTime = auditTime; } public String getAuditOpinion() { return auditOpinion; } public void setAuditOpinion(String auditOpinion) { this.auditOpinion = auditOpinion; } public String getUsableStatus() { return usableStatus; } public void setUsableStatus(String usableStatus) { this.usableStatus = usableStatus; } public Date getCreateTime() { return createTime; } public void setCreateTime(Timestamp createTime) { this.createTime = createTime; } public String getCreateIp() { return createIp; } public void setCreateIp(String createIp) { this.createIp = createIp; } public String getCreateUserId() { return createUserId; } public void setCreateUserId(String createUserId) { this.createUserId = createUserId; } public String getCreateUserName() { return createUserName; } public void setCreateUserName(String createUserName) { this.createUserName = createUserName; } public Date getModifyTime() { return modifyTime; } public void setModifyTime(Timestamp modifyTime) { this.modifyTime = modifyTime; } public String getModifyIp() { return modifyIp; } public void setModifyIp(String modifyIp) { this.modifyIp = modifyIp; } public String getModifyUserId() { return modifyUserId; } public void setModifyUserId(String modifyUserId) { this.modifyUserId = modifyUserId; } public String getModifyUserName() { return modifyUserName; } public void setModifyUserName(String modifyUserName) { this.modifyUserName = modifyUserName; } public Date getDeleteTime() { return deleteTime; } public void setDeleteTime(Timestamp deleteTime) { this.deleteTime = deleteTime; } public String getDeleteIp() { return deleteIp; } public void setDeleteIp(String deleteIp) { this.deleteIp = deleteIp; } public String getDeleteFlag() { return deleteFlag; } public void setDeleteFlag(String deleteFlag) { this.deleteFlag = deleteFlag; } public String getDeleteUserId() { return deleteUserId; } public void setDeleteUserId(String deleteUserId) { this.deleteUserId = deleteUserId; } public String getDeleteUserName() { return deleteUserName; } public void setDeleteUserName(String deleteUserName) { this.deleteUserName = deleteUserName; } public String getOrderCode() { return orderCode; } public void setOrderCode(String orderCode) { this.orderCode = orderCode; } public String getAttribute1() { return attribute4; } public void setAttribute1(String attribute1) { this.attribute1 = attribute1; } public String getAttribute2() { return attribute2; } public void setAttribute2(String attribute2) { this.attribute2 = attribute2; } public String getAttribute3() { return attribute3; } public void setAttribute3(String attribute3) { this.attribute3 = attribute3; } public String getAttribute4() { return attribute4; } public void setAttribute4(String attribute4) { this.attribute4 = attribute4; } public String getContractProvision() { return contractProvision; } public void setContractProvision(String contractProvision) { this.contractProvision = contractProvision; } } 后台方法: @RequestMapping(params = {"method=insert"}, method = {org.springframework.web.bind.annotation.RequestMethod.POST}, consumes = {"application/x-www-form-urlencoded"}, produces = {"application/json"}) @ResponseBody public Map<String, Object> insert(HttpServletRequest request, @Valid TransportVo vo){。。。。。} 为什么TransportVo 这个实体没有值呢?如果把后面这个实体参数删掉就可以请求跳转到后台。但问题是,我的项目中其他的页面也是这么写的就可以传值---前台传一个JSONDATA,后台方法有两个参数,页面发送请求之后,后台方法中这两个参数都有值。而我新建的页面却不行 我想知道是什么地方给这另外加的实体类赋值了呢?
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页