基于黑马的SpringBoot自动配置的ip访问计数器原理

之前学习springboot自动装配时,了解了如何自己写一个spring-boot-starter进行引入其它项目里,以此来记录,加深记忆,
ip计数器原理: 当别人访问自己的网页时,得到ip地址然后进行记录,若多次访问 则进行+1操作,并打印在控制台

如何自己动手搭建一个xx-spring-boot-starter

如何搭建一个技术starter呢?下面就是一些具体操作,一般自己搭建的starter都是以 xx技术-spring-boot-starter 的形式命名

创建一个springboot项目

首先创建一个spring boot项目 对项目名字和maven坐标进行修改,例如搭一个叫做 ip-count-spring-boot-starter项目
做好命名规范
在这里插入图片描述
点击next 后继续点击 把项目创建好后,开始搭基本框架
在这里插入图片描述

配置属性类

这里我们设置三个属性
第一个:cycle:多少时间打印一次
第二个:reset属性代表是否每次周期性打印时,是否清空里面存储的值,重新计数
第三个:modle 分为,极简模式(只显示ip地址)和详细模式(显示ip地址和次数)

package com.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * 设置属性
 *
 * @author 幕自由人
 * @date 2022/04/30
 */
@Component("ipProperties")
@ConfigurationProperties(prefix = "tools")
public class IpProperties {

    /**
     * 周期数,多少秒打印一次
     */
    private Long cycle=5L;
    /**
     * 每次周期是否重置ip信息
     */
    private Boolean reset=false;
    /**
     * 打印模式,默认详细
     */
    private String model=LogModel.DETAIL.value;

    public Long getCycle() {
        return cycle;
    }

    public void setCycle(Long cycle) {
        this.cycle = cycle;
    }

    public Boolean getReset() {
        return reset;
    }

    public void setReset(Boolean reset) {
        this.reset = reset;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    /**
     * 日志模式
     *
     * @author 幕自由人
     * @date 2022/04/30
     * 利用枚举设置信息
     */
    public enum LogModel {
    DETAIL("dateil"),
    SIMPLE("simple");
    private String value;
    LogModel(String value){
        this.value=value;
    }

    public String getValue() {
        return value;
    }
}
}

根据属性类编写逻辑代码

需求是:别人访问地址后获取他的ip地址进行保存后并且对着ip的访问次数也+1操作
利用Map集合进行存储:key是IP地址,value是 该ip访问的次数
count()方法:

    /**
     * 计数功能的实现
     */
    public void count(){
//    利用hashmap存储
        //key存在+1 不存在 设置为1
        String ipaddress=request.getRemoteAddr();
        if (ipCountMap.containsKey(ipaddress)){
            ipCountMap.put(ipaddress,ipCountMap.get(ipaddress)+1);
        }else {
            ipCountMap.put(ipaddress,1);
        }
    }

print打印方法()

  /**
     * 把存储在map里面的东西根据设置的属性条件打印出来打印查出来
     * 通过bean的注入形式把 cycle属性注入到cron表达式中
     */
    @Scheduled(cron = "0/#{ipProperties.cycle} * * * * ?")
    public void print(){

//        判断是否是详细模式
    if (ipProperties.getModel().equals(IpProperties.LogModel.DETAIL.getValue())){

        System.out.println("          ip访问监控");
        System.out.println("+----ipaddress----+---num---+");
        Set<String> strings = ipCountMap.keySet();
        for (String string : strings) {
            Integer integer = ipCountMap.get(string);
            System.out.println(String.format("|%15s  |%5d   |", string, integer));
        }
        System.out.println("+-----------------+---------+");

    }//判断是否是简单模式
    else if(ipProperties.getModel().equals(IpProperties.LogModel.SIMPLE.getValue())){
        System.out.println("          ip访问监控");
        System.out.println("+----ipaddress----+");
        Set<String> strings = ipCountMap.keySet();
        for (String string : strings) {
            System.out.println(String.format("|%15s  |", string));
        }
        System.out.println("+-----------------+");
    }

//        判断是否是周期性更新
    if (ipProperties.getReset()){
        ipCountMap.clear();
    }

    }

完整的业务逻辑代码:

package com.service;

import com.properties.IpProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class IpCountService {
//    通过调用该技术的项目进行注入
    @Autowired
private HttpServletRequest request;
private  Map<String, Integer> ipCountMap=new HashMap<>();

    /**
     * 计数功能的实现
     */
    public void count(){
//    利用hashmap存储
        //key存在+1 不存在 设置为1
        String ipaddress=request.getRemoteAddr();
        if (ipCountMap.containsKey(ipaddress)){
            ipCountMap.put(ipaddress,ipCountMap.get(ipaddress)+1);
        }else {
            ipCountMap.put(ipaddress,1);
        }
    }

    @Autowired
    private IpProperties ipProperties;
    /**
     * 把存储在map里面的东西根据设置的属性条件打印出来打印查出来
     * 通过bean的注入形式把 cycle属性注入到cron表达式中
     */
    @Scheduled(cron = "0/#{ipProperties.cycle} * * * * ?")
    public void print(){

//        判断是否是详细模式
    if (ipProperties.getModel().equals(IpProperties.LogModel.DETAIL.getValue())){

        System.out.println("          ip访问监控");
        System.out.println("+----ipaddress----+---num---+");
        Set<String> strings = ipCountMap.keySet();
        for (String string : strings) {
            Integer integer = ipCountMap.get(string);
            System.out.println(String.format("|%15s  |%5d   |", string, integer));
        }
        System.out.println("+-----------------+---------+");

    }//判断是否是简单模式
    else if(ipProperties.getModel().equals(IpProperties.LogModel.SIMPLE.getValue())){
        System.out.println("          ip访问监控");
        System.out.println("+----ipaddress----+");
        Set<String> strings = ipCountMap.keySet();
        for (String string : strings) {
            System.out.println(String.format("|%15s  |", string));
        }
        System.out.println("+-----------------+");
    }

//        判断是否是周期性更新
    if (ipProperties.getReset()){
        ipCountMap.clear();
    }

    }
}

编写spring.factories和自动配置类引入业务类

第一步编写自动装配类,什么都不用做映入类 和开启定时器就行了

/**
 * ip自动装配类
 *
 * @author 幕自由人
 * @date 2022/04/30
 */
@Configuration
//引入类
@Import(IpCountService.class)
//开启定时器
@EnableScheduling
public class IpAutoConfig {

}

第二步在resource下创建META-INF文件夹创建spring.factories

#自动加载的类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.autoconfig.IpAutoConfig

编写拦截器

package com.interceptor;

import com.service.IpCountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * ip数拦截器
 *配置拦截器,设置对那些地址进行拦截
 * @author 幕自由人
 * @date 2022/04/30
 */
public class IpCountInterceptor implements HandlerInterceptor {
//    属性注入
    @Autowired
    private IpCountService ipCountService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        ipCountService.count();

        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
}

添加拦截器

package com.config;

import com.interceptor.IpCountInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器,设置拦截路径
        registry.addInterceptor(interceptor()).addPathPatterns("/**");
        WebMvcConfigurer.super.addInterceptors(registry);
    }
