主项目链接:https://gitee.com/java_wxid/java_wxid
项目架构及博文总结:

  • 点击:【使用Spring Boot快速构建应用】
  • 点击:【使用Spring Cloud Open Feign基于动态代理动态构造请求实现与其他系统进行交互】
  • 点击:【使用Spring Cloud Hystrix实现服务容错、熔断、降级、监控】
  • 点击:【使用Spring Cloud Ribbon以库的方式集成到服务的消费方实现客户端负载均衡】
  • 点击:【使用Spring Cloud Gateway作为API网关服务进行请求拦截、服务分发、降级、限流】
  • 点击:【使用Spring Cloud Security Oauth2作为微服务统一认证中心实现用户认证和授权访问】
  • 点击:【使用Spring Cloud Stream作为消息驱动用于动态的切换中间件】
  • 点击:【使用Spring Cloud Skywalking基于字节码注入通过探针方式进行链路追踪、分布式追踪、性能指标分析、应用和服务依赖分析】
  • 点击:【使用Spring Cloud Alibaba Nacos实现服务注册/发现/续约/剔除/下线、心跳检测、服务配置管理、基于长轮训机制实现配置动态变更】
  • 点击:【使用Spring Cloud Alibaba Seata作为对项目代码无入侵的分布式事务解决方案】
  • 点击:【使用Spring Cloud Alibaba Sentinel实现高可用流量防护】
  • 点击:【使用Apache ShardingSphere作为关系型数据库中间件实现分库分表、读写分离】
  • 点击:【使用Apache Mybatis作为持久层框架用于定制化SQL、存储过程以及高级映射】
  • 点击:【使用Redis作为高性能分布式缓存数据库】
  • 点击:【使用ElasticSearch全文搜索】
  • 点击:【使用MongoDB非关系型数据库】
  • 点击:【使用xxl-job作为分布式任务调度平台】
  • 点击:【使用Elasticsearch + Logstash + Kibana作为日志收集系统】
  • 点击:【使用Apifox作为API文档、API调试、API Mock、API自动化测试】
  • 点击:【使用Apache Spark作为基于内存计算的大数据分析引擎用于批处理、交互式查询】
  • 点击:【使用ETL工具将数据源抽取到HDFS作为高可靠、高吞吐量的分布式文件系统存储,通过Hive清洗、处理和计算原始数据,Hive清洗处理后的结果,将存入Hbase,海量数据随机查询场景从HBase查询数据】
  • 点击:【使用领域驱动DDD设计和设计模式进行开发】
  • 点击:【使用Netty基于Java NIO封装的高性能的网络通信框架】
  • 点击:【使用k8s、docker、docker-compose、宝塔面板进行环境搭建和部署】
  • 点击:【使用Vue渐进式JavaScript框架作为适用场景丰富的Web前端框架】
  • 点击:【分享人才筛选、工作分配、高效办公、项目推动等团队管理经验】

项目模块:
前期规划,实现部分

java_wxid
├── demo                                                            // 演示模块
│     └── 模块名称:apache-mybatis-demo模块                            //Apache Mybatis集成(已实现并有博文总结)
│     └── 模块名称:apache-shardingsphere-demo模块                     //Apache ShardingSphere集成(已实现并有博文总结)
│     └── 模块名称:design-demo模块                                    //设计模式实战落地(已实现并有博文总结)
│     └── 模块名称:elasticsearch-demo模块                             //ElasticSearch集成(已实现并有博文总结)
│     └── 模块名称:mongodb-demo模块                                   //MongoDB集成(已实现并有博文总结)
│     └── 模块名称:redis-demo模块                                     //Redis集成(已实现并有博文总结)
│     └── 模块名称:spring-boot-demo模块                               //Spring Boot快速构建应用(已实现并有博文总结)
│     └── 模块名称:spring-cloud-alibaba-nacos-demo模块                //Spring Cloud Alibaba Nacos集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-alibaba-seata-demo模块                //Spring Cloud Alibaba Seata集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-alibaba-sentinel-demo模块             //Spring Cloud Alibaba Sentinel集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-gateway-demo模块                      //Spring Cloud Gateway集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-hystrix-demo模块                      //Spring Cloud Hystrix集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-open-feign-demo模块                   //Spring Cloud Open Feign集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-ribbon-demo模块                       //Spring Cloud Ribbon集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-security-oauth2-demo模块              //Spring Cloud Security Oauth2集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-security-oauth2-sso-client-demo模块   //Spring Cloud Security Oauth2集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-skywalking-demo模块                   //Spring Cloud Skywalking集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-stream-demo模块                       //Spring Cloud Stream集成(已实现并有博文总结)
│     └── 模块名称:swagger-demo模块                                   //springfox-swagger2集成(已实现并有博文总结)
│     └── 模块名称:xxl-job模块                                        //xxl-job集成(已实现并有博文总结)
│     └── 模块名称:apache-spark-demo模块                              //Apache Spark集成
│     └── 模块名称:etl-hdfs-hive-hbase-demo模块                       //ETL、HDFS、Hive、Hbase集成
│     └── 模块名称:ddd-mode-demo模块                                  //DDD领域设计
│     └── 模块名称:netty-demo模块                                     //Netty集成
│     └── 模块名称:vue-demo模块                                       //前端vue集成
├── document                                                        // 文档
│     └── JavaKnowledgeDocument                                     //java知识点
│           └── java基础知识点.md
│           └── mq知识点.md
│           └── mysql知识点.md
│           └── redis知识点.md
│           └── springcould知识点.md
│           └── spring知识点.md
│     └── FounderDocument                                           //创始人
│           └── 创始人.md

系列文章:快速集成各种微服务相关的技术,帮助大家可以快速集成到自己的项目中,节约开发时间。
提示:系列文章还未全部完成,后续的文章,会慢慢补充进去的。

文章目录

  • 创建spring-cloud-alibaba-sentinel-demo项目
    • 修改pom.xml
    • 修改SpringCloudAlibabaSentinelDemoApplication
    • 创建bootstrap.yml
    • 创建application.yml
    • 创建SentinelConfig
    • 创建HelloController
    • 创建LimitFlowController
    • 创建UserController
    • 创建UserDao
    • 创建AuthorityDemo
    • 创建FlowThreadDemo
    • 创建PaceFlowDemo
    • 创建SystemGuardDemo
    • 创建WarmUpFlowDemo
    • 创建UserEntity
    • 创建RRException
    • 创建OrderFeignService
    • 创建CommonBlockHandler
    • 创建CommonFallback
    • 创建MyBlockExceptionHandler
    • 创建MyRequestOriginParser
    • 创建MyUrlBlockHandler
    • 创建UserServiceImpl
    • 创建UserService
    • 创建Constant
    • 创建PageUtils
    • 创建Query
    • 创建R
    • 创建HTMLFilter
    • 创建SQLFilter
    • 创建XssFilter
    • 创建XssHttpServletRequestWrapper
    • 创建UserDao.xml

创建spring-cloud-alibaba-sentinel-demo项目

项目代码:https://gitee.com/java_wxid/java_wxid/tree/master/demo/spring-cloud-alibaba-sentinel-demo
项目结构如下(示例):

修改pom.xml

代码如下(示例):

