Spring Cloud之Feign消费和Hystrix熔断

news2024/11/15 9:19:19

Spring Cloud的Feign消费和Hystrix熔断

现如今,由于互联网的流行,很多特产都可以在网上订购,你可以在堆满积雪的冬北订购海南的椰子,海南的椰子就会采用很快的物流方式调送到堆满积地的东北,就相当于在本地实现了买椰子的举动,这种远程调用的方法称为Feign。如下图所示。

 

一、Feign的解释

Feign 主要是帮助我们方便进行rest api服务间的调用,其大体实现思路就我们通过标记注解在一个接口类上(注解上将包含要调用的接口信息),之后在调用时根据注解信息组装好请求信息,通过服务器获取生成真实的服务地址,最后将请求发送出去;之后将接收到的结果反序列化为相关的Java对象供我们直接使用。

Feign在实际应用中通过在启动类上标记 @EnableFeignClients 注解来开启feign的功能,服务启动后会扫描 @FeignClient 注解标记的接口,然后根据扫描的注解信息为每个接口类生成feign客户端请求,同时解析接口方法中的Spring MVC的相关注解,通过专门的注解解析器识别这些注解信息,以便后面可以正确的组装请求参数,使用Eureka 获取到请求服务的真实地址等信息,最后使用 http 相关组件进行执行调用。其大致流程图如下:

 

在Feign的通信过程中,可能会出现服务器荡机的状况,Hystrix起到了一定的熔断保护措施。

二、Hystrix的解释

Hystrix是一个用于处理分布式系统的延迟和容错开源库,在分布式系统中,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能保证在一个依赖出现问题时,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

hystrix提供了五种理论技术,如下:

1、降级:当调用出现异常或超时等无法返回正常数据时,返回一个合理的结果或实现fallback方法,针对客户端而言。

2、熔断:当失败率达到阈值自动触发降级,这里的熔断就是具有特定条件的降级,当出现熔断时在设定的时间内不在请求。熔断有自动恢复机制,举个例子说,当熔断器启动后,每隔10秒,尝试将新的请求发送给service,如果服务可正常执行并返回结果,则关闭熔断器,恢复服务。如果仍调用失败,则继续返回fallback,熔断器持续开启。

3、请求缓存:服务A调用服务B,如果在A中添加请求缓存,第一次请求后走缓存,不在访问微服务B,即使出现大量请求,不会对B产生高负荷。请求缓存可以使用spring cache实现。

4、请求合并:当服务A调用服务B时,设定在5毫秒内所有请求合并到一起,对于服务B的负荷就会减少。使用@HystrixCollapser。方法返回值必须为Future

5、隔离:隔离分为线程池隔离合信号量隔离。通过判断线程池或信号量是否满,超过容量的请求直接降级,从而达到限流。

Hystrix可以理解成电路中的保险丝,线路不通还有那么一层保护,如下图所示。

 

三、产品的eureka服务器的启动

1、点击File--->New---->Project.....,如下图。

 

2、在弹出的地话框中,左边点击Spring Initializr,表示Spring的初始程序,右边在默认的地方可能会初始化失败,需要选择自定义的地址:http://start.aliyun.com。如右图所示。

 

3、在接下来的弹出框中输入spring cloud项目名称的Group和artifactId。如下图所示。

 

4、点击Next进入下一步,左边先点击Web,右边点击Spring web可以建立Web应用程序。如下图。

 

5、继续在这个对话框中,左边点击Spring Cloud Discovery,右边点击Eureka Server,如下图所示。

 

6、然后点击Next进入到“下一步”,会出现对话框。如下图所示。

 

7、在出现的对话框中,点击Finish后完成项目的构建向导。

项目框架建立后,修改主程序中的主类,如下图所示。

 

8、在打开的主程序中,加入注解@EnableEurekaServer。如下图所示。

 

最终,eurekaserver的程序代码如下。

package com.myfirsteurekabalance.myfirsteurekabalance;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class MyfirsteurekabalanceApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyfirsteurekabalanceApplication.class, args);
    }

}

