• SpringBoot自定义starter


    目录

     自定义starter

    统计独立IP访问次数

    使用自定义starter

    设置拦截器

     开启yml提示功能


     自定义starter

    统计独立IP访问次数

    需求分析:

    1、数据记录位置:Map/Redis

    2|功能触发位置:每次web请求(拦截器

    • 步骤1:降低难度,主动调用,仅统计单一操作访问次数(例如查询)
    • 步骤2:开发拦截器

    3、业务参数(配置项)

    1. 输出频度:默认10秒
    2. 数据特征:累计数据/阶段数据,默认累计数据
    3. 输出格式:详细模式(显示ip和次数)/极简模式(只显示ip)

    创建一个模块

    pom.xml中

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <groupId>com.kcgroupId>
    6. <artifactId>springboot_ipcount_starterartifactId>
    7. <version>0.0.1-SNAPSHOTversion>
    8. <properties>
    9. <java.version>1.8java.version>
    10. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    11. <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
    12. <spring-boot.version>2.4.1spring-boot.version>
    13. properties>
    14. <dependencies>
    15. <dependency>
    16. <groupId>org.springframework.bootgroupId>
    17. <artifactId>spring-boot-starter-webartifactId>
    18. dependency>
    19. dependencies>
    20. <dependencyManagement>
    21. <dependencies>
    22. <dependency>
    23. <groupId>org.springframework.bootgroupId>
    24. <artifactId>spring-boot-dependenciesartifactId>
    25. <version>${spring-boot.version}version>
    26. <type>pomtype>
    27. <scope>importscope>
    28. dependency>
    29. dependencies>
    30. dependencyManagement>
    31. project>

    写入主要的类

    1. package com.kc.service;
    2. import com.kc.properties.IpProperties;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.scheduling.annotation.Scheduled;
    5. import javax.servlet.http.HttpServletRequest;
    6. import java.util.HashMap;
    7. import java.util.Map;
    8. public class IpCountService {
    9. private HashMap ipCountMap=new HashMap<>();
    10. //当前的request对象的注入工作由使用当前starter的工程提供自动装配
    11. @Autowired
    12. private HttpServletRequest httpServletRequest;
    13. public void count(){
    14. //每次调用当前操作,就记录当前访问的IP,然后累加访问次数
    15. //1、获取当前操作的ip地址
    16. String ip=httpServletRequest.getRemoteAddr();
    17. //2、根据ip地址从Map取值,并递增
    18. Integer value = ipCountMap.get(ip);
    19. //判断当前ip否存在
    20. if(value==null){
    21. ipCountMap.put(ip, 1);
    22. }else {
    23. ipCountMap.put(ip, value+1);
    24. }
    25. }
    26. //注入配置类
    27. @Autowired
    28. private IpProperties ipProperties;
    29. //打印
    30. @Scheduled(cron = "0/2 * * * * ?") //2秒执行一次
    31. public void show(){
    32. System.out.println(" IP访问监控 ");
    33. if (ipProperties.getModel().equals(IpProperties.LogModel.DETAIL.getValue())) {
    34. System.out.println("+-----ip-address-----+--num--+");
    35. //同时获取key和value
    36. for (Map.Entry entry : ipCountMap.entrySet()) {
    37. String key = entry.getKey();
    38. Integer value = entry.getValue();
    39. //format格式输出,%18s是给字符串占18位和%5d是给数字占5位符
    40. System.out.println(String.format("|%18s |%5d |", key,value));
    41. }
    42. System.out.println("+--------------------+-------+");
    43. }else if (ipProperties.getModel().equals(IpProperties.LogModel.SIMPLE.getValue())){
    44. System.out.println("+-----ip-address-----+");
    45. //同时获取key和value
    46. for (String key : ipCountMap.keySet()) {
    47. System.out.println(String.format("|%18s |", key));
    48. }
    49. System.out.println("+--------------------+-------+");
    50. }
    51. //是否清除数据
    52. if (ipProperties.getCycleReset()){
    53. ipCountMap.clear();
    54. }
    55. }
    56. }

    配置类下

    1. package com.kc.properties;
    2. import org.springframework.boot.context.properties.ConfigurationProperties;
    3. import org.springframework.stereotype.Component;
    4. @Component
    5. @ConfigurationProperties(prefix = "ip")
    6. public class IpProperties {
    7. /**
    8. * 日志显示周期
    9. */
    10. private long cycle=5L;
    11. /**
    12. * 是否重置周期数据
    13. */
    14. private boolean cycleReset=false;
    15. /**
    16. * 日志输出模式 detail :详细模式 simple 极简模式
    17. */
    18. private String model=LogModel.DETAIL.value;
    19. /**
    20. * 使用枚举来存储
    21. */
    22. public enum LogModel{
    23. DETAIL("detail"),
    24. SIMPLE("simple");
    25. private String value;
    26. LogModel(String value) {
    27. this.value=value;
    28. }
    29. public String getValue() {
    30. return value;
    31. }
    32. }
    33. public boolean getCycleReset() {
    34. return cycleReset;
    35. }
    36. public void setCycleReset(boolean cycleReset) {
    37. this.cycleReset = cycleReset;
    38. }
    39. public String getModel() {
    40. return model;
    41. }
    42. public void setModel(String model) {
    43. this.model = model;
    44. }
    45. }

    自动配置信息类

    1. package com.kc.autoConfig;
    2. import com.kc.service.IpCountService;
    3. import org.springframework.context.annotation.Import;
    4. import org.springframework.scheduling.annotation.EnableScheduling;
    5. @EnableScheduling//开启定义任务调度
    6. @Import(IpCountService.class)
    7. public class IpAutoConfiguration {
    8. }

    在资源中新建

    META-INF下的spring.factories

    1. #要自动配置的类写在这
    2. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    3. com.kc.autoConfig.IpAutoConfiguration

    这个自定义starter就完成了

    使用自定义starter

     导入对应的坐标即可

     注入和使用对应的方法

    设置拦截器

    1. package com.kc.interceptor;
    2. import com.kc.service.IpCountService;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.web.servlet.HandlerInterceptor;
    5. import javax.servlet.http.HttpServletRequest;
    6. import javax.servlet.http.HttpServletResponse;
    7. public class IpCountInterceptor implements HandlerInterceptor {
    8. @Autowired
    9. private IpCountService ipCountService;
    10. @Override
    11. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    12. ipCountService.count();
    13. ipCountService.show();
    14. return true;
    15. }
    16. }

    为了能被springmvc识别还得写个配置

    1. package com.kc.interceptor;
    2. import org.springframework.context.annotation.Bean;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    6. @Configuration(proxyBeanMethods = true)//保证bean创建的对象唯一
    7. //告诉springMVC拦截器的位置
    8. public class SpringMvcConfig implements WebMvcConfigurer {
    9. @Override
    10. //添加一个拦截器
    11. public void addInterceptors(InterceptorRegistry registry) {
    12. registry.addInterceptor(ipCountInterceptor()).addPathPatterns("/**");//"/**表示所有请求"
    13. }
    14. @Bean
    15. public IpCountInterceptor ipCountInterceptor(){
    16. return new IpCountInterceptor();
    17. }
    18. }

    运行之后 ,访问任意的功能都可以计数

     开启yml提示功能

    在自定义starter中pom.xml中加入,mavenclean和install之后可以删除此坐标

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-configuration-processorartifactId>
    4. dependency>

    然后在maven中点击clean和install重新编译

     就会多出一个json文件

    在使用这个starter的yaml配置文件

     就已经可以出现提示了,这些后面的中文都是之前写入的文档注释,所以得多写文档注释

    输出之后,没有提示我们要写入的值

     在前面生成的json文件中

    1. "hints": [
    2. {
    3. "name": "properties.ip.model",
    4. "values": [
    5. {
    6. "value": "detail",
    7. "description": "详细模式."
    8. },
    9. {
    10. "value": "simple",
    11. "description": "简略模式."
    12. }
    13. ]
    14. }
    15. ]

     这样就可以得出提示了

  • 相关阅读:
    Redis 排障:你永远不知道告警和下班,谁先到来?
    技术分享 | mysql 客户端对配置文件的读取顺序
    硬核性感!沉浸式体验 ZStack Cube 超融合的7大亮点功能
    C语言 ,不用string.h的函数,实现A+B A-B的字符串处理功能。
    springboot异常(一):springboot自定义全局异常处理
    数据结构与算法:二叉树的中序遍历
    Linux shell 处理文件路径文件名和后缀截取(basename和dirname无法满足的操作)
    3DEXPERIENCE许可合规性:确保企业设计流程的合法与安全
    【数据库】Redis
    Python学习笔记第四十三天(NumPy 数学函数)
  • 原文地址:https://blog.csdn.net/weixin_60719453/article/details/127554793