<?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.example</groupId><artifactId>spring-cloud-alibaba-sentinel-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>spring-cloud-alibaba-sentinel-demo</name><description>Demo project for Spring Boot</description><!--    属性配置--><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><!--引入 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者 BOM 文件,进行依赖版本的管理,防止不兼容。在 https://dwz.cn/mcLIfNKt 文章中,Spring Cloud Alibaba 开发团队推荐了三者的依赖关系--><spring.boot.version>2.3.12.RELEASE</spring.boot.version><spring.cloud.version>Hoxton.SR12</spring.cloud.version><spring.cloud.alibaba.version>2.2.7.RELEASE</spring.cloud.alibaba.version></properties><dependencies><!--        代表web模块,在这个模块中含了许多JAR包,有spring相关的jar,内置tomcat服务器,jackson等,这些web项目中常用的的功能都会自动引入--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.4.5</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>2.4.1</version></dependency><!--        druid驱动--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.23</version></dependency><!--        mysql连接--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.22</version></dependency><!--        mybatis的一个库--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.3.2</version></dependency><!-- Alibaba Nacos 配置 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--        在SpringBoot 2.4.x的版本之后,对于bootstrap.properties/bootstrap.yaml配置文件(我们合起来成为Bootstrap配置文件)的支持,其实这个jar包里什么都没有,就只有一个标识类Marker,用来标识要开启Bootstrap配置文件的支持,由于父类用了2.5.6版本需要导入如下的依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId><version>3.1.0</version></dependency><!--openfeign客户端依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-openfeign-core</artifactId><version>2.2.6.RELEASE</version></dependency><!--引入HttpClient依赖--><dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId></dependency><!-- 引入Feign Slf4j --><dependency><groupId>com.netflix.feign</groupId><artifactId>feign-slf4j</artifactId><version>8.14.4</version></dependency><!--        lombok插件--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>RELEASE</version><scope>compile</scope></dependency><!--        @SentinelResource 注解用来标识资源是否被限流、降级。blockHandler: 定义当资源内部发生了BlockException应该进入的方法(捕获的是Sentinel定义的异常)fallback: 定义的是资源内部发生了Throwable应该进入的方法exceptionsToIgnore:配置fallback可以忽略的异常源码入口:com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-annotation-aspectj</artifactId><version>1.8.0</version></dependency><!--        流控规则设置可以通过Sentinel dashboard配置客户端需要引入 Transport 模块来与 Sentinel 控制台进行通信。--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId><version>1.8.0</version></dependency><!--- 解决流控链路不生效的问题从1.6.3版本开始,Sentinel Web filter默认收敛所有URL的入口context,导致链路限流不生效。从1.7.0版本开始,官方在CommonFilter引入了WEB_CONTEXT_UNIFY参数,用于控制是否收敛context,将其配置为false即可根据不同的URL进行链路限流。1.8.0 需要引入sentinel-web-servlet依赖--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-web-servlet</artifactId></dependency><!-- Spring Cloud Alibaba整合Sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--sentinel持久化 采用 Nacos 作为规则配置数据源-->
<!--        <dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId></dependency>--></dependencies><!--引入 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者 BOM 文件,进行依赖版本的管理,防止不兼容。在 https://dwz.cn/mcLIfNKt 文章中,Spring Cloud Alibaba 开发团队推荐了三者的依赖关系--><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>${spring.boot.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring.cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring.cloud.alibaba.version}</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></build></project>

修改SpringCloudAlibabaSentinelDemoApplication

代码如下(示例):

package com.example.springcloudalibabasentineldemo;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;@MapperScan("com.example.springcloudalibabasentineldemo.dao")
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class SpringCloudAlibabaSentinelDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringCloudAlibabaSentinelDemoApplication.class, args);}}

创建bootstrap.yml

代码如下(示例):

#bootstrap.yml优先级比application.yml优先级高
spring:#prefix−{spring.profile.active}.${file-extension}#nacos会根据当前环境去拼接配置名称查找相应配置文件,#示例:{spring.application.name}-{spring.profiles.active}-{spring.cloud.nacos.config.file-extension}#获取到值:nacos-autoconfig-service-dev.ymlprofiles:#开发环境dev,测试环境test,生产环境prodactive: devapplication:#配置应用的名称,用于获取配置name: spring-cloud-alibaba-sentinel-democloud:nacos:discovery:# 服务注册地址server-addr: 106.14.132.94:8848config:#nacos配置中心地址server-addr: 106.14.132.94:8848#配置中心的命名空间idnamespace: 9e50b6d9-6c3d-4e7a-b701-10f085e4b98d#配置分组,默认没有也可以group: DEFAULT_GROUP#配置文件后缀,用于拼接配置配置文件名称,目前只支持yaml和propertiesfile-extension: yaml#配置自动刷新refresh-enabled: true#配置文件的前缀,默认是application.name的值,如果配了prefix,就取prefix的值#prefix: nacos-autoconfig-service-${spring.profile.active}# 配置编码encode: UTF-8username: nacospassword: nacos

创建application.yml

代码如下(示例):

server:port: 8095
#暴露actuator端点   http://localhost:8800/actuator/sentinel
management:endpoints:web:exposure:include: '*'
spring:application:name: mall-user-sentinel-democloud:sentinel:transport:# 添加sentinel的控制台地址dashboard: 127.0.0.1:8080# 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer#port: 8719#      datasource:#        ds1:#          nacos:#            server-addr: 127.0.0.1:8848#            dataId: ${spring.application.name}#            groupId: DEFAULT_GROUP#            data-type: json#            rule-type: flow#数据库配置datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://139.224.137.74:3306/syncdemo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: ca0a997ee4770063
#mybatis
mybatis-plus:mapper-locations: classpath*:/mapper/*.xml#实体扫描,多个package用逗号或者分号分隔typeAliasesPackage: com.example.springcloudalibabasentineldemo.entity

创建SentinelConfig

代码如下(示例):

package com.example.springcloudalibabasentineldemo.config;import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
import com.example.springcloudalibabasentineldemo.sentinel.MyUrlBlockHandler;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @className: SentinelConfig* @description: https://github.com/alibaba/Sentinel/issues/1213* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
@Configuration
public class SentinelConfig {@Beanpublic FilterRegistrationBean sentinelFilterRegistration() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new CommonFilter());registration.addUrlPatterns("/*");// 入口资源关闭聚合  解决流控链路不生效的问题registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");registration.setName("sentinelFilter");registration.setOrder(1);//CommonFilter的BlockException自定义处理逻辑WebCallbackManager.setUrlBlockHandler(new MyUrlBlockHandler());//解决授权规则不生效的问题//com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser//WebCallbackManager.setRequestOriginParser(new MyRequestOriginParser());return registration;}}

创建HelloController

代码如下(示例):

package com.example.springcloudalibabasentineldemo.controller;import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
@RestController
@Slf4j
public class HelloController {private static final String RESOURCE_NAME = "hello";@RequestMapping(value = "/hello")public String hello() {Entry entry = null;try {// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。entry = SphU.entry(RESOURCE_NAME);// 被保护的业务逻辑String str = "hello world";log.info("====="+str+"=====");return str;} catch (BlockException e1) {// 资源访问阻止,被限流或被降级//进行相应的处理操作log.info("block!");return "被流控了!";} catch (Exception ex) {// 若需要配置降级规则,需要通过这种方式记录业务异常Tracer.traceEntry(ex, entry);} finally {if (entry != null) {entry.exit();}}return null;}/*** 定义流控规则*/@PostConstructprivate static void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();//设置受保护的资源rule.setResource(RESOURCE_NAME);// 设置流控规则 QPSrule.setGrade(RuleConstant.FLOW_GRADE_QPS);// 设置受保护的资源阈值// Set limit QPS to 20.rule.setCount(1);rules.add(rule);// 加载配置好的规则FlowRuleManager.loadRules(rules);}
}

创建LimitFlowController

代码如下(示例):

package com.example.springcloudalibabasentineldemo.controller;import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.springcloudalibabasentineldemo.entity.UserEntity;
import com.example.springcloudalibabasentineldemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.concurrent.atomic.AtomicInteger;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
@RestController
public class LimitFlowController {@RequestMapping("/test")
//    @SentinelResource(value = "test",blockHandlerClass = CommonBlockHandler.class,blockHandler = "handleException3")public String test() {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}return "========test()========";}AtomicInteger atomicInteger = new AtomicInteger();@RequestMapping("/test2")public String test2() {atomicInteger.getAndIncrement();if (atomicInteger.get() % 2 == 0){//模拟异常和异常比率int i = 1/0;}return "========test2()========";}@Autowiredprivate UserService userService;@RequestMapping(value = "/test3")  //CommonFilterpublic UserEntity test3() {UserEntity user = userService.getUser(1);return user;}@RequestMapping(value = "/test4")public UserEntity test4() {UserEntity user = userService.getUser(1);return user;}public String handleException(BlockException exception) {return "===被限流降级啦===";}
}

创建UserController

代码如下(示例):