9、下面需要编辑resources下面的application.yml文件,在原来的resouces目录下只有application.properties,需要把application.properties改成application.yml。然后编辑该文件。

 

10、application.yml的文件内容如下。

# 应用名称
spring:
  application:
    name: myfirsteurekabalance
# 应用服务 WEB 访问端口
server:
  port: 8819
eureka:
  client:
    register-with-eureka: true
    fetch-registry: false
    service-url:
      defaultZone: http://localhost:8819/eureka
  instance:
    hostname: myprovider1

其文件内容的解释如下 。

 

四、产品的Feign客户端的搭建

1、同样点击File--->New----->Project....,如下图所示。

 

2、在打开的对话框中,左边继续点击Spring Initializr,表示Spring的初始程序,右边在默认的地方可能会初始化失败,需要选择自定义的地址:http://start.aliyun.com。如下图所示。

 

3、点击Next,然后在出现的对话框中输入项目名称。如下图所示。

 

4、在接下来出现的对话框中,左边选择Web,右边选择Spring Web。如下图所示。

 

5、继续在这个对话框中,左边选择Spring Cloud Discovery,右边选择Eureka Discovery Client。如下图所示。

 

6、然后点击左侧的Spring Cloud Routing,然后点右侧的OpenFeign。再点击Next。

 

7、然后点击下一步即Next,在出现的对话框中直接点击Finish完成项目建立的向导。如下图所示。

 

项目完成后,接下来设置pom.xml中需要用到的依赖包,具体依赖内容如下。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.2.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zipkin</artifactId>
        <version>2.2.8.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

这里面后加入的依赖是spring-cloud-starter-zipkin、lombok、spring-cloud-starter-netflix-hystrix。具体依赖的内容如下。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.2.10.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
    <version>2.2.8.RELEASE</version>
</dependency>

8、这里是需要Feign的fallback,Fallback可以帮助我们在使用Feign去调用另外一个服务时,如果出现了问题,走服务降级,返回一个错误数据,避免功能因为一个服务出现问题,全部失效。需要首先定义feign包,然后产生feign的java包。这里feign的包中包括两个Feign消费端,一个是Product的Feign消费端,一个是Order的Feign消费端。结构如下。

 

对于ProductFeign需要使用FegnClient指定消费客户端,同时指定消费在eureka注册中心的服务器名称,并且指明如果服务出现问题的服务降级错误处理fallback。

注意,这里的feign是一个接口,代码如下。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.stereotype.Component;
@FeignClient(name="myprovider5",fallback= ProductFallBackMethod.class)
public interface ProductFeign {
    @GetMapping("/product/lists")
    public String lists();
}

对于OrderFeign的代码也是做这样的处理,代码如下。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.stereotype.Component;
@FeignClient(name="myprovider4",fallback= OrderFallBackMethod.class)
public interface OrderFeign {
    @GetMapping("/order/lists")
    public String lists();
}

9、每个feign消费端都指定了一个fallback类方法,所以需要分别定义ProductFallback和OrderFallback的类方法,可以把这两个类放在fallback包下面.结构如下图。

 

在ProductFallbackMethod方法中实现定义的Feign接口,并且重写ProductFeign接口中的lists方法.特别注意的是这个类必须使用@Component注解来说明,不然spring cloud找不到这个fallback方法。代码如下。

package com.example.mymicroservice1.fallback;

import com.example.mymicroservice1.feigns.ProductFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class ProductFallBackMethod implements ProductFeign {
    @Override
    public String lists() {
        log.info("ProductFacllbackMethod调用异常");
        return "ProductFacllbackMethod调用异常";

    }
}

代码中的log只是输出日志文件, return是返回到网页中的显示数据,这里的log使用lombok的Slf4j注解来实现,实现后就会有log的声明。

同理实现OrderFallBackMethod方法,代码如下。

import com.example.mymicroservice1.feigns.OrderFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class OrderFallBackMethod implements OrderFeign {
    @Override
    public String lists() {
        log.info("OrderFallBackMethod调用异常");
        return "OrderFallBackMethod调用异常";
    }
}

