小型框架合集2

十、SeaTa分布式事务

        添加依赖

        <!--    Seata和SpringBoot整合依赖      -->
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
        </dependency>
        <!--   Seata 完成分布式事务的两个相关依赖(Seata会自动使用其中的资源)   -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>

消费者只添加

      <!--    Seata和SpringBoot整合依赖      -->
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
        </dependency>

        添加配置信息 

seata:
  #定义事务分组,方便与其他项目区分  
  tx-service-group: csmall_group
  service:
    vgroup-mapping:
      #分组配置按照默认的配置seata      
      csmall_group: default
    grouplist:
      #配置seata服务器地址和端口号      
      default: localhost:8091

        事务触发者(消费者)添加注解 :谁是TM就添加注解

    //Global全局 Transactional事务
    //方法添加注解后,会设置为分部式事务的起点,当前模块就是TM事务管理器
    //所有远程调用操作数据库的功能都在同一个事务中,体现事务原子性
    @GlobalTransactional
    @Override
    public void buy() {
        OrderAddDTO orderAddDTO = new OrderAddDTO();
        orderAddDTO.setMoney(20);
        orderAddDTO.setCommodityCode("PC100");
        orderAddDTO.setUserId("UU100");
        orderAddDTO.setCount(100);
        log.info("新增订单信息为:{}",orderAddDTO);
        //dubbo调用,完成订单的增加
        dubbooderService.orderAdd(orderAddDTO);
    }

 

十一、Sentinel框架

        主要用于限流

     <!--Spring Cloud Sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        配置路径,和spring cloud nacos处于同一路径 

sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel提供的运行状态仪表盘
        port: 8721 #执行限流的端口号,每个项目需设置不同端口号,例如cart模块设置为8722

        添加注解,添加在controller中。在方法运行前不会被检测到,必须执行一次后才可以被检测到

  @SentinelResource("减少商品库存数")
    public JsonResult reduceCommodityCount(
                        StockReduceCountDTO stockReduceCountDTO){
        // 调用业务逻辑层
        stockService.reduceCommodityCount(stockReduceCountDTO);
        return JsonResult.ok("库存减少完成!");
    }

十二、Gateway网关

添加网关依赖

        <!--   SpringGateway的依赖   -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--   Nacos依赖   -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--   网关负载均衡依赖    -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>

配置文件,配置网关路由

server:
  port: 9000
spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        # 网关也是微服务项目的一部分,所以也要注册到Nacos
        server-addr: localhost:8848
    gateway:
      # routes就是路由的意思,这是属性是一个数组类型,其中的值都是数组元素
      routes:
        # 数组元素配置中,-开头表示一个数组元素的开始,后面所有内容都是这个元素的内容
        # id表示当前路由的名称,和任何之前出现过的名字没有任何关联,唯一的要求就是不要后之后的id重复
        - id: gateway-beijing
          # 下面的配置是路由的目标,也就是目标的服务器名称
          # lb是LoadBalance的缩写,beijing是服务器名称
          uri: lb://beijing
          # predicates是断言的意思,就是满足某个条件时,去执行某些操作的设置
          predicates:
            # predicates也是一个数组,配置断言的内容
            # 这个断言的意思就是如果访问的路径是/bj/开头(**表示任何路径),
            # 就去访问上面定好的beijing服务器
            # ↓   P一定要大写!!!!!!!
            - Path=/bj/**
    # spring.cloud.gateway.routes[0].uri
    # spring.cloud.gateway.routes[0].predicates[0]

routes:

{                在配置中添加数组后是这个样子

                {"id":"gateway-beijing","uri":"lb://beijing","predicates":{"Path=/bj/**"}},

}

  动态路由配置:

        不需要再繁琐的添加路由配置

 gateway:
      #开启网关动态路由配置
      #匹配规则:在网关端口号后先编写注册在nacos的名称再编写路径
      #eg:localhost:9081/bj/show -> localhost:9000/beijing/bj/show
      discovery:
        locator:
          enabled: true

十二、Spring Data框架和ES搜索

        类似mybaits,数据源整合框架,此框架用作ES搜索引擎的数据源配置

 <!--   Spring Data Elasticsearch 整合依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
#es ip位置和端口号
spring.elasticsearch.rest.uris=http://localhost:9200
#设置日志门槛
logging.level.cn.tedu.search=debug
#SpringDataElasticsearch框架中有一个框架日志需要设置日志门槛
logging.level.org.elasticsearch.client.RestClient=debug

        添加数据库的实体类

@Data
@Accessors(chain = true) //支持链式set赋值
@AllArgsConstructor      //自动生成全参构造方法
@NoArgsConstructor       //自动生成无参构造方法
//@Document 对应ES框架的一个实体类
//indexName指定ES索引名  例如http中的(/questions),没有的话会自动创建
@Document(indexName = "items")
public class Item implements Serializable {
    //SpringData通过Id注解标记当前实体类主键
    @Id
    private Long id;
    //标记分词,定义分词器
    @Field(type = FieldType.Text,
            analyzer = "ik_max_word",
            searchAnalyzer = "ik_max_word")
    private String title;
    //FieldType.Keyword不分词按整体保存
    @Field(type = FieldType.Keyword)
    private String category;
    @Field(type = FieldType.Keyword)
    private String brand;
    @Field(type = FieldType.Double)
    private Double price;
    //index=false不添加索引
    @Field(type = FieldType.Keyword,index=false)
    private String imgPath;
}

        编写Repository层,等同于mapper层的mapper 

@Repository
//等同于mapper层的mapper,这是SpringData的命名规范,也必须 extends ElasticsearchRepository
public interface ItemRepository extends ElasticsearchRepository<Item, Long> {
    // ItemRepository接口要继承SpringData框架提供的父接口ElasticsearchRepository
    // 一旦继承,当前接口就可以编写连接ES操作数据的代码了,
    // 继承了父接口后,SpringData会根据我们泛型中编写的Item找到对应的索引
    // 会对这个索引自动生成基本的增删改查方法,我们自己无需再编写
    // ElasticsearchRepository<[要操作的\关联的实体类名称],[实体类主键的类型]>

    //SpringData实现自定义查询
    //ES数据库没有SQL语句
    //query(查询)等价SQL的select
    // Item/Items:确定要查询的实体类(对应的索引),不带s是查询单个对象的,带s的查集合
    // By(通过/根据):标识开始设置查询条件的单词,等价于sql中的where
    // Title:要查询的字段,可以是Item实体类中声明的任何字段
    // Matches(匹配):执行查询条件的操作,Matches是匹配字符串类型的关键字,支持分词等价sql中的like
    Iterable<Item> queryItemsByTitleMatches(String title);

    //多条件查询(与)
    Iterable<Item> queryItemsByTitleMatchesAndBrandMatches(String title, String brand);

    //条件查询结果排序
    //多条件查询(或)
    Iterable<Item> queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(String title, String brand);

    //分页查询
    Page<Item> queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(String title, String brand, Pageable pageable);
}

public interface ItemRepository extends ElasticsearchRepository<Item, Long>  

//需要继承springdata给定的父接口可以直接使用基本的增删改查方法

//要实现的实体类,主键类型

         实例测试

      //执行单增
    @Test
    void addOne() {
        Item item = new Item()
                .setId(1L)
                .setTitle("小米卷纸")
                .setCategory("生活")
                .setBrand("罗技")
                .setPrice(10.0)
                .setImgPath("/xioami.jpg");
        //利用自带的添加方法添加
        itemRepository.save(item);
        System.out.println("添加OK");
    }

    //单查
    @Test
    void getOne() {
        //optional类型只能放一个元素,类似List但list能放多个
        Optional<Item> byId = itemRepository.findById(1L);
        //把他从Optional里取出来
        Item item = byId.get();
        System.out.println(item);
    }

    //批量增
    @Test
    void addList() {
        //实例化一个list对保存到es数据库中
        List<Item> list = new ArrayList<>();
        list.add(new Item(2L, "罗技激光有线游戏鼠标", "鼠标"
                , "罗技", 9.9, "/2.jpg"));
        list.add(new Item(3L, "雷蛇机械无线办公键盘", "键盘"
                , "雷蛇", 119.9, "/3.jpg"));
        list.add(new Item(4L, "微软有线静音办公鼠标", "鼠标"
                , "微软", 29.9, "/4.jpg"));
        list.add(new Item(5L, "罗技机械有线背光键盘", "键盘"
                , "罗技", 236.0, "/5.jpg"));
        itemRepository.saveAll(list);
        System.out.println("批量添加OK");
    }

    //全查
    @Test
    void getAll() {
        Iterable<Item> items = itemRepository.findAll();
        for (Item item : items) {
            System.out.println(item);
        }
        System.out.println("------------------------");
        items.forEach(item -> System.out.println(item));
    }

    //单查
    @Test
    void queryOne() {
        //查询es中items索引数据,title中字段包含"游戏"的分词数据
        Iterable<Item> items = itemRepository.queryItemsByTitleMatches("键盘");
        items.forEach(item -> System.out.println(item));
    }

    //多条件查询
    @Test
    void queryTwo() {
        //查询ES中,items索引里,title字段包含"游戏",品牌是"罗技"的数据
        Iterable<Item> items = itemRepository
                .queryItemsByTitleMatchesAndBrandMatches("游戏", "罗技");
        items.forEach(item -> System.out.println(item));
    }

    //多条件查询结果排序
    @Test
    void queryTwoorderby() {
        //查询ES中,items索引里,title字段包含"游戏",品牌是"罗技"的数据
        Iterable<Item> items = itemRepository
                .queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc("游戏", "罗技");
        items.forEach(item -> System.out.println(item));
    }

    // 自定义分页查询
    @Test
    void queryPage(){
        int page=2;             // 要查询的页码,写1表示查询第一页
        int pageSize=2;         // 每页条数的设置
        Page<Item> pages=itemRepository
                .queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
                        "游戏","罗技", PageRequest.of(page-1,pageSize));
        pages.forEach(item -> System.out.println(item));
        // pages对象包含的分页信息输出
        System.out.println("总页数:"+pages.getTotalPages());
        System.out.println("总条数:"+pages.getTotalElements());
        System.out.println("当前页:"+(pages.getNumber()+1));
        System.out.println("每页条数:"+pages.getSize());
        System.out.println("是否是首页:"+pages.isFirst());
        System.out.println("是否是末页:"+pages.isLast());

    }

十三、Pagehelper分页

添加依赖

        <!--分页-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
        </dependency>

在业务中的使用

        Paperhelper框架完成分页的功能原理是sql语句后自动添加limit。

    //Mapper层
    //查所有
    List<LogMg> selectAll();
    //业务层接口
    //查所有
    List<LogMg> selectAll( Integer page,  Integer pageSize);

        page分页只需要包裹住业务层即可不需要关注mapper,controller层只需要调用业务接口就可以。

    //分页查询所有订单信息的方法
    //参数page是页码,pageSize是每页条数
    public List<LogMg> getAllOrdersByPage(Integer page, Integer pageSize) {
        //pagehepler框架实现分页最核心代码,是要编写在执行查询数据代码之前
        PageHelper.startPage(page, pageSize);
        //上面设置好分页执行条件,下面的查询在执行时,SQL会自动追加limit关键字
        List<LogMg> list = orderMapper.findAllOrders();
        return list;
    }

十四、Kafka消息队列

              添加依赖

 <!--Kafka整合SpringBoot=依赖-->
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>

             添加配置 

spring:
  kafka:
    #定义kafka的位置
    bootstrap-servers: localhost:9092
    #consumer.group-id  是kafka框架必需配置,是话题分组,来区分不同项目消息
    #这个分组名称会在发送时自动前缀在话题名称前
    consumer:
      group-id: csmall
@EnableDubbo
@SpringBootApplication
//启动kafka
@EnableKafka
//为了测试Kafka添加Spring自带的定时任务,向Kafka发送消息
@EnableScheduling
public class CsmallCartWebapiApplication {

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

}

         测试

        消息产生

//这个类要实现周期运行代码(定时任务)
@Component
public class Producer {
    //直接从spring中获取kafkaTemplate对象
    //这个对象会在springboot启动时,根据配置自动生成
    //kafkaTemplate<话题类型,消息类型>
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    int i = 0;

    //实现每隔15秒,发送以此话题
    @Scheduled(fixedRate = 15000)
    public void sendMessage() {
        Cart cart = new Cart();
        cart.setId(i++);
        cart.setUserId("UU100");
        cart.setCommodityCode("PC100");
        cart.setPrice(RandomUtils.nextInt(90) + 10);
        cart.setCount(RandomUtils.nextInt(10) + 1);
        //将cart转换为JSON格式发送
        //{"id":"1","userId":"UU100"....}
        Gson gson = new Gson();
        String json = gson.toJson(cart);
        System.out.println("要发送的JSON消息为"+json);
        //kafka发送
        kafkaTemplate.send("001",json);
    }
    
}

         消息接受

//要接受Kafka消息必须是spring中装载了的类
@Component
public class Consumer {
    //Springkafka使用了监听机制
    //我们指定了一个话题,只要这个话题发送了信息,这个监听器就会通知我们
    //topics="创建的话题"
    @KafkaListener(topics = "001")
    //方法的参数和返回值是话题指定的不能修改<话题类型,消息类型>
    public void received(ConsumerRecord<String, String> record) {
        //record由监听器自动赋值
        String json = record.value();
        Gson gson = new Gson();
        //                        需要转的值,转的类型
        Cart cart = gson.fromJson(json, Cart.class);
        System.out.println("接受消息" + cart);
    }
}

十五、RabbitMQ消息队列

        添加依赖

        <!--rabbitmq依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

      配置

spring: 
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

        创建交换机队列key 

@Slf4j
@Configuration
//配置Rabbit交换机,路由key和队列关系
//交换机,队列是实体对象,key是他俩绑定关系
public class RabbitConfig {
    public static final String STOCK_EX = "stock_ex";
    public static final String STOCK_ROUT = "stock_rout";
    public static final String STOCK_QUEUE = "stock_queue";

    //创建交换机
    @Bean
    public DirectExchange stockDirectExchange() {
        return new DirectExchange(STOCK_EX);
    }
    //创建队列
    @Bean
    public Queue stockQueue(){
        return new Queue(STOCK_QUEUE);
    }
    //绑定将队列绑定到交换机,和绑定的key
    @Bean
    public Binding stockBinding(){
        return BindingBuilder
                .bind(stockQueue()).to(stockDirectExchange())
                .with(STOCK_ROUT);
    }
}

        添加到消息队列 

       //秒杀成功记录添加到消息队列
        //success信息与秒杀sku信息大部分相同,赋值
        Success success = new Success();
        BeanUtils.copyProperties(seckillOrderAddDTO.getSeckillOrderItemAddDTO(), success);
        success.setUserId(userId);
        success.setOrderSn(orderAddVO.getSn());
        success.setSeckillPrice(seckillOrderAddDTO.getSeckillOrderItemAddDTO().getPrice());
        rabbitTemplate.convertAndSend(
                RabbitMqComponentConfiguration.SECKILL_EX,
                RabbitMqComponentConfiguration.SECKILL_QUEUE,
                success
        );

        接受

@Slf4j
@Component
//创建监听器
@RabbitListener(queues = RabbitConfig.STOCK_QUEUE)
public class RabbitMQConsumer {
    //唯一的注解,监听到后执行的方法
    @RabbitHandler
    public void process(Stock stock){
        System.out.println("消息接受完成:"+stock);
        log.info("消息接受完成:{}",stock);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值