package com.example.springcloudalibabasentineldemo.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.springcloudalibabasentineldemo.entity.UserEntity;
import com.example.springcloudalibabasentineldemo.feign.OrderFeignService;
import com.example.springcloudalibabasentineldemo.sentinel.CommonBlockHandler;
import com.example.springcloudalibabasentineldemo.sentinel.CommonFallback;
import com.example.springcloudalibabasentineldemo.service.UserService;
import com.example.springcloudalibabasentineldemo.utils.PageUtils;
import com.example.springcloudalibabasentineldemo.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.Map;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
@RestController
@RequestMapping(value = "/user")
public class UserController {@Autowiredprivate UserService userService;@AutowiredOrderFeignService orderFeignService;@RequestMapping(value = "/getNacosConfigure")@SentinelResource(value = "getNacosConfigure",blockHandlerClass = CommonBlockHandler.class,blockHandler = "getNacosConfigure",fallbackClass = CommonFallback.class,fallback = "getNacosConfigure")public String getNacosConfigure() {
//        try {
//            // 模拟测试并发线程数限流
//            Thread.sleep(900);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }// findOrderByUserId  限流规则  2    sentinel dashboard 定义规则//feign调用String result = orderFeignService.getNacosConfigure();return result;}/*** 列表*/@RequestMapping("/list")@SentinelResource(value = "userlist",blockHandlerClass = CommonBlockHandler.class,blockHandler = "handleException",fallback = "fallback")public R list(@RequestParam Map<String, Object> params){PageUtils page = userService.queryPage(params);// int i=1/0;return R.ok().put("page", page);}public R handleException(@RequestParam Map<String, Object> params,BlockException exception){return R.error(-1,"===被限流降级啦===");}/*** 信息*/@RequestMapping("/info/{id}")@SentinelResource(value = "userinfo",blockHandlerClass = CommonBlockHandler.class,blockHandler = "handleException2",fallbackClass = CommonFallback.class,fallback = "fallback")public R info(@PathVariable("id") Integer id){UserEntity user = userService.getById(id);if(id==4){throw new IllegalArgumentException("异常参数");}return R.ok().put("mapper", user);}public R handleException2(@PathVariable("id") Integer id, BlockException exception){return R.error(-1,"===被限流降级啦===");}public R fallback(@PathVariable("id") Integer id,Throwable e){return R.error(-1,"===被熔断降级啦==="+e.getMessage());}/*** 保存*/@RequestMapping("/save")public R save(@RequestBody UserEntity user){userService.save(user);return R.ok();}/*** 修改*/@RequestMapping("/update")public R update(@RequestBody UserEntity user){userService.updateById(user);return R.ok();}/*** 删除*/@RequestMapping("/delete")public R delete(@RequestBody Integer[] ids){userService.removeByIds(Arrays.asList(ids));return R.ok();}}

创建UserDao

代码如下(示例):

package com.example.springcloudalibabasentineldemo.dao;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.springcloudalibabasentineldemo.entity.UserEntity;
import org.apache.ibatis.annotations.Mapper;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
@Mapper
public interface UserDao extends BaseMapper<UserEntity> {}

创建AuthorityDemo

代码如下(示例):

package com.example.springcloudalibabasentineldemo.demo;import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;import java.util.Collections;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class AuthorityDemo {private static final String RESOURCE_NAME = "testABC";public static void main(String[] args) {System.out.println("========Testing for black list========");initBlackRules();testFor(RESOURCE_NAME, "appA");testFor(RESOURCE_NAME, "appB");testFor(RESOURCE_NAME, "appC");testFor(RESOURCE_NAME, "appE");System.out.println("========Testing for white list========");initWhiteRules();testFor(RESOURCE_NAME, "appA");testFor(RESOURCE_NAME, "appB");testFor(RESOURCE_NAME, "appC");testFor(RESOURCE_NAME, "appE");}private static void testFor(/*@NonNull*/ String resource, /*@NonNull*/ String origin) {ContextUtil.enter(resource, origin);Entry entry = null;try {entry = SphU.entry(resource);System.out.println(String.format("Passed for resource %s, origin is %s", resource, origin));} catch (BlockException ex) {System.err.println(String.format("Blocked for resource %s, origin is %s", resource, origin));} finally {if (entry != null) {entry.exit();}ContextUtil.exit();}}private static void initWhiteRules() {AuthorityRule rule = new AuthorityRule();rule.setResource(RESOURCE_NAME);rule.setStrategy(RuleConstant.AUTHORITY_WHITE);rule.setLimitApp("appA,appE");AuthorityRuleManager.loadRules(Collections.singletonList(rule));}private static void initBlackRules() {AuthorityRule rule = new AuthorityRule();rule.setResource(RESOURCE_NAME);rule.setStrategy(RuleConstant.AUTHORITY_BLACK);rule.setLimitApp("appA,appB");AuthorityRuleManager.loadRules(Collections.singletonList(rule));}
}

创建FlowThreadDemo

代码如下(示例):

package com.example.springcloudalibabasentineldemo.demo;import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.util.TimeUtil;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class FlowThreadDemo {private static AtomicInteger pass = new AtomicInteger();private static AtomicInteger block = new AtomicInteger();private static AtomicInteger total = new AtomicInteger();private static AtomicInteger activeThread = new AtomicInteger();private static volatile boolean stop = false;private static final int threadCount = 100;private static int seconds = 60 + 40;private static volatile int methodBRunningTime = 2000;public static void main(String[] args) throws Exception {System.out.println("MethodA will call methodB. After running for a while, methodB becomes fast, "+ "which make methodA also become fast ");tick();initFlowRule();for (int i = 0; i < threadCount; i++) {Thread entryThread = new Thread(new Runnable() {@Overridepublic void run() {while (true) {Entry methodA = null;try {TimeUnit.MILLISECONDS.sleep(5);methodA = SphU.entry("methodA");activeThread.incrementAndGet();Entry methodB = SphU.entry("methodB");TimeUnit.MILLISECONDS.sleep(methodBRunningTime);methodB.exit();pass.addAndGet(1);} catch (BlockException e1) {block.incrementAndGet();} catch (Exception e2) {// biz exception} finally {total.incrementAndGet();if (methodA != null) {methodA.exit();activeThread.decrementAndGet();}}}}});entryThread.setName("working thread");entryThread.start();}}private static void initFlowRule() {List<FlowRule> rules = new ArrayList<FlowRule>();FlowRule rule1 = new FlowRule();rule1.setResource("methodA");// set limit concurrent thread for 'methodA' to 20rule1.setCount(20);rule1.setGrade(RuleConstant.FLOW_GRADE_THREAD);rule1.setLimitApp("default");rules.add(rule1);FlowRuleManager.loadRules(rules);}private static void tick() {Thread timer = new Thread(new TimerTask());timer.setName("sentinel-timer-task");timer.start();}static class TimerTask implements Runnable {@Overridepublic void run() {long start = System.currentTimeMillis();System.out.println("begin to statistic!!!");long oldTotal = 0;long oldPass = 0;long oldBlock = 0;while (!stop) {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {}long globalTotal = total.get();long oneSecondTotal = globalTotal - oldTotal;oldTotal = globalTotal;long globalPass = pass.get();long oneSecondPass = globalPass - oldPass;oldPass = globalPass;long globalBlock = block.get();long oneSecondBlock = globalBlock - oldBlock;oldBlock = globalBlock;System.out.println(seconds + " total qps is: " + oneSecondTotal);System.out.println(TimeUtil.currentTimeMillis() + ", total:" + oneSecondTotal+ ", pass:" + oneSecondPass+ ", block:" + oneSecondBlock+ " activeThread:" + activeThread.get());if (seconds-- <= 0) {stop = true;}if (seconds == 40) {System.out.println("method B is running much faster; more requests are allowed to pass");methodBRunningTime = 20;}}long cost = System.currentTimeMillis() - start;System.out.println("time cost: " + cost + " ms");System.out.println("total:" + total.get() + ", pass:" + pass.get()+ ", block:" + block.get());System.exit(0);}}
}

创建PaceFlowDemo

代码如下(示例):

package com.example.springcloudalibabasentineldemo.demo;import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.util.TimeUtil;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class PaceFlowDemo {private static final String KEY = "abc";private static volatile CountDownLatch countDown;private static final Integer requestQps = 100;private static final Integer count = 10;private static final AtomicInteger done = new AtomicInteger();private static final AtomicInteger pass = new AtomicInteger();private static final AtomicInteger block = new AtomicInteger();public static void main(String[] args) throws InterruptedException {System.out.println("pace behavior");countDown = new CountDownLatch(1);initPaceFlowRule();simulatePulseFlow();countDown.await();System.out.println("done");System.out.println("total pass:" + pass.get() + ", total block:" + block.get());System.out.println();System.out.println("default behavior");TimeUnit.SECONDS.sleep(5);done.set(0);pass.set(0);block.set(0);countDown = new CountDownLatch(1);initDefaultFlowRule();simulatePulseFlow();countDown.await();System.out.println("done");System.out.println("total pass:" + pass.get() + ", total block:" + block.get());System.exit(0);}private static void initPaceFlowRule() {List<FlowRule> rules = new ArrayList<FlowRule>();FlowRule rule1 = new FlowRule();rule1.setResource(KEY);rule1.setCount(count);rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);rule1.setLimitApp("default");/** CONTROL_BEHAVIOR_RATE_LIMITER means requests more than threshold will be queueing in the queue,* until the queueing time is more than {@link FlowRule#maxQueueingTimeMs}, the requests will be rejected.*/rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);rule1.setMaxQueueingTimeMs(20 * 1000);rules.add(rule1);FlowRuleManager.loadRules(rules);}private static void initDefaultFlowRule() {List<FlowRule> rules = new ArrayList<FlowRule>();FlowRule rule1 = new FlowRule();rule1.setResource(KEY);rule1.setCount(count);rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);rule1.setLimitApp("default");// CONTROL_BEHAVIOR_DEFAULT means requests more than threshold will be rejected immediately.rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);rules.add(rule1);FlowRuleManager.loadRules(rules);}private static void simulatePulseFlow() {for (int i = 0; i < requestQps; i++) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {long startTime = TimeUtil.currentTimeMillis();Entry entry = null;try {entry = SphU.entry(KEY);} catch (BlockException e1) {block.incrementAndGet();} catch (Exception e2) {// biz exception} finally {if (entry != null) {entry.exit();pass.incrementAndGet();long cost = TimeUtil.currentTimeMillis() - startTime;System.out.println(TimeUtil.currentTimeMillis() + " one request pass, cost " + cost + " ms");}}try {TimeUnit.MILLISECONDS.sleep(5);} catch (InterruptedException e1) {// ignore}if (done.incrementAndGet() >= requestQps) {countDown.countDown();}}}, "Thread " + i);thread.start();}}
}

创建SystemGuardDemo

代码如下(示例):

package com.example.springcloudalibabasentineldemo.demo;import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.csp.sentinel.util.TimeUtil;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class SystemGuardDemo {private static AtomicInteger pass = new AtomicInteger();private static AtomicInteger block = new AtomicInteger();private static AtomicInteger total = new AtomicInteger();private static volatile boolean stop = false;private static final int threadCount = 100;private static int seconds = 60 + 40;public static void main(String[] args) throws Exception {tick();initSystemRule();for (int i = 0; i < threadCount; i++) {Thread entryThread = new Thread(new Runnable() {@Overridepublic void run() {while (true) {Entry entry = null;try {entry = SphU.entry("methodA", EntryType.IN);pass.incrementAndGet();try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {// ignore}} catch (BlockException e1) {block.incrementAndGet();try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {// ignore}} catch (Exception e2) {// biz exception} finally {total.incrementAndGet();if (entry != null) {entry.exit();}}}}});entryThread.setName("working-thread");entryThread.start();}}private static void initSystemRule() {List<SystemRule> rules = new ArrayList<SystemRule>();SystemRule rule = new SystemRule();// max load is 3rule.setHighestSystemLoad(3.0);// max cpu usage is 60%rule.setHighestCpuUsage(0.6);// max avg rt of all request is 10 msrule.setAvgRt(10);// max total qps is 20rule.setQps(20);// max parallel working thread is 10rule.setMaxThread(10);rules.add(rule);SystemRuleManager.loadRules(Collections.singletonList(rule));}private static void tick() {Thread timer = new Thread(new TimerTask());timer.setName("sentinel-timer-task");timer.start();}static class TimerTask implements Runnable {@Overridepublic void run() {System.out.println("begin to statistic!!!");long oldTotal = 0;long oldPass = 0;long oldBlock = 0;while (!stop) {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {}long globalTotal = total.get();long oneSecondTotal = globalTotal - oldTotal;oldTotal = globalTotal;long globalPass = pass.get();long oneSecondPass = globalPass - oldPass;oldPass = globalPass;long globalBlock = block.get();long oneSecondBlock = globalBlock - oldBlock;oldBlock = globalBlock;System.out.println(seconds + ", " + TimeUtil.currentTimeMillis() + ", total:"+ oneSecondTotal + ", pass:"+ oneSecondPass + ", block:" + oneSecondBlock);if (seconds-- <= 0) {stop = true;}}System.exit(0);}}
}

创建WarmUpFlowDemo

代码如下(示例):

package com.example.springcloudalibabasentineldemo.demo;import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.util.TimeUtil;import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class WarmUpFlowDemo {private static final String KEY = "abc";private static AtomicInteger pass = new AtomicInteger();private static AtomicInteger block = new AtomicInteger();private static AtomicInteger total = new AtomicInteger();private static volatile boolean stop = false;private static final int threadCount = 100;private static int seconds = 60 + 40;public static void main(String[] args) throws Exception {initFlowRule();// trigger Sentinel internal initEntry entry = null;try {entry = SphU.entry(KEY);} catch (Exception e) {} finally {if (entry != null) {entry.exit();}}Thread timer = new Thread(new TimerTask());timer.setName("sentinel-timer-task");timer.start();//first make the system run on a very low conditionfor (int i = 0; i < 3; i++) {Thread t = new Thread(new WarmUpTask());t.setName("sentinel-warmup-task");t.start();}Thread.sleep(20000);/** Start more thread to simulate more qps. Since we use {@link RuleConstant.CONTROL_BEHAVIOR_WARM_UP} as* {@link FlowRule#controlBehavior}, real passed qps will increase to {@link FlowRule#count} in* {@link FlowRule#warmUpPeriodSec} seconds.*/for (int i = 0; i < threadCount; i++) {Thread t = new Thread(new RunTask());t.setName("sentinel-run-task");t.start();}}private static void initFlowRule() {List<FlowRule> rules = new ArrayList<FlowRule>();FlowRule rule1 = new FlowRule();rule1.setResource(KEY);rule1.setCount(20);rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);rule1.setLimitApp("default");rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);rule1.setWarmUpPeriodSec(10);rules.add(rule1);FlowRuleManager.loadRules(rules);}static class WarmUpTask implements Runnable {@Overridepublic void run() {while (!stop) {Entry entry = null;try {entry = SphU.entry(KEY);// token acquired, means passpass.addAndGet(1);} catch (BlockException e1) {block.incrementAndGet();} catch (Exception e2) {// biz exception} finally {total.incrementAndGet();if (entry != null) {entry.exit();}}Random random2 = new Random();try {TimeUnit.MILLISECONDS.sleep(random2.nextInt(2000));} catch (InterruptedException e) {// ignore}}}}static class RunTask implements Runnable {@Overridepublic void run() {while (!stop) {Entry entry = null;try {entry = SphU.entry(KEY);pass.addAndGet(1);} catch (BlockException e1) {block.incrementAndGet();} catch (Exception e2) {// biz exception} finally {total.incrementAndGet();if (entry != null) {entry.exit();}}Random random2 = new Random();try {TimeUnit.MILLISECONDS.sleep(random2.nextInt(50));} catch (InterruptedException e) {// ignore}}}}static class TimerTask implements Runnable {@Overridepublic void run() {long start = System.currentTimeMillis();System.out.println("begin to statistic!!!");long oldTotal = 0;long oldPass = 0;long oldBlock = 0;while (!stop) {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {}long globalTotal = total.get();long oneSecondTotal = globalTotal - oldTotal;oldTotal = globalTotal;long globalPass = pass.get();long oneSecondPass = globalPass - oldPass;oldPass = globalPass;long globalBlock = block.get();long oneSecondBlock = globalBlock - oldBlock;oldBlock = globalBlock;System.out.println(TimeUtil.currentTimeMillis() + ", total:" + oneSecondTotal+ ", pass:" + oneSecondPass+ ", block:" + oneSecondBlock);if (seconds-- <= 0) {stop = true;}}long cost = System.currentTimeMillis() - start;System.out.println("time cost: " + cost + " ms");System.out.println("total:" + total.get() + ", pass:" + pass.get()+ ", block:" + block.get());System.exit(0);}}
}

创建UserEntity

代码如下(示例):

package com.example.springcloudalibabasentineldemo.entity;import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;/*** @className: RedisController* @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
@Data
@TableName("t_user")
public class UserEntity implements Serializable {private static final long serialVersionUID = 1L;/*** */@TableIdprivate Integer id;/*** */private String username;/*** */private Integer age;}

创建RRException

代码如下(示例):

/*** Copyright (c) 2016-2019 人人开源 All rights reserved.** https://www.renren.io** 版权所有,侵权必究!*/package com.example.springcloudalibabasentineldemo.exception;/*** @description:自定义异常* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class RRException extends RuntimeException {private static final long serialVersionUID = 1L;private String msg;private int code = 500;public RRException(String msg) {super(msg);this.msg = msg;}public RRException(String msg, Throwable e) {super(msg, e);this.msg = msg;}public RRException(String msg, int code) {super(msg);this.msg = msg;this.code = code;}public RRException(String msg, int code, Throwable e) {super(msg, e);this.msg = msg;this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}}

创建OrderFeignService

代码如下(示例):

package com.example.springcloudalibabasentineldemo.feign;import com.example.springcloudalibabasentineldemo.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
@FeignClient(value = "open-feign",path = "/feign")
public interface OrderFeignService {@RequestMapping("/getNacosConfigure")public String getNacosConfigure();
}

创建CommonBlockHandler

代码如下(示例):

package com.example.springcloudalibabasentineldemo.sentinel;import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.springcloudalibabasentineldemo.utils.R;
import java.util.Map;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class CommonBlockHandler {/*** 注意: 必须为 static 函数   多个方法之间方法名不能一样* @param exception* @return*/public static R handleException(Map<String, Object> params, BlockException exception){return R.error(-1,"===被限流啦==="+exception);}public String getNacosConfigure() {return "===被限流啦===";}public static R handleException2(Integer id, BlockException exception){return R.error(-1,"===被限流啦==="+exception);}public static String handleException3(BlockException exception){return "===被限流啦==="+exception;}
}

创建CommonFallback

代码如下(示例):

package com.example.springcloudalibabasentineldemo.sentinel;import com.example.springcloudalibabasentineldemo.utils.R;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class CommonFallback {/*** 注意: 必须为 static 函数* @param e* @return*/public static R fallback(Integer id, Throwable e){return R.error(-2,"===被异常降级啦==="+e.getMessage());}public String getNacosConfigure() {return "===被异常降级啦===";}
}

创建MyBlockExceptionHandler

代码如下(示例):

package com.example.springcloudalibabasentineldemo.sentinel;import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.example.springcloudalibabasentineldemo.utils.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
@Slf4j
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {log.info("BlockExceptionHandler BlockException================"+e.getRule());R r = null;if (e instanceof FlowException) {r = R.error(100,"接口限流了");} else if (e instanceof DegradeException) {r = R.error(101,"服务降级了");} else if (e instanceof ParamFlowException) {r = R.error(102,"热点参数限流了");} else if (e instanceof SystemBlockException) {r = R.error(103,"触发系统保护规则了");} else if (e instanceof AuthorityException) {r = R.error(104,"授权规则不通过");}//返回json数据response.setStatus(500);response.setCharacterEncoding("utf-8");response.setContentType(MediaType.APPLICATION_JSON_VALUE);new ObjectMapper().writeValue(response.getWriter(), r);}
}

创建MyRequestOriginParser

代码如下(示例):

package com.example.springcloudalibabasentineldemo.sentinel;import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import javax.servlet.http.HttpServletRequest;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
//@Component
public class MyRequestOriginParser implements RequestOriginParser {/*** 通过request获取来源标识,交给授权规则进行匹配* @param request* @return*/@Overridepublic String parseOrigin(HttpServletRequest request) {// 标识字段名称可以自定义String origin = request.getParameter("serviceName");
//        if (StringUtil.isBlank(origin)){
//            throw new IllegalArgumentException("serviceName参数未指定");
//        }return origin;}
}

创建MyUrlBlockHandler

代码如下(示例):

package com.example.springcloudalibabasentineldemo.sentinel;import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.example.springcloudalibabasentineldemo.utils.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
@Slf4j
public class MyUrlBlockHandler implements UrlBlockHandler {@Overridepublic void blocked(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException {log.info("UrlBlockHandler BlockException================"+e.getRule());R r = null;if (e instanceof FlowException) {r = R.error(100,"接口限流了");} else if (e instanceof DegradeException) {r = R.error(101,"服务降级了");} else if (e instanceof ParamFlowException) {r = R.error(102,"热点参数限流了");} else if (e instanceof SystemBlockException) {r = R.error(103,"触发系统保护规则了");} else if (e instanceof AuthorityException) {r = R.error(104,"授权规则不通过");}//返回json数据response.setStatus(500);response.setCharacterEncoding("utf-8");response.setContentType(MediaType.APPLICATION_JSON_VALUE);new ObjectMapper().writeValue(response.getWriter(), r);}
}

创建UserServiceImpl

代码如下(示例):

package com.example.springcloudalibabasentineldemo.service.impl;import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springcloudalibabasentineldemo.dao.UserDao;
import com.example.springcloudalibabasentineldemo.entity.UserEntity;
import com.example.springcloudalibabasentineldemo.service.UserService;
import com.example.springcloudalibabasentineldemo.utils.PageUtils;
import com.example.springcloudalibabasentineldemo.utils.Query;
import org.springframework.stereotype.Service;
import java.util.Map;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {@Overridepublic PageUtils queryPage(Map<String, Object> params) {IPage<UserEntity> page = this.page(new Query<UserEntity>().getPage(params),new QueryWrapper<UserEntity>());return new PageUtils(page);}@Override@SentinelResource(value = "getUser")  //aoppublic UserEntity getUser(int id){UserEntity user = baseMapper.selectById(id);return user;}public UserEntity handleException(int id, BlockException ex) {UserEntity userEntity = new UserEntity();userEntity.setUsername("===被限流降级啦===");return userEntity;}}

创建UserService

代码如下(示例):

package com.example.springcloudalibabasentineldemo.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.example.springcloudalibabasentineldemo.entity.UserEntity;
import com.example.springcloudalibabasentineldemo.utils.PageUtils;
import java.util.Map;/*** @description:* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public interface UserService extends IService<UserEntity> {PageUtils queryPage(Map<String, Object> params);UserEntity getUser(int id);
}

创建Constant

代码如下(示例):

/*** Copyright (c) 2016-2019 人人开源 All rights reserved.** https://www.renren.io** 版权所有,侵权必究!*/package com.example.springcloudalibabasentineldemo.utils;/*** @description:常量* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class Constant {/** 超级管理员ID */public static final int SUPER_ADMIN = 1;/*** 当前页码*/public static final String PAGE = "page";/*** 每页显示记录数*/public static final String LIMIT = "limit";/*** 排序字段*/public static final String ORDER_FIELD = "sidx";/*** 排序方式*/public static final String ORDER = "order";/***  升序*/public static final String ASC = "asc";/*** 菜单类型* * @author chenshun* @email sunlightcs@gmail.com* @date 2016年11月15日 下午1:24:29*/public enum MenuType {/*** 目录*/CATALOG(0),/*** 菜单*/MENU(1),/*** 按钮*/BUTTON(2);private int value;MenuType(int value) {this.value = value;}public int getValue() {return value;}}/*** 定时任务状态* * @author chenshun* @email sunlightcs@gmail.com* @date 2016年12月3日 上午12:07:22*/public enum ScheduleStatus {/*** 正常*/NORMAL(0),/*** 暂停*/PAUSE(1);private int value;ScheduleStatus(int value) {this.value = value;}public int getValue() {return value;}}/*** 云服务商*/public enum CloudService {/*** 七牛云*/QINIU(1),/*** 阿里云*/ALIYUN(2),/*** 腾讯云*/QCLOUD(3);private int value;CloudService(int value) {this.value = value;}public int getValue() {return value;}}}

创建PageUtils

代码如下(示例):

/*** Copyright (c) 2016-2019 人人开源 All rights reserved.** https://www.renren.io** 版权所有,侵权必究!*/package com.example.springcloudalibabasentineldemo.utils;import com.baomidou.mybatisplus.core.metadata.IPage;
import java.io.Serializable;
import java.util.List;/*** @description:分页工具类* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class PageUtils implements Serializable {private static final long serialVersionUID = 1L;/*** 总记录数*/private int totalCount;/*** 每页记录数*/private int pageSize;/*** 总页数*/private int totalPage;/*** 当前页数*/private int currPage;/*** 列表数据*/private List<?> list;/*** 分页* @param list        列表数据* @param totalCount  总记录数* @param pageSize    每页记录数* @param currPage    当前页数*/public PageUtils(List<?> list, int totalCount, int pageSize, int currPage) {this.list = list;this.totalCount = totalCount;this.pageSize = pageSize;this.currPage = currPage;this.totalPage = (int)Math.ceil((double)totalCount/pageSize);}/*** 分页*/public PageUtils(IPage<?> page) {this.list = page.getRecords();this.totalCount = (int)page.getTotal();this.pageSize = (int)page.getSize();this.currPage = (int)page.getCurrent();this.totalPage = (int)page.getPages();}public int getTotalCount() {return totalCount;}public void setTotalCount(int totalCount) {this.totalCount = totalCount;}public int getPageSize() {return pageSize;}public void setPageSize(int pageSize) {this.pageSize = pageSize;}public int getTotalPage() {return totalPage;}public void setTotalPage(int totalPage) {this.totalPage = totalPage;}public int getCurrPage() {return currPage;}public void setCurrPage(int currPage) {this.currPage = currPage;}public List<?> getList() {return list;}public void setList(List<?> list) {this.list = list;}}

创建Query

代码如下(示例):

/*** Copyright (c) 2016-2019 人人开源 All rights reserved.** https://www.renren.io** 版权所有,侵权必究!*/package com.example.springcloudalibabasentineldemo.utils;import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.springcloudalibabasentineldemo.xss.SQLFilter;
import org.apache.commons.lang.StringUtils;
import java.util.Map;/*** @description:查询参数* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class Query<T> {public IPage<T> getPage(Map<String, Object> params) {return this.getPage(params, null, false);}public IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {//分页参数long curPage = 1;long limit = 10;if(params.get(Constant.PAGE) != null){curPage = Long.parseLong((String)params.get(Constant.PAGE));}if(params.get(Constant.LIMIT) != null){limit = Long.parseLong((String)params.get(Constant.LIMIT));}//分页对象Page<T> page = new Page<>(curPage, limit);//分页参数params.put(Constant.PAGE, page);//排序字段//防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险)String orderField = SQLFilter.sqlInject((String)params.get(Constant.ORDER_FIELD));String order = (String)params.get(Constant.ORDER);//前端字段排序if(StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)){if(Constant.ASC.equalsIgnoreCase(order)) {return  page.addOrder(OrderItem.asc(orderField));}else {return page.addOrder(OrderItem.desc(orderField));}}//没有排序字段,则不排序if(StringUtils.isBlank(defaultOrderField)){return page;}//默认排序if(isAsc) {page.addOrder(OrderItem.asc(defaultOrderField));}else {page.addOrder(OrderItem.desc(defaultOrderField));}return page;}
}

创建R

代码如下(示例):

/*** Copyright (c) 2016-2019 人人开源 All rights reserved.** https://www.renren.io** 版权所有,侵权必究!*/package com.example.springcloudalibabasentineldemo.utils;import org.apache.http.HttpStatus;
import java.util.HashMap;
import java.util.Map;/*** @description:返回数据* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class R extends HashMap<String, Object> {private static final long serialVersionUID = 1L;public R() {put("code", 0);put("msg", "success");}public static R error() {return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");}public static R error(String msg) {return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);}public static R error(int code, String msg) {R r = new R();r.put("code", code);r.put("msg", msg);return r;}public static R ok(String msg) {R r = new R();r.put("msg", msg);return r;}public static R ok(Map<String, Object> map) {R r = new R();r.putAll(map);return r;}public static R ok() {return new R();}public R put(String key, Object value) {super.put(key, value);return this;}
}

创建HTMLFilter

代码如下(示例):

package com.example.springcloudalibabasentineldemo.xss;import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/**** HTML filtering utility for protecting against XSS (Cross Site Scripting).** This code is licensed LGPLv3** This code is a Java port of the original work in PHP by Cal Hendersen.* http://code.iamcal.com/php/lib_filter/** The trickiest part of the translation was handling the differences in regex handling* between PHP and Java.  These resources were helpful in the process:** http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html* http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php* http://www.regular-expressions.info/modifiers.html** A note on naming conventions: instance variables are prefixed with a "v"; global* constants are in all caps.** Sample use:* String input = ...* String clean = new HTMLFilter().filter( input );** The class is not thread safe. Create a new instance if in doubt.** If you find bugs or have suggestions on improvement (especially regarding* performance), please contact us.  The latest version of this* source, and our contact details, can be found at http://xss-html-filter.sf.net** @author Joseph O'Connell* @author Cal Hendersen* @author Michael Semb Wever*/
public final class HTMLFilter {/** regex flag union representing /si modifiers in php **/private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);private static final Pattern P_END_ARROW = Pattern.compile("^>");private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");private static final Pattern P_AMP = Pattern.compile("&");private static final Pattern P_QUOTE = Pattern.compile("<");private static final Pattern P_LEFT_ARROW = Pattern.compile("<");private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");// @xxx could grow large... maybe use sesat's ReferenceMapprivate static final ConcurrentMap<String,Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<String, Pattern>();private static final ConcurrentMap<String,Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<String, Pattern>();/** set of allowed html elements, along with allowed attributes for each element **/private final Map<String, List<String>> vAllowed;/** counts of open tags for each (allowable) html element **/private final Map<String, Integer> vTagCounts = new HashMap<String, Integer>();/** html elements which must always be self-closing (e.g. "<img />") **/private final String[] vSelfClosingTags;/** html elements which must always have separate opening and closing tags (e.g. "<b></b>") **/private final String[] vNeedClosingTags;/** set of disallowed html elements **/private final String[] vDisallowed;/** attributes which should be checked for valid protocols **/private final String[] vProtocolAtts;/** allowed protocols **/private final String[] vAllowedProtocols;/** tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") **/private final String[] vRemoveBlanks;/** entities allowed within html markup **/private final String[] vAllowedEntities;/** flag determining whether comments are allowed in input String. */private final boolean stripComment;private final boolean encodeQuotes;private boolean vDebug = false;/*** flag determining whether to try to make tags when presented with "unbalanced"* angle brackets (e.g. "<b text </b>" becomes "<b> text </b>").  If set to false,* unbalanced angle brackets will be html escaped.*/private final boolean alwaysMakeTags;/** Default constructor.**/public HTMLFilter() {vAllowed = new HashMap<>();final ArrayList<String> a_atts = new ArrayList<String>();a_atts.add("href");a_atts.add("target");vAllowed.put("a", a_atts);final ArrayList<String> img_atts = new ArrayList<String>();img_atts.add("src");img_atts.add("width");img_atts.add("height");img_atts.add("alt");vAllowed.put("img", img_atts);final ArrayList<String> no_atts = new ArrayList<String>();vAllowed.put("b", no_atts);vAllowed.put("strong", no_atts);vAllowed.put("i", no_atts);vAllowed.put("em", no_atts);vSelfClosingTags = new String[]{"img"};vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"};vDisallowed = new String[]{};vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp.vProtocolAtts = new String[]{"src", "href"};vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"};vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};stripComment = true;encodeQuotes = true;alwaysMakeTags = true;}/** Set debug flag to true. Otherwise use default settings. See the default constructor.** @param debug turn debug on with a true argument*/public HTMLFilter(final boolean debug) {this();vDebug = debug;}/** Map-parameter configurable constructor.** @param conf map containing configuration. keys match field names.*/public HTMLFilter(final Map<String,Object> conf) {assert conf.containsKey("vAllowed") : "configuration requires vAllowed";assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");vDisallowed = (String[]) conf.get("vDisallowed");vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");vProtocolAtts = (String[]) conf.get("vProtocolAtts");vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");vAllowedEntities = (String[]) conf.get("vAllowedEntities");stripComment =  conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;}private void reset() {vTagCounts.clear();}private void debug(final String msg) {if (vDebug) {Logger.getAnonymousLogger().info(msg);}}//---------------------------------------------------------------// my versions of some PHP library functionspublic static String chr(final int decimal) {return String.valueOf((char) decimal);}public static String htmlSpecialChars(final String s) {String result = s;result = regexReplace(P_AMP, "&amp;", result);result = regexReplace(P_QUOTE, "&quot;", result);result = regexReplace(P_LEFT_ARROW, "&lt;", result);result = regexReplace(P_RIGHT_ARROW, "&gt;", result);return result;}//---------------------------------------------------------------/*** given a user submitted input String, filter out any invalid or restricted* html.** @param input text (i.e. submitted by a user) than may contain html* @return "clean" version of input, with only valid, whitelisted html elements allowed*/public String filter(final String input) {reset();String s = input;debug("************************************************");debug("              INPUT: " + input);s = escapeComments(s);debug("     escapeComments: " + s);s = balanceHTML(s);debug("        balanceHTML: " + s);s = checkTags(s);debug("          checkTags: " + s);s = processRemoveBlanks(s);debug("processRemoveBlanks: " + s);s = validateEntities(s);debug("    validateEntites: " + s);debug("************************************************\n\n");return s;}public boolean isAlwaysMakeTags(){return alwaysMakeTags;}public boolean isStripComments(){return stripComment;}private String escapeComments(final String s) {final Matcher m = P_COMMENTS.matcher(s);final StringBuffer buf = new StringBuffer();if (m.find()) {final String match = m.group(1); //(.*?)m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));}m.appendTail(buf);return buf.toString();}private String balanceHTML(String s) {if (alwaysMakeTags) {//// try and form html//s = regexReplace(P_END_ARROW, "", s);s = regexReplace(P_BODY_TO_END, "<$1>", s);s = regexReplace(P_XML_CONTENT, "$1<$2", s);} else {//// escape stray brackets//s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);//// the last regexp causes '<>' entities to appear// (we need to do a lookahead assertion so that the last bracket can// be used in the next pass of the regexp)//s = regexReplace(P_BOTH_ARROWS, "", s);}return s;}private String checkTags(String s) {Matcher m = P_TAGS.matcher(s);final StringBuffer buf = new StringBuffer();while (m.find()) {String replaceStr = m.group(1);replaceStr = processTag(replaceStr);m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));}m.appendTail(buf);s = buf.toString();// these get tallied in processTag// (remember to reset before subsequent calls to filter method)for (String key : vTagCounts.keySet()) {for (int ii = 0; ii < vTagCounts.get(key); ii++) {s += "</" + key + ">";}}return s;}private String processRemoveBlanks(final String s) {String result = s;for (String tag : vRemoveBlanks) {if(!P_REMOVE_PAIR_BLANKS.containsKey(tag)){P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));}result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);if(!P_REMOVE_SELF_BLANKS.containsKey(tag)){P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));}result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);}return result;}private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) {Matcher m = regex_pattern.matcher(s);return m.replaceAll(replacement);}private String processTag(final String s) {// ending tagsMatcher m = P_END_TAG.matcher(s);if (m.find()) {final String name = m.group(1).toLowerCase();if (allowed(name)) {if (!inArray(name, vSelfClosingTags)) {if (vTagCounts.containsKey(name)) {vTagCounts.put(name, vTagCounts.get(name) - 1);return "</" + name + ">";}}}}// starting tagsm = P_START_TAG.matcher(s);if (m.find()) {final String name = m.group(1).toLowerCase();final String body = m.group(2);String ending = m.group(3);//debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );if (allowed(name)) {String params = "";final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);final List<String> paramNames = new ArrayList<String>();final List<String> paramValues = new ArrayList<String>();while (m2.find()) {paramNames.add(m2.group(1)); //([a-z0-9]+)paramValues.add(m2.group(3)); //(.*?)}while (m3.find()) {paramNames.add(m3.group(1)); //([a-z0-9]+)paramValues.add(m3.group(3)); //([^\"\\s']+)}String paramName, paramValue;for (int ii = 0; ii < paramNames.size(); ii++) {paramName = paramNames.get(ii).toLowerCase();paramValue = paramValues.get(ii);//          debug( "paramName='" + paramName + "'" );
//          debug( "paramValue='" + paramValue + "'" );
//          debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );if (allowedAttribute(name, paramName)) {if (inArray(paramName, vProtocolAtts)) {paramValue = processParamProtocol(paramValue);}params += " " + paramName + "=\"" + paramValue + "\"";}}if (inArray(name, vSelfClosingTags)) {ending = " /";}if (inArray(name, vNeedClosingTags)) {ending = "";}if (ending == null || ending.length() < 1) {if (vTagCounts.containsKey(name)) {vTagCounts.put(name, vTagCounts.get(name) + 1);} else {vTagCounts.put(name, 1);}} else {ending = " /";}return "<" + name + params + ending + ">";} else {return "";}}// commentsm = P_COMMENT.matcher(s);if (!stripComment && m.find()) {return  "<" + m.group() + ">";}return "";}private String processParamProtocol(String s) {s = decodeEntities(s);final Matcher m = P_PROTOCOL.matcher(s);if (m.find()) {final String protocol = m.group(1);if (!inArray(protocol, vAllowedProtocols)) {// bad protocol, turn into local anchor link insteads = "#" + s.substring(protocol.length() + 1, s.length());if (s.startsWith("#//")) {s = "#" + s.substring(3, s.length());}}}return s;}private String decodeEntities(String s) {StringBuffer buf = new StringBuffer();Matcher m = P_ENTITY.matcher(s);while (m.find()) {final String match = m.group(1);final int decimal = Integer.decode(match).intValue();m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));}m.appendTail(buf);s = buf.toString();buf = new StringBuffer();m = P_ENTITY_UNICODE.matcher(s);while (m.find()) {final String match = m.group(1);final int decimal = Integer.valueOf(match, 16).intValue();m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));}m.appendTail(buf);s = buf.toString();buf = new StringBuffer();m = P_ENCODE.matcher(s);while (m.find()) {final String match = m.group(1);final int decimal = Integer.valueOf(match, 16).intValue();m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));}m.appendTail(buf);s = buf.toString();s = validateEntities(s);return s;}private String validateEntities(final String s) {StringBuffer buf = new StringBuffer();// validate entities throughout the stringMatcher m = P_VALID_ENTITIES.matcher(s);while (m.find()) {final String one = m.group(1); //([^&;]*)final String two = m.group(2); //(?=(;|&|$))m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));}m.appendTail(buf);return encodeQuotes(buf.toString());}private String encodeQuotes(final String s){if(encodeQuotes){StringBuffer buf = new StringBuffer();Matcher m = P_VALID_QUOTES.matcher(s);while (m.find()) {final String one = m.group(1); //(>|^)final String two = m.group(2); //([^<]+?)final String three = m.group(3); //(<|$)m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, "&quot;", two) + three));}m.appendTail(buf);return buf.toString();}else{return s;}}private String checkEntity(final String preamble, final String term) {return ";".equals(term) && isValidEntity(preamble)? '&' + preamble: "&amp;" + preamble;}private boolean isValidEntity(final String entity) {return inArray(entity, vAllowedEntities);}private static boolean inArray(final String s, final String[] array) {for (String item : array) {if (item != null && item.equals(s)) {return true;}}return false;}private boolean allowed(final String name) {return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);}private boolean allowedAttribute(final String name, final String paramName) {return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));}
}

创建SQLFilter

代码如下(示例):

/*** Copyright (c) 2016-2019 人人开源 All rights reserved.** https://www.renren.io** 版权所有,侵权必究!*/package com.example.springcloudalibabasentineldemo.xss;import com.example.springcloudalibabasentineldemo.exception.RRException;
import org.apache.commons.lang.StringUtils;/*** @description:SQL过滤* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class SQLFilter {/*** SQL注入过滤* @param str  待验证的字符串*/public static String sqlInject(String str){if(StringUtils.isBlank(str)){return null;}//去掉'|"|;|\字符str = StringUtils.replace(str, "'", "");str = StringUtils.replace(str, "\"", "");str = StringUtils.replace(str, ";", "");str = StringUtils.replace(str, "\\", "");//转换成小写str = str.toLowerCase();//非法字符String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop"};//判断是否包含非法字符for(String keyword : keywords){if(str.indexOf(keyword) != -1){throw new RRException("包含非法字符");}}return str;}
}

创建XssFilter

代码如下(示例):

/*** Copyright (c) 2016-2019 人人开源 All rights reserved.** https://www.renren.io** 版权所有,侵权必究!*/package com.example.springcloudalibabasentineldemo.xss;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;/*** @description:XSS过滤* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class XssFilter implements Filter {@Overridepublic void init(FilterConfig config) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);chain.doFilter(xssRequest, response);}@Overridepublic void destroy() {}}

创建XssHttpServletRequestWrapper

代码如下(示例):

/*** Copyright (c) 2016-2019 人人开源 All rights reserved.** https://www.renren.io** 版权所有,侵权必究!*/package com.example.springcloudalibabasentineldemo.xss;import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;/*** @description:XSS过滤处理* @author: zhiweiLiao* @date: 2022-09-13 15:28*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {//没被包装过的HttpServletRequest(特殊场景,需要自己过滤)HttpServletRequest orgRequest;//html过滤private final static HTMLFilter htmlFilter = new HTMLFilter();public XssHttpServletRequestWrapper(HttpServletRequest request) {super(request);orgRequest = request;}@Overridepublic ServletInputStream getInputStream() throws IOException {//非json类型,直接返回if(!MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(super.getHeader(HttpHeaders.CONTENT_TYPE))){return super.getInputStream();}//为空,直接返回String json = IOUtils.toString(super.getInputStream(), "utf-8");if (StringUtils.isBlank(json)) {return super.getInputStream();}//xss过滤json = xssEncode(json);final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8"));return new ServletInputStream() {@Overridepublic boolean isFinished() {return true;}@Overridepublic boolean isReady() {return true;}@Overridepublic void setReadListener(ReadListener readListener) {}@Overridepublic int read() throws IOException {return bis.read();}};}@Overridepublic String getParameter(String name) {String value = super.getParameter(xssEncode(name));if (StringUtils.isNotBlank(value)) {value = xssEncode(value);}return value;}@Overridepublic String[] getParameterValues(String name) {String[] parameters = super.getParameterValues(name);if (parameters == null || parameters.length == 0) {return null;}for (int i = 0; i < parameters.length; i++) {parameters[i] = xssEncode(parameters[i]);}return parameters;}@Overridepublic Map<String,String[]> getParameterMap() {Map<String,String[]> map = new LinkedHashMap<>();Map<String,String[]> parameters = super.getParameterMap();for (String key : parameters.keySet()) {String[] values = parameters.get(key);for (int i = 0; i < values.length; i++) {values[i] = xssEncode(values[i]);}map.put(key, values);}return map;}@Overridepublic String getHeader(String name) {String value = super.getHeader(xssEncode(name));if (StringUtils.isNotBlank(value)) {value = xssEncode(value);}return value;}private String xssEncode(String input) {return htmlFilter.filter(input);}/*** 获取最原始的request*/public HttpServletRequest getOrgRequest() {return orgRequest;}/*** 获取最原始的request*/public static HttpServletRequest getOrgRequest(HttpServletRequest request) {if (request instanceof XssHttpServletRequestWrapper) {return ((XssHttpServletRequestWrapper) request).getOrgRequest();}return request;}}

创建UserDao.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.springcloudalibabasentineldemo.dao.UserDao"><!-- 可根据自己的需求,是否要使用 --><resultMap type="com.example.springcloudalibabasentineldemo.entity.UserEntity" id="userMap"><result property="id" column="id"/><result property="username" column="username"/><result property="age" column="age"/></resultMap></mapper>

文章关联地址:https://liaozhiwei.blog.csdn.net/article/details/127160493

【java_wxid项目】【第十六章】【Spring Cloud Alibaba Sentinel集成】相关推荐

  1. 《深入理解 Spring Cloud 与微服务构建》第十六章 Spring Boot Security 详解

    <深入理解 Spring Cloud 与微服务构建>第十六章 Spring Boot Security 详解 文章目录 <深入理解 Spring Cloud 与微服务构建>第十 ...

  2. Spring Cloud Alibaba —— Sentinel 详细使用

    导航 引言 一.Sentinel的两个基本概念 二.流控规则 2.1 基本选项 2.2 高级选项 三.熔断(降级)规则 四.热点规则 五.授权规则(了解) 六.系统规则(了解) 七.自定义异常返回 八 ...

  3. 【SpringCloud】Spring cloud Alibaba Sentinel 降级规则

    文章目录 1.概述 2.服务降级 2.1 RT 2.2 异常比例 2.3 异常数 1.概述 本章是接着上一章讲解:[SpringCloud]Spring cloud Alibaba Sentinel ...

  4. Spring Cloud Alibaba | Sentinel: 服务限流高级篇

    Spring Cloud Alibaba | Sentinel: 服务限流高级篇 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如无特殊说明 ...

  5. spring cloud Alibaba Sentinel中文文档

    spring cloud Alibaba Sentinel中文文档 github中的中文文档:https://github.com/alibaba/Sentinel/wiki/介绍

  6. Spring Cloud Alibaba - Sentinel入门案例(四)(热点规则 )

    Spring Cloud Alibaba - Sentinel入门案例(四)(热点规则 ) 回溯 什么是Sentinel? 正文 环境准备 简单使用 复杂使用 注意事项 回溯 什么是Sentinel? ...

  7. spring cloud alibaba sentinel 学习

    sentinel 学习 介绍(官方文档) 流量控制设计理念 熔断降级 Hystrix Sentinel 系统自适应保护 spring cloud alibaba sentinel sentinel.d ...

  8. (十六)spring cloud微服务分布式云架构-集成项目简介

    Spring Cloud集成项目有很多,下面我们列举一下和Spring Cloud相关的优秀项目,我们的企业架构中用到了很多的优秀项目,说白了,也是站在巨人的肩膀上去整合的.在学习Spring Clo ...

  9. 第十二章 Spring Cloud Config 统一配置中心详解

    目录 一.配置问题分析及解决方案 1.问题分析 2.解决方案 二.Spring Cloud Config 介绍 1.Spring Cloud Config特性 2.Spring Cloud Confi ...

最新文章

  1. 为uThreadPool增加线程池等待功能
  2. datagridview新增列在最后_数说|科创板2020:募资额2200+亿超主板列A股第一,科技“千元股”、“市值王”长成...
  3. express get和post数据
  4. Docker 部署 postgresql 与 pgadmin4
  5. 自己构造公共程序(3)--DataGrid小方法
  6. 如何完全卸载oracle和删除oracle在注册表中的注册信息
  7. Compiling XORP v1.2 in Debian 3.1
  8. mysql多表连接的几种写法
  9. 通过寄生组合式继承创建js的异常类
  10. C#使用DevExpress中的chartcontrol
  11. nanohttpd文件服务器,NanoHttpd 轻量级的 HTTP 服务器
  12. STM32F103(1)
  13. npm安装electron报RequestError: socket hang up错误解决方法
  14. java面向对象(封装、重载、构造、继承)
  15. 蓝桥杯第五届省赛模拟试题--“模拟智能灌溉系统”
  16. 上、下、左、右键的ASCII值
  17. VxWorks的移植和BSP定制过程
  18. python对RabbitMQ的简单使用
  19. Charles安装web端证书以及基本设置
  20. 数据恢复软件哪个好?强推easyrecovery!

热门文章

  1. 出口IP和本机IP的区别?
  2. 创投日报:10月16日收录投融资项目11起
  3. ESP32/ESP8266系列之AMG8833热成像
  4. 爱情公寓4不断刷新记录 大数据成就网络神剧
  5. JPEG压缩基本原理
  6. 八名新人杀入十大最牛散户榜 刘元生卫冕
  7. python fixture_使用Fixture
  8. pytest进阶之fixture函数
  9. PIL imagefont文字加边框
  10. Sql排序(当有Null值存在时,将它排在最后面)