实现了这个fallback类后,对这两个Feign的调用可以通过service来实现,首先可以建立services包,然后建立一个微服务接口,注意,这里是接口, queryProductList方法中未来会实现ProductFeign, queryOrderList方法中未来会实现OrderFeign。

将两个服务放在一个微服务service的接口Micro1Service代码如下。

package com.example.mymicroservice1.services;
public interface Micro1Service {
    String queryProductList();
    String queryOrderList();
}

接下来定义第一个微服务Micro1Service接口的实现类。services包的结构图如下。

 

这里建立一个impl包,在impl包下面建立Micro1Service的接口的实现类Micro1ServiceImpl.代码如下。

package com.example.mymicroservice1.services.impl;

import com.example.mymicroservice1.feigns.OrderFeign;
import com.example.mymicroservice1.feigns.ProductFeign;
import com.example.mymicroservice1.services.Micro1Service;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@Service
@Slf4j
public class Micro1ServiceImpl  implements Micro1Service {
    @Autowired
    private ProductFeign productFeign;
    @Autowired
    private OrderFeign orderFeign;
    @Override
    public String queryProductList() {
        String lists=productFeign.lists();
        log.info("ProductFeign调用返回结果:{}",lists);
        return lists;
    }

    @Override
    public String queryOrderList() {
        String lists=orderFeign.lists();
        log.info("OrderFeign调用结果返回:{}",lists);
        return lists;
    }
}

注意,这里的Micro1ServiceImpl实现类需要实现接口Micro1Service,同时需要使用注解Service,这样Spring Cloud可以得到这样的Service.在Service代码中将ProductFeign和OrderFeign 注入到Service当中,再实现Micro1Service的两个方法。在两个方法中分别调用ProductFeign和OrderFeign的lists接口。最后返回lists()接口返回的数据。

Service代码设置成功后,设置Controller控制器的代码,在控制器实现ProductList商品列表的显示及OrderList订单列表的显示.同时需要RestController对于页面返回数据的显示,在控制器中第一个微服务Micro1Service也需要注入到Controller控制器中。

代码如下。

package com.example.mymicroservice1.controller;
import com.example.mymicroservice1.services.Micro1Service;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@Slf4j
@RestController
@RequestMapping("/micro1")
public class Micro1Controller {
    @Autowired
    private Micro1Service micro1service;
    @RequestMapping("/productList")
    public String productList(){
        return micro1service.queryProductList();
    }
    @RequestMapping("/orderList")
    public String orderList(){
        return micro1service.queryOrderList();
    }
}

因为这个项目中使用Feign消费端,所以需要在主启动类中加入@EnableFeignClients的注解.代码如下。

package com.example.mymicroservice1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class Mymicroservice1Application {

    public static void main(String[] args) {
        SpringApplication.run(Mymicroservice1Application.class, args);
    }

}

最后的yml文件中需要设置客户端feign的启动,新版本的启动hystrix使用circuitbreaker,代码如下。

spring:
  application:
    name: myprovider2
  zipkin:
    base-url: http://localhost:9411/
  sleuth:
    sampler:
      probability: 1.0
server:
  port: 8830
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8819/eureka
  instance:
    hostname: myprovider2
feign:
  circuitbreaker:
    enabled: true

五、产品的Product消费端的产生.

1、同样点击File--->New----->Project....,如下图所示。

 

2、在打开的对话框中,左边继续点击Spring Initializr,表示Spring的初始程序,右边在默认的地方可能会初始化失败,需要选择自定义的地址:http://start.aliyun.com。如下图所示。

 

3、点击Next,然后在出现的对话框中输入项目名称。如下图所示。

 

4、在接下来出现的对话框中,左边选择Web,右边选择Spring Web。如下图所示。

 

5、继续在这个对话框中,左边选择Spring Cloud Discovery,右边选择Eureka Discovery Client。如下图所示。

 

