记录一次配置文件中加入开关的简单实现
场景描述:
给程序添加一个使用时间,几天之后程序就不可被正常访问了
可能的实现方式:
1,程序启动时开启起一个定时任务,到指定时间后销毁程序,但是如果程序重启… 还得些定时任务代码,能不写就不写,先过
2,在redis中添加一个key,给这个key添加失效时间;
程序启动(加载bean的时候)时往redis中添加一个key,并设置好失效时间,在失效时间内程序重启时,如果有这个key就不往redis中添加;
以上两种方式都有bug,但是目前我只能这样解决了.
暂且记录一下实现的方式:
配置开关
配置文件中添加一个开关
配置文件中添加标价已标识是否开启特定功能
login: true
然后检测配置文件开关是否打开:
通过spring中的注解实现:
import com.hmrs.filter.LoginFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class LoginFilterWebConfig {
@LoginTaskConditionOnProperTy(value = "login" ,havingValue = "true")
@Bean
public LoginFilter buildFilter() {
return new LoginFilter();
}
}
如果配置文件中有这个配置,并且值为true,表示开启这个过滤器;
开启这个过滤干嘛呢?-----拦截请求:
拦截的条件就是redis中是否有指定的key
自定义一个注解
import org.springframework.context.annotation.Conditional;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional(LoginFilterCondition.class)
public @interface LoginTaskConditionOnProperTy {
String value();
String prefix() default "";
String havingValue() default "";
boolean matchIfMissing() default false;
boolean relaxedNames() default true;
}
过滤器长什么样子呢?
import com.alibaba.fastjson2.JSONObject;
import com.hmrs.comm.BaseResult;
import com.hmrs.service.RedisRWService;
import com.hmrs.util.HmrsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Gavin
*/
@Slf4j
public class LoginFilter implements Filter {
@Autowired
private RedisRWService redisRWService;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
if (redisRWService.hasKey("Gavin")){
log.info("redis中已有key");
}else{
log.info("设置redis的key");
redisRWService.saveObjData("Gavin", "Gavin");
redisRWService.setKeyExpireTime("Gavin", 72);
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest){
if (redisRWService.hasKey("Gavin")) {
log.info("Gavin过滤器已生效");
chain.doFilter(request, response);
} else {
log.info("Gavin过滤器已失效");
BaseResult baseResult = HmrsUtils.setHttpBaseResult(400, "failed", "接口已失效");
HmrsUtils.returnJson((HttpServletResponse) response, JSONObject.toJSONString(baseResult));
return;
}
}else{
return ;
}
}
@Override
public void destroy() {
}
}
有了过滤器之后,我们要注入这个过滤器使其生效:
import com.hmrs.filter.LoginFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//@ConditionalOnProperty(prefix = "login", name = "enable", havingValue = "true")
@Configuration
public class LoginFilterWebConfig {
/**
* 注册LoginFilter
*
* @return 返回实例
*/
@LoginTaskConditionOnProperTy(value = "login" ,havingValue = "true")
@Bean
public LoginFilter buildFilter() {
return new LoginFilter();
}
}
问题时什么时候才让其生效呢?这里是由我们来控制的,如果在上面的LoginFilterWebConfig直接添加注解
@ConditionalOnProperty(prefix = “login”, name = “enable”, havingValue = “true”)
由于spring自己管理,而不是按照我们想要样子来的,简单的说就是无论开关是否打开该过滤器都会生效,所以我们要自定义一个注解,然后在某种条件下会注入这个过滤器LoginFilter,
自定义注解LoginTaskConditionOnProperTy时我们要导入一个类:LoginFilterCondition—即有了该注解后将会按照imprt导入的类下匹配的情况来自定义bean是否加载:
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.MultiValueMap;
import java.util.List;
public class LoginFilterCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> allAnnotationAttributes = metadata.getAllAnnotationAttributes(LoginTaskConditionOnProperTy.class.getName());
List<Object> objectList = allAnnotationAttributes.get("value");
List<Object> havingValue = allAnnotationAttributes.get("havingValue");
String property = context.getEnvironment().getProperty((String) objectList.get(0));
if (property.equals(havingValue.get(0))){
return true;
}
return false;
}
}
最后我们打开开关之后:
com.hmrs.filter.LoginFilter - redis中已有key
关闭开关后: 该类的bean就没有加载