//    把拦截器实例化bean
    @Bean
    public IpCountInterceptor interceptor(){
        return new IpCountInterceptor();
    }
}

设置属性提示语

第一步导包


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>

导完包后编译一下 然后把在注释掉(目的是防止重复提示)
找到编译文件下的json文件:
在这里插入图片描述
打开application.yml设置属性时,就会有提示语了
在这里插入图片描述

设置属性提示选择

打开之前的json文件 找到最底部的属性:

{
  "groups": [
    {
      "name": "tools",
      "type": "com.properties.IpProperties",
      "sourceType": "com.properties.IpProperties"
    }
  ],
  "properties": [
    {
      "name": "tools.cycle",
      "type": "java.lang.Long",
      "description": "周期数,多少秒打印一次",
      "sourceType": "com.properties.IpProperties",
      "defaultValue": 5
    },
    {
      "name": "tools.model",
      "type": "java.lang.String",
      "description": "打印模式,默认详细",
      "sourceType": "com.properties.IpProperties"
    },
    {
      "name": "tools.reset",
      "type": "java.lang.Boolean",
      "description": "每次周期是否重置ip信息",
      "sourceType": "com.properties.IpProperties",
      "defaultValue": false
    }
  ],
  "hints": []
}

修改成:

{
  "groups": [
    {
      "name": "tools",
      "type": "com.properties.IpProperties",
      "sourceType": "com.properties.IpProperties"
    }
  ],
  "properties": [
    {
      "name": "tools.cycle",
      "type": "java.lang.Long",
      "description": "周期数,多少秒打印一次",
      "sourceType": "com.properties.IpProperties",
      "defaultValue": 5
    },
    {
      "name": "tools.model",
      "type": "java.lang.String",
      "description": "打印模式,默认详细",
      "sourceType": "com.properties.IpProperties"
    },
    {
      "name": "tools.reset",
      "type": "java.lang.Boolean",
      "description": "每次周期是否重置ip信息",
      "sourceType": "com.properties.IpProperties",
      "defaultValue": false
    }
  ],
  "hints": [{
    "name": "tools.model",
    "values":[{
      "value": "simple",
      "description": "极简模式"
    },{
      "value": "detail",
      "description": "详细模式"
    }]
  }]
}

选择的值就会出现提示语了
在这里插入图片描述

清除(clean)安装(install) 到本地仓库

ctrl+鼠标点击maven 生命周期的 clean 和install 在点击运行
在这里插入图片描述

创建一个springbootweb项目引入刚刚安装到仓库的项目坐标坐标

在这里插入图片描述
然后配置yml文件
在这里插入图片描述

启动项目就会发现会自动打印了
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
黑马SpringBoot是一个基于Java语言开发的Web应用开发框架。它通过简化配置和提供一系列的自动化工具,使得开发人员能够更加快速和便捷地构建和部署应用程序。黑马SpringBoot框架的核心思想是约定大于配置,即通过一些默认的规则和约定,减少开发人员需要手动配置的工作,从而提高开发效率。 在使用黑马SpringBoot框架时,可以通过使用@Import注解来导入自定义的配置类,如引用中的示例代码中的@Import(MyImportSelector.class)。这样可以将需要自动配置的内容放入这个配置类中,使得在SpringBoot启动时无需对SpringBoot进行相关的手动配置,如引用所述。 另外,如果想要使用黑马SpringBoot框架整合ActiveMQ,可以通过在项目的pom.xml文件中添加相应的依赖,如引用所示。这样就可以使用SpringBoot提供的ActiveMQ的starter,简化了对ActiveMQ的配置和集成过程。 总结来说,黑马SpringBoot是一个基于Java语言开发的Web应用开发框架,通过简化配置和提供自动化工具,使得开发人员能够更加快速和便捷地构建和部署应用程序。可以通过导入自定义的配置类和使用相应的starter来实现对SpringBoot自动配置和集成。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [黑马SpringBoot --原理篇](https://blog.csdn.net/D_boj/article/details/129494265)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [黑马SpringBoot笔记](https://blog.csdn.net/qq_39634715/article/details/127869532)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值