6、然后点击下一步即Next,在出现的对话框中直接点击Finish完成项目建立的向导。如下图所示。

 

7、在Product的微服务消费端中需要定义一个Pojo与数据库中的product表相对应。建立pojo对应的包entity,然后在entity包中产生Pojo的类Product。结构如下图所示。

 

8、在Product商品类中定义商品需要的信息。

package com.example.mymicroservice2.entity;
import lombok.Data;
import java.util.Date;
@Data
public class Product {
    private Integer id;
    private String productName;
    private Double productPrice;
    private String crop;
    private Date createTime;
    private Date modifyTime;
    private String remark;
}

这里通过lombok的Data注解来实现类中的Getter和Setter方法。

根据mvc的原理,下面需要根据Product定义dao模型。首先建立dao包,然后来dao包下建立ProductDao接口文件,注意这里是一个接口,结构如下图。

 

在接口文件中,定义接口方法lists,其目的显示product表中的所有数据。同时将接口中的注解Mapper来实现与mybatis和配置文件进行对应。代码如下。

package com.example.mymicroservice2.dao;
import com.example.mymicroservice2.entity.Product;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ProductDao {
    public List<Product> lists();
}

这个ProductDao接口需要对应于mybatis的一个ProductDao.xml的mapper文件,mapper文件是存放在resource目录下,结构截图如下。

 

mapper文件内容中定义resultMap对应于Product类的类中字段,并通过select方法来完成product表的查询语句SQL操作,ProdudctDao.xml具体代码内容如下。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mymicroservice2.dao.ProductDao">
    <resultMap id="BaseResultMap" type="com.example.mymicroservice2.entity.Product">
        <id column="id" jdbcType="INTEGER" property="id"></id>
        <result column="product_name" jdbcType="VARCHAR" property="productName"></result>
        <result column="product_price" jdbcType="NUMERIC" property="productPrice"></result>
        <result column="crop" jdbcType="VARCHAR" property="crop"></result>
        <result column="create_time" jdbcType="TIMESTAMP" property="createTime"></result>
        <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"></result>
        <result column="remark" jdbcType="VARCHAR" property="remark"></result>
    </resultMap>
    <select id="lists" resultMap="BaseResultMap">
        select * from product
    </select>
</mapper>

注意mapper文件中resultMap中的column属性指向数据库中字段名,jdbcType指示数据库中的字段类型,property指示java bean中的类属性。

在<select>标签中指示select查询SQL语句查找product表中的所有数据。

有了dao层和pojo模型后,定义service层的接口,然后通过实现service层的接口实现接口的内部实现代码,结构图如下图。

 

ProductService接口方法中定义查询所有商品的接口lists,其代码如下。

package com.example.mymicroservice2.services;

import com.example.mymicroservice2.entity.Product;
import java.util.List;
public interface ProductService {
    public List<Product> lists();
}

对这样的Service接口定义实现,需要使用implements关键字实现这个接口,重写其中的lists方法,同时将ProductDao作为dao层注到Service层中,ProductDao层的逻辑是通过mybatis的配置文件中SQL语句来实现的.ProductServceImpl的代码如下。

package com.example.mymicroservice2.services.impl;

import com.example.mymicroservice2.dao.ProductDao;
import com.example.mymicroservice2.entity.Product;
import com.example.mymicroservice2.services.ProductService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
import java.util.List;

@Service
@Slf4j
public class ProductServiceImpl  implements ProductService {
    @Resource
    private ProductDao productDao;

    @Override
    public List<Product> lists() {
        List<Product> mylist=productDao.lists();
        log.info("查询商品的结果:{}",JSON.toJSONString(mylist));
        return mylist;
    }
}

这里输出调用了alibaba的json模块把输出的字符串以json的形式输出。

Service接口实现后,就可以实现Controller控制器的逻辑.在Controller接口中需要注意前面Feign消费端定义的请求接口是”/product”中的”/lists”路由路径.因此这里的Controller也要实现这样的路径.代码如下。

package com.example.mymicroservice2.services.impl;
import com.example.mymicroservice2.dao.ProductDao;
import com.example.mymicroservice2.entity.Product;
import com.example.mymicroservice2.services.ProductService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
import java.util.List;
@Service
@Slf4j
public class ProductServiceImpl  implements ProductService {
    @Resource
    private ProductDao productDao;

    @Override
    public List<Product> lists() {
        List<Product> mylist=productDao.lists();
        log.info("查询商品的结果:{}",JSON.toJSONString(mylist));
        return mylist;
    }
}

代码中也需要指明返回前端页面的是json数据的字符串化,使用了alibaba的json模块来进行转换。

代码截图如下。

package com.example.mymicroservice2.controller;
import com.example.mymicroservice2.entity.Product;
import com.example.mymicroservice2.services.ProductService;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.alibaba.fastjson.JSON;
import java.util.List;
@RestController
@RequestMapping("/product")
public class ProductController {
    @Autowired
    private ProductService productService;
    @GetMapping("/lists")
    public String lists(){
        List<Product> lists=productService.lists();
        return JSON.toJSONString(lists);
    }
}

客户端的yml文件中需要增加指明zipkin的路径,数据库的连接四个参数及mybatis的配置文件路径。具体内容如下。

spring:
    application:
        name: myprovider5
    datasource:
        url: jdbc:mysql://localhost:3306/testservice?characterEncoding=utf8
        driver-class-name: com.mysql.jdbc.Driver
        username: root
        password: admin
    zipkin:
        base-url: http://localhost:9411/
    sleuth:
        sampler:
            probability: 1.0
