在SpringBoot中我们需要引入一项新的技术或者功能,往往只是在pom中引入相应的坐标这样简单就完成了,那么现在我们先尝试一下自定义一个starter模块,然后再使用一下
模块功能
在web应用中加入一个访问检测器,每当有用户访问网页时,后台打印出其ip地址和访问次数
实现过程
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
public class IpCount {
private Map<String,Integer> ipCountMap = new HashMap<>();
@Autowired
private HttpServletRequest request;
public void count(){
String ipAddress = request.getRemoteAddr();
if (ipCountMap.containsKey(ipAddress)){
ipCountMap.put(ipAddress,ipCountMap.get(ipAddress)+1);
}
else {
ipCountMap.put(ipAddress,1);
}
System.out.println("ipAddress:"+ipAddress+"count:"+ipCountMap.get(ipAddress));
}
}
@Autowired
private HttpServletRequest request;
HttpServletRequest的bean由使用这个模块的项目提供
- 创建一个自动配置类,并初始化刚刚创建的业务类的bean
public class IpAutoConfiguration {
@Bean
public IpCount ipCount(){
return new IpCount();
}
}
- 在resources下创建META-INF/spring.factories文件,将自动装配信息填入
这样就会自动配置IpAutoConfiguration类的bean,同时启动它所依赖的所有bean
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.ipcount.autoconfig.IpAutoConfiguration
写好之后用maven上传到本地的库中
<dependency>
<groupId>cn.ipcount</groupId>
<artifactId>ipcount_spring_boot_starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
@RestController
@RequestMapping("/account")
public class AccountController {
@Autowired
IpCount ipCount;
@GetMapping
public String getAccount(){
ipCount.count();
System.out.println("get...");
return "success";
}
}
定义属性
现在我们需要能够自定义属性,在使用时没有配置属性就用默认属性,配置了属性就使用配置的属性
- 创建一个配置类
这里仅仅设置一个简易的属性note,默认为"检测到用户访问"
@ConfigurationProperties(prefix = "ipcount")
public class IpProperties {
private String note = "检测到用户访问";
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
@EnableConfigurationProperties(IpProperties.class)
public class IpAutoConfiguration {
@Bean
public IpCount ipCount(){
return new IpCount();
}
}
- 简单修改一下业务类中的方法,直接让其打印出note
public class IpCount {
private Map<String,Integer> ipCountMap = new HashMap<>();
@Autowired
private IpProperties ipProperties;
@Autowired
private HttpServletRequest request;
public void count(){
String ipAddress = request.getRemoteAddr();
if (ipCountMap.containsKey(ipAddress)){
ipCountMap.put(ipAddress,ipCountMap.get(ipAddress)+1);
}
else {
ipCountMap.put(ipAddress,1);
}
System.out.println(ipProperties.getNote());
System.out.println("ipAddress:"+ipAddress+"count:"+ipCountMap.get(ipAddress));
}
}
现在,如果没有配置属性,程序会在运行时打印默认的参数,如果在项目中配置了这个属性,那么则会打印配置的值
ipcount:
note: "test"
test
ipAddress:[0:0:0:0:0:0:0:1]count:1
get...
加一个拦截器
这个模块目前只能在一个account-get请求里面使用,我们希望在所有资源请求都使用这个功能,于是想到了使用拦截器,当然也可以使用AOP,但是这是一个web应用,优先考虑拦截器。关于拦截器的知识也在之前的文章中已经解释过
public class IpInterceptor implements HandlerInterceptor {
@Autowired
private IpCount ipCount;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
ipCount.count();
return true;
}
}
@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {
@Bean
public IpInterceptor interceptor(){
return new IpInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor()).addPathPatterns("/**");
}
}
- 在IpAutoConfiguration中引入SpringMvcConfig
@EnableConfigurationProperties(IpProperties.class)
@Import(SpringMvcConfig.class)
public class IpAutoConfiguration {
@Bean
public IpCount ipCount(){
return new IpCount();
}
}
ok,这样一来我们就给模块加上了拦截器,并且成功定义了一个相对完整的starter,进一步了解了SpringBoot的自动装配机制
|