mybatis:
    mapper-locations: classpath*:/mapper/*.xml
server:
    port: 8065
eureka:
    client:
        service-url:
            defaultZone: http://localhost:8819/eureka

    instance:
        hostname: myprovider5

六、环境测试

1、新版本的zipKin,先启动zipkin的server端,通过maven仓库下载exec包的zipkin的jar包。然后通过java来执行。执行方法如下。

 java -jar zipkin-server-2.12.9-exec.jar

运行结果如下图所示。

 

2、启动eurekaserver端注册中心。

3、然后启动mymicro1server端的关于商品和订单消费的feign微服务。

4、再次启动mymicro2server端关于商品请求的与数据库关联的逻辑接口服务。

5、最后启动mymicro3server端关于订单请求的与数据库关联的逻辑接口程序。

zipkin启动后,可以通过网页web页面访问9411端口,即可看到zipkin页面。如下图所示。

 

7、urekaserver端,mymicro1server端,mymicro2server端三者都启动后,可以在浏览器中访问接口,就会返回数据信息。如下图所示。

 

注意:这里需要建立mysql数据库,数据库名与配置文件中的一致,并且在当前数据库中建立product表格和order表格,product表格中的字段与mapper文件中配置的resultMapper中的类型匹配需一致,并且向表中插入数据,表的结构和数据如下图.

 

8、当访问成功后,断开mymicro2server端,也就是断开商品列表的控制器端,最后访问结果如下 ,证明feign消费端的fallback有效。

 

9、访问成功后,刷新 zipkin的访问页面。可以看到服务名及服务的接口span名。点击查找时,如下图所示。

 

10、此时,可以点击zipkin页面左上角的Try lens UI按钮,然后可以看到图形化的链路跟踪。如下图。

 

看到的效果如下图。

 

 

 

七、注意点

1、新版的Spring cloud必须有新版的依赖,通过mvnrepository仓库查询最新版的hystrix的版本是2.2.10.RELEASE。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.2.10.RELEASE</version>
</dependency>

2、新版的spring cloud启动hystrix需要使用circuitbreaker,设置其为true,代码如下.

feign:
circuitbreaker:
   enabled:true

3、fallback方法中必须加入@Component注解,不然不能将fallback注册到方法中。

4、在主启动类中使用注解@EnableFeignClients.

5、在Feign的接口方法中,使用@FeignClient注解,在注解中使用能够ping通的子服务服务器名称,同时调用熔断的fallback方法,后面是fallback方法的类名。

6、测试时当子服务的服务器没有启动时,会显示fallback方法后面的类名中实现的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/99185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Opencv(C++)笔记--图像金字塔

目录 1--图像金字塔的原理 2--图像金字塔的用途 3--Opencv API 3-1--拉普拉斯金字塔上采样 3-2--高斯金字塔下采样 3-3--代码实例 4--参考 1--图像金字塔的原理 图像金字塔常用于图像缩放&#xff08;resize&#xff09;和图像分割当中&#xff0c;不同分辨率的图像以金…

CSS基础总结(四)浮动

文章目录 一、为什么需要浮动 1.传统网页布局的三种方式 2.标准流 二、浮动的概述 三、浮动的特性 1.脱标 2.一行显示&#xff0c;顶部对齐 3.具备行内块元素特性 四、清除浮动 1.为什么要清除浮动 2.清除浮动的本质与策略 3.清除浮动的四大方法 &#xff08;1&…

解决安卓刷新recyclerView时导致itemDecoration分栏标题绘制错乱(重叠和隔空现象)

安卓的 itemDecoration 装饰器是个好东西&#xff0c;可以与adapter适配器一样闪耀。但是刷新的时候有可能发生重叠绘制或者莫名隔空的BUG。 三、原作 本文分栏标题装饰器的原作者为简书博主endeavor等人&#xff1a; https://www.jianshu.com/p/8a51039d9e68 二、隔空 紧…

Java+MySQL基于ssm的残疾人管理系统

我国残疾人人口数量相当巨大,据中残联给出的数据,我国约有8500万残疾人。残疾人是社会弱势群体,并且数量庞大影响人数众多,如何能更好的对这些残疾人进行关注和帮助他们更好的生活是当下社会研究的一个主要问题之一,于是我们提出了残疾人信息管理系统的设计与开发。 本课题是一…

内核驱动修改内存

概述 本文会利用内核驱动进行读写取第三方应用内存。 内核实现会使用内联汇编 所以对于内核数据结构每个windwos版本不一样需要判断&#xff0c;本文使用19041所写代码。 命令行&#xff1a;winver 即可查看你当前的版本&#xff0c;如下图19042.631 就是构建版本号 或者调用…

痞子衡嵌入式:低功耗高性能边缘人工智能应用的新答案 - MCXN947

大家好&#xff0c;我是痞子衡&#xff0c;是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦MCX系列MCU的新品MCXN947。 自 2015 年恩智浦和飞思卡尔合并成新恩智浦之后&#xff0c;关于它们各自的 Arm Cortex-M 内核通用微控制器代表作系列 LPC 和 Kinetis 接下来怎么发展…

数据结构 | 链式二叉树【递归的终极奥义】

递归——这就是俄罗斯套娃吗&#x1f62e;&#x1f333;链式二叉树的结构及其声明&#x1f333;链式二叉树的四种遍历方式&#x1f4d5;先序遍历&#xff08;先根遍历&#xff09;递归算法图解&#x1f4d5;中序遍历&#xff08;中根遍历&#xff09;&#x1f4d5;后序遍历&…

TIA PORTAL 导出导入数据块

1.导出&#xff1a;选择要导出的数据块鼠标右键-->从块生成源-->仅所选块或包含所有关联块-->最后选择数据块的存储路径保存 2.导入&#xff1a;选外部源文件-->添加新的外部文件-->选择要导入的数据块文件-->单击文件鼠标右键-->从源生成块&#xff0c;最…

Vue3——ref(),reactive(),watch(),computed()的使用

都需要先引入才能使用 ref()函数 作用&#xff1a;创建一个响应式变量&#xff0c;使得某个变量在发生改变时可以同步发生在页面上 模板语句中使用这个变量时可以直接使用变量名来调用&#xff0c;在setup内部调用时则需要在变量明后面加上一个.value获取它的值&#xff0c;原…

记录一次使用卷积神经网络进行图片二分类的实战

写在前面 笔者目前就读的专业是软件工程&#xff0c;并非人工智能专业&#xff0c;但是由于对人工智能有兴趣&#xff0c;于是课下进行了一些自学。正巧最近有些闲暇时间&#xff0c;就想着使用自学的内容做个小型的实战。这篇文章的主要目的也就是从一个入门者的角度&#xf…

【C++】list

本期就来讲讲list的使用技巧 文章目录list的介绍及使用list的介绍list迭代器失效list的模拟实现list与vector的对比我们前面知道迭代器是一个像指针一样的东西&#xff0c;但是在C里面&#xff0c;出来string和vector&#xff0c;其他类都不能 将迭代器当成指针使用&#xff0c…

二叉树的非递归与相关oj

&#x1f9f8;&#x1f9f8;&#x1f9f8;各位大佬大家好&#xff0c;我是猪皮兄弟&#x1f9f8;&#x1f9f8;&#x1f9f8; 文章目录一、二叉树相关oj①二叉搜索树与双向链表②前序遍历和中序遍历构造二叉树二、二叉树的非递归①前序遍历非递归②中序遍历非递归③后序遍历非…

简单的算法思想 - 利用快慢指针解决问题 - 寻找链表中的中间节点,回文序列,倒数第k个节点 - 详解

文章目录1. 寻找链表中倒数第K个节点1.1. 思路分析1.2 代码实现2. 寻找链表中的中间结点2.1 思路概述2.2 代码实现3. 链表的回文结构3.1 思路分析3.2 代码实现总结✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来&#xff01; 本文通过寻找链表中的中间节点&#xff0…

汽车托运网址

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 基于Web的汽车托运网站的设计与实现 网站前台&#xff1a;关于我们、联系我们、公告信息、卡车类型、卡车信息、运输评论…

【语音处理】一种增强的隐写及其在IP语音隐写中的应用(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

Effective Objective-C 2.0学习记录(一)

48.多用块枚举&#xff0c;少用for循环for循环快速枚举&#xff08;快速遍历&#xff09;基于块的遍历方式在编程中经常需要用到列举collection&#xff08;NSArray、NSDictionary、NSSet等&#xff09;中的元素&#xff0c;当前的Objective-C语言有多种办法实现此功能&#xf…

【专栏】核心篇09| 怎么保证缓存与DB的数据一致性

计算机类PDF整理&#xff1a;【详细&#xff01;&#xff01;】计算机类PDF整理 Redis专栏合集 【专栏】01| Redis夜的第一章 【专栏】基础篇02| Redis 旁路缓存的价值 【专栏】基础篇03| Redis 花样的数据结构 【专栏】基础篇04| Redis 该怎么保证数据不丢失&#xff08;上…

Python -- 模块和包

目录 1.Python中的模块 1.1 import 1.3 from...import * 1.4 as别名 2.常见的系统模块和使用 2.1 OS模块 2.2 sys模块 2.3 math模块 2.4 random模块 2.5 datetime模块 2.6 time模块 2.7 calendar模块 2.8 hashlib模块 2.9 hmac模块 2.10 copy模块 3.pip命令的使…

【机器学习---01】机器学习

文章目录1. 什么是机器学习&#xff1f;2. 机器学习分类2.1 基本分类2.2 按模型分类2.3 其他分类(不重要)3. 机器学习三要素4. 监督学习的应用(分类、标注、回归问题)1. 什么是机器学习&#xff1f; 定义&#xff1a;给定训练集D&#xff0c;让计算机从一个函数集合F {f1(x)&…

虚拟机打不开,提示“此主机不支持虚拟化实际模式”的详细解决方法

虚拟机打不开&#xff0c;提示“此主机不支持虚拟机实际模式”的解决方法 一、第一种情况安装/启动虚拟机失败&#xff0c; 在VMWare软件中&#xff0c;安装/启动虚拟机时&#xff0c;如果出以类似以下的错误提示&#xff1a; 出现该提示是由于电脑不支持虚拟化技术或是相关功…