Filter过滤器学习使用

验证token

对外API过滤器
java 复制代码
public class APIFilter implements Filter {
    private static Logger logger = LogManager.getLogger(APIFilter.class);
    private ICachedTokenService tokenService;

    public APIFilter(ICachedTokenService tokenService) {
        super();
        this.tokenService = tokenService;
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }
    @Override
    public void destroy() {

    }
    
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest hreq = (HttpServletRequest) req;
        HttpServletResponse hres = (HttpServletResponse) resp;
		//设置一些Header其他信息
        hres.setHeader("Access-Control-Allow-Origin", hreq.getHeader("Origin"));
        hres.setHeader("Access-Control-Allow-Credentials", "true");
        hres.setHeader("Access-Control-Allow-Methods", hreq.getMethod());
        hres.setHeader("Access-Control-Max-Age", "86400");
        hres.setHeader("Access-Control-Allow-Headers", "*");
       
        //不校验权限
        if(hreq.getRequestURI().contains("/unauth") || hreq.getRequestURI().contains("/question")){
            chain.doFilter(req, resp);
            return;
        }

        // 如果是OPTIONS则结束请求
        if (HttpMethod.OPTIONS.toString().equals(hreq.getMethod())) {
            hres.setStatus(HttpStatus.NO_CONTENT.value());
            return;
        }
        
        try{
        	//从请求cookie中获取access_token
            AccessTokenUser user = null;
            String access_token=hreq.getParameter("access_token");
            if(StringUtils.isBlank(access_token)){
                access_token= hreq.getHeader("access_token");
            }
            if(StringUtils.isBlank(access_token)){
                access_token=this.getCookieByCookieName("access_token", hreq);
            }
            //获取用户
            if(StringUtils.isNotBlank(access_token)){
                String token=access_token;
                user = ThreadLocalCache.fetchAPIData(
                    "AccessTokenUserByAccessToken:"+token+",true",
                    () -> {
                        ApiResultDTO<AccessTokenUser> tokenUserResp= tokenService.getAccessTokenUserByAccessToken(token, true);
                        if(tokenUserResp.isSuccessed()) {
                            return tokenUserResp;
                        }else {
                            String errorMsg = "访问令牌服务发生错误,错误码:"+tokenUserResp.getStatus()+",错误信息:"+tokenUserResp.getStatusMsg();
                            logger.error(errorMsg);
                            throw new RuntimeException(errorMsg);
                        }
                    }
                );
                //判断是否存在这样的用户
                if(user==null) logger.error("请求地址{}根据access_token【{}】无法获取登录用户。",hreq.getRequestURI(),access_token);
            }
            
            if(user==null){
                throw new BusinessException("登录已过期,请重新登录!", ApiResultDTO.STATUS_UNAUTH);
            }
            
            LoginInitUtils.afterLogin(false,hreq,hres,user);
            
            chain.doFilter(req, resp);
            return;
        } catch (Exception e) {
            ApiResultDTO<String> apiResult=null;
            if(e instanceof BusinessException) {
                BusinessException businessException = (BusinessException) e;
                apiResult = ApiResultDTO.failed(businessException.getErrorCode(), businessException.getOriMsg());
            }else {
                apiResult = ApiResultDTO.failed(e.getMessage());
            }
             hres.setContentType("application/json;charset=UTF-8");
             hres.setHeader("Cache-Control", "no-store");
             hres.setHeader("Pragma", "no-cache");
             hres.setDateHeader("Expires", 0);
             hres.getWriter().write(new ObjectMapper().writeValueAsString(apiResult));
             hres.getWriter().flush();
             hres.getWriter().close();
        }
    }
    
    private String getCookieByCookieName(String cookieName,HttpServletRequest hreq) {
        Cookie[] cookies = hreq.getCookies();
        if(cookies!=null){
            for(Cookie cookie:cookies){
                if(cookieName.equalsIgnoreCase(cookie.getName())){
                    return cookie.getValue();
                }
            }
        }
        return null;
    }
}
对内API过滤器
java 复制代码
public class _APIFilter implements Filter {
	private Logger logger=LogManager.getLogger(this.getClass()); 
	
    private ICachedTokenService tokenService;
    
    public _APIFilter(ICachedTokenService tokenService) {
        super();
        this.tokenService = tokenService;
    }
    
    @Override
    public void init(FilterConfig arg0) throws ServletException {
        
    }
    @Override
    public void destroy() {
    	
    }
    
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
    	HttpServletRequest hreq = (HttpServletRequest) req;
    	HttpServletResponse hres = (HttpServletResponse) resp;
        try{
            Utils.passOverByIp(hreq.getRemoteAddr());
            
           // logger.error("--------------------------_APIFilter["+hreq.getRequestURL()+"]开始--------------------------");
            AccessTokenUser user = null;
            String access_token=hreq.getParameter("access_token");
            if(StringUtils.isBlank(access_token)){
                access_token= hreq.getHeader("access_token");
            }
            //根据访问令牌获取用户
            if(StringUtils.isNotBlank(access_token)){
                try {
                    String token=access_token;
                    user = ThreadLocalCache.fetchAPIData(
                        "AccessTokenUser."+token+",true",
                        () -> {
                        	ApiResultDTO<AccessTokenUser> tokenUserResp=  tokenService.getAccessTokenUserByAccessToken(token, true);
                            if(tokenUserResp.isSuccessed()) {
                        		return tokenUserResp;
                        	}else {
                        		String errorMsg = "访问令牌服务发生错误,错误码:"+tokenUserResp.getStatus()+",错误信息:"+tokenUserResp.getStatusMsg();
                        		logger.error(errorMsg);
                        		throw new RuntimeException(errorMsg);
                        	}
                        }
                    );
                } catch (Exception e) {
                    e.printStackTrace();
                    user=null;
                }
                if(user==null) logger.error("--------------------------_APIFilter["+hreq.getRequestURL()+"]access_token["+access_token+"]获取用户结果"+user+"--------------------------");
            }
            //根据内部令牌获取用户
            if(user==null) {
            	String inner_token=hreq.getParameter("inner_token");
                if(StringUtils.isBlank(inner_token)){
                    inner_token = hreq.getHeader("inner_token");
                }
                if(StringUtils.isBlank(inner_token)) throw new RuntimeException("未找到访问令牌");
                
                String token=inner_token;
                user=ThreadLocalCache.fetchAPIData(null,()->{
                    return tokenService.verifyTokenAndGetUser(token);
                },"验证访问令牌错误,");
                if(user==null) logger.error("--------------------------_APIFilter["+hreq.getRequestURL()+"]inner_token["+inner_token+"]获取用户结果"+user+"--------------------------");
            }
            
            LoginInitUtils.afterLogin(false,hreq,hres,user);
            
            chain.doFilter(req, resp);
            return;
        } catch (Exception e) {
        	e.printStackTrace();
        	ApiResultDTO<String> apiResult=ApiResultDTO.failed(e.getMessage());
            hres.setContentType("application/json;charset=UTF-8");
            hres.setHeader("Cache-Control", "no-store");
            hres.setHeader("Pragma", "no-cache");
            hres.setDateHeader("Expires", 0);
            hres.getWriter().write(new ObjectMapper().writeValueAsString(apiResult));
            hres.getWriter().flush();
            hres.getWriter().close();
		}
    }
    
}
java 复制代码
public ApiResultDTO<AccessTokenUser> verifyTokenAndGetUser(String inner_token) {
        Map<String,String> claims=JWTUtils.verifyTokenAndGetClaims(inner_token);
        AccessTokenUser user=null;
        if(claims.get("user")!=null) {
            user=JsonConverter.jsonStrToObject(claims.get("user"), AccessTokenUser.class);
        }
        return ApiResultDTO.success(user);
        
    }
java 复制代码
//将inner_token 转化为用户信息
public static Map<String,String> verifyTokenAndGetClaims(String jwt_token) {
		JWT jwt=JWT.create();
        //jwt.setHeader(JWTHeader.TYPE, "JWT");//默认值
        jwt.setHeader(JWTHeader.ALGORITHM, "HS256");
        jwt.setSigner(JWTSignerUtil.createSigner("HS256", SECRET));
	    try {
	        jwt.parse(jwt_token);
		} catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("校验jwt_token令牌失败");
        }
	    if(!jwt.verify()) {
        	throw new RuntimeException("无效的jwt_token");
        }
        
    	Map<String,String> result = new HashMap<String,String>();
    	
    	JSONObject jo=jwt.getPayloads();
    	if(jo==null||jo.size()==0) {
    		return result;
    	}
        for (Map.Entry<String,Object> d: jo.entrySet()) {
        	if(d.getValue()==null) {
        		continue;
        	}
        	result.put(d.getKey(), d.getValue().toString());
		}
        
        return result;
	}

配置拦截器

java 复制代码
@Configuration
public class FiltersConfiguration {
    @Autowired
    private ICachedTokenService tokenService;
    
    //前后端交互处理-拦截所有api访问请求
    @Bean
    public FilterRegistrationBean<APIFilter> apiFilterRegistrationBean() {
        FilterRegistrationBean<APIFilter> registrationBean = new FilterRegistrationBean<APIFilter>();
        registrationBean.setFilter(new APIFilter(tokenService));
        registrationBean.addUrlPatterns("/api/*");
        registrationBean.setOrder(5);
        return registrationBean;
    }
    
    //前后端交互处理-拦截所有_api访问请求
    @Bean
    public FilterRegistrationBean<_APIFilter> _apiFilterRegistrationBean() {
        FilterRegistrationBean<_APIFilter> registrationBean = new FilterRegistrationBean<_APIFilter>();
        registrationBean.setFilter(new _APIFilter(tokenService));
        registrationBean.addUrlPatterns("/_api/*");
        registrationBean.setOrder(6);
        return registrationBean;
    }
}

清除缓存

基础数据定义的一些资源变更,需要同步清除其他项目本地缓存

配置清除缓存过滤器
java 复制代码
	//处理基础数据变更后通知各系统清空本系统的基础数据的缓存
    @Bean
    public FilterRegistrationBean<FireSysDataChangedEventFilter> fireSysDataChangedEventFilterRegistrationBean() {
        FilterRegistrationBean<FireSysDataChangedEventFilter> registrationBean = new FilterRegistrationBean<FireSysDataChangedEventFilter>();
        registrationBean.setFilter(new FireSysDataChangedEventFilter(fireSysDataChangedEventService));
        registrationBean.addUrlPatterns("/api/*");
        registrationBean.setOrder(5);
        return registrationBean;
    }
定义过滤器
java 复制代码
public class FireSysDataChangedEventFilter implements Filter {
	private Logger logger = LoggerFactory.getLogger(this.getClass());
    private IFireSysDataChangedEventService fireSysDataChangedEventService;

    public FireSysDataChangedEventFilter(IFireSysDataChangedEventService fireSysDataChangedEventService) {
        super();
        this.fireSysDataChangedEventService = fireSysDataChangedEventService;
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }
    @Override
    public void destroy() {

    }
    
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
    	try {
    		chain.doFilter(req, resp);
    		fireSysDataChangedEventIfNecessary(req);
    	}finally {
    		SysDataChanged.reset();
    	}
    }

	private void fireSysDataChangedEventIfNecessary(ServletRequest req) {
		try {
			if(SysDataChanged.isChanged()) {
				HttpServletRequest hreq = (HttpServletRequest)req;
				String uri = hreq.getRequestURI();
				logger.info("完成请求{}后,基础数据有变更,需要向其他系统发出清除缓存的消息",uri);
				fireSysDataChangedEventService.sysDataChanged();
			}
		}catch(Exception e) {
			e.printStackTrace();
			logger.error("fireSysDataChangedEventIfNecessary错误{}",e.getMessage());
		}	
	}
}
定义清除缓存服务
java 复制代码
public interface IFireSysDataChangedEventService {
	/**
	 * 基础数据发生变更
	 */
	void sysDataChanged();

}
java 复制代码
@Service
@ConfigurationProperties(prefix="docin-sys.config",ignoreUnknownFields=true)
public class FireSysDataChangedEventService implements IFireSysDataChangedEventService  {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private ISysDataVersionService sysDataVersionService;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private AsyncTaskComponent asyncTaskComponent;
    //这里的url是再配置文件配置的
    //清理缓存urls
    private Map<String, List<String>> clearcacheurls = new HashMap<>();
    public void setClearcacheurls(Map<String, List<String>> clearcacheurls) {
        this.clearcacheurls = clearcacheurls;
    }
    
    
    @SuppressWarnings("unchecked")
    @Override
    public void sysDataChanged() {
        long lastTimestamp = System.currentTimeMillis();
        //更新系统版本时间戳
        sysDataVersionService.updateLastTimestampOfSysData(lastTimestamp);
        logger.info("成功更新系统版本时间戳为{}",lastTimestamp);
        if(MapUtils.isEmpty(clearcacheurls)) return;
        for (Map.Entry<String,List<String>> e: clearcacheurls.entrySet()) {
            asyncTaskComponent.runTaskInThreadPool((d)->{
                String name=(String)d.get("name");
                List<String> urls=(List<String>)(d.get("urls"));
                for (String url : urls) {
                    try {
                        restTemplate.getForObject(url, String.class);
                        logger.info("向服务["+name+"].["+url+"]发送清理缓存请求成功");
                    } catch (Exception e2) {
                        logger.error("向服务["+name+"].["+url+"]发送清理缓存请求失败,",e2);
                    }
                }
                return null;
            }, Utils.buildMap("name",e.getKey(),"urls",e.getValue()));
        }
    }
    
}
properties 复制代码
docin-sys.config.clearcacheurls.docin-xfxt[0]=http://localhost:8088/docin-xfxt/syscache/clear
docin-sys.config.clearcacheurls.docin-xfxt[1]=http://localhost:8088/docin-xfxt/syscache/clear
docin-sys.config.clearcacheurls.docin-sys[0]=http://localhost:8088/docin-sys/syscache/clear
docin-sys.config.clearcacheurls.docin-sys[1]=http://localhost:8088/docin-sys/syscache/clear
docin-sys.config.clearcacheurls.docin-portal[0]=http://localhost:8088/docin-portal/syscache/clear
docin-sys.config.clearcacheurls.docin-stat[0]=http://localhost:8088/docin-portal/syscache/clear
docin-sys.config.clearcacheurls.hlw-xfxt[0]=http://localhost:8089/hlw-xfxt/syscache/clear
docin-sys.config.clearcacheurls.hlw-sys[0]=http://localhost:8089/hlw-sys/syscache/clear
docin-sys.config.clearcacheurls.docin-xf-exchange[0]=http://localhost:8080/docin-xf-exchange/syscache/clear
具体清除缓存请求接口
java 复制代码
@Api(value="公共基础请求-基础数据缓存处理",tags="公共基础请求")
@RestController
@RequestMapping(value="/syscache")
public class SysDataCacheController {
    
    @Autowired
    private CronClearSysDataCacheJob cronClearSysDataCacheJob;
    
    @ApiOperation(value="清理基础数据缓存", httpMethod="GET")
    @RequestMapping(value="/clear", method=RequestMethod.GET)
    public ApiResultDTO<RequestMsgTempVO> clearSyscache(HttpServletRequest request){
        return RestAPITemplate.restapi(()->{
            cronClearSysDataCacheJob.refreshCache();
            return null;
        });
    }
    
}
清除本地缓存
java 复制代码
	@Autowired
    private ISysDataVersionService sysDataVersionService;
    //本地所获得基础数据最后更新时间戳
    private volatile long lastSysTimestamp = -1L;
    private volatile boolean refreshing=false;
    @Async("taskExecutor")//使用线程池 启动
    public void refreshCache() {
        logger.info("定时刷新令牌任务启动");
        if(this.refreshing) {
            logger.error("之前刷新任务还在堵塞中....");
            return;
        }
        try {
            this.refreshing = true;
            long lastSysTimestampOfServer = sysDataVersionService.getLastTimestampOfSysData();
            if(this.lastSysTimestamp!=lastSysTimestampOfServer) {
                this.lastSysTimestamp = lastSysTimestampOfServer;
                SysDataCacheAspect.clearCache();
                logger.warn("本地基础数据缓存已经清理,清理后本地基础数据版本为{}",lastSysTimestamp);
                Thread.sleep(5000);//防止攻击
            }else {
                logger.info("本地基础数据缓存的版本与基础数据服务一致,无需清理,本地基础数据版本为{}",lastSysTimestamp);
            }
        }catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            this.refreshing=false;
        }
    }
缓存逻辑
java 复制代码
@Aspect   //定义一个切面
@Configuration
public class SysDataCacheAspect {
    private static Logger logger = LogManager.getLogger(SysDataCacheAspect.class);
    private static final  Map<String,Boolean> cacheFileNames = new ConcurrentHashMap<String, Boolean>();

    private static LoadingCache<String,Object> cache = null;
    static {
        // CacheLoader 初始化
        CacheLoader<String, Object> cacheLoader = new CacheLoader<String, Object>() {
            @Override
            // load方法的作用是在通过get方法从LoadingCache获取不到值时去加载该值并放入缓存。
            public Object load(String key) throws Exception {
                return null;
            }
        };
        cache = CacheBuilder.newBuilder()
                // 设置容量大小
                .maximumSize(80000)
                //默认一天后过期
                .expireAfterWrite(10, TimeUnit.DAYS)
                .removalListener(new RemovalListener<String, Object>() {
                    @Override
                    public void onRemoval(RemovalNotification<String, Object> notification) {
                        if(notification.getValue()!=null && notification.getValue() instanceof CacheFile) {
                            CacheFile cacheFile = (CacheFile)notification.getValue();
                            removeCacheFile(cacheFile.fileName);
                        }
                        
                    }
                })
                // 加载器配置
                .build(cacheLoader);
    }
    
    private String normalizedArgsStr(Object[] args){
        if(args==null || args.length==0) {
            return "";
        }
        Object[] normalizedArgs = new Object[args.length];
        if(args!=null) {
            for(int i=0;i<args.length;i++) {
                Object arg = args[i];
                
                if(arg instanceof AccessTokenUser) {
                    AccessTokenUser user = (AccessTokenUser)arg;
                    normalizedArgs[i]= user.getUserId();
                }else {
                    normalizedArgs[i]=arg;
                }
            }
        }
        return JsonConverter.toJsonStr(normalizedArgs);
    }
    
    @Around("execution(* (@com.xysd.bizbase.annotation.SysDataCache *).*(..)) || execution(@com.xysd.bizbase.annotation.SysDataCache * *(..))")
    public Object process(ProceedingJoinPoint point) throws Throwable {
        String className = point.getSignature().getDeclaringTypeName();
        String methodName = point.getSignature().getName();
        Object[] args = point.getArgs();
        String key = className+"_$_"+methodName+"_$_"+(normalizedArgsStr(args));
        Object cached = cache.getIfPresent(key);
        
        if(methodName.endsWith("_dontCache")){
            return point.proceed(args);
        }
        if(cached!=null) {
            if(cached instanceof CacheFile) {
                CacheFile cachedFile = (CacheFile)cached;
                Object cachedData =  readCachedData(cachedFile);
                if(cachedData==null) {
                    //读取缓存失败
                    return point.proceed(args);
                }else {
                    return cachedData;
                }
            }else {
                return cached;
            }
            
        }else {
            cached = point.proceed(args);
            if(cached instanceof ApiResultDTO){
                if(((ApiResultDTO<?>) cached).getData() == null) return cached;
            }
            if(cached!=null) {
                try {
                    CacheFile cachedFile = cacheToDiskIfNecessary(cached);
                    if(cachedFile!=null) {
                        cache.put(key, cachedFile);
                    }else {
                        cache.put(key, cached);
                    }
                    
                }catch(Exception e) {
                    logger.error("缓存失败,失败信息{}",e.getMessage());
                    e.printStackTrace();
                }
                
            }
            return cached;
        }
    }
    private Object readCachedData(CacheFile cachedFile) {
        String fileName = cachedFile.getFileName();
        String absolutePath = getAbsoluteCacheFilePath(fileName);
        File f = new File(absolutePath);
        InputStream in = null;
        ObjectInputStream oin = null;
        try {
            in = new FileInputStream(f);
            oin = new ObjectInputStream(in);
            Object cachedData = oin.readObject();
            return cachedData;
        }catch(Exception e) {
            logger.error("读取缓存序列化文件失败,失败信息:{}",e.getMessage());
            e.printStackTrace();
            return null;
        }
        finally {
            Utils.clean(in,oin);
        }
        
    }
    /**
     * 当value序列化后占用字节大于50K时写入磁盘进行缓存
     * @param value
     * @return
     */
    private CacheFile cacheToDiskIfNecessary(Object value) {
        int cachThreadshold = 50*1024;
        ByteArrayOutputStream bos = null ; 
        ObjectOutputStream oos = null;
        try {
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(value);
            oos.flush();
            byte[] byteArray = bos.toByteArray();
            if(byteArray!=null && byteArray.length>cachThreadshold) {
                return buildCacheFile(byteArray);
            }else {
                return null;
            }
        }catch(Exception e) {
            throw new RuntimeException(e);
        }finally {
            Utils.clean(bos,oos);
        }
    }
    
    private CacheFile buildCacheFile(byte[] byteArray) {
        String fileName = "syscachefile_"+Utils.getUUID("");
        String absolutePath = getAbsoluteCacheFilePath(fileName);
        File f = new File(absolutePath);
        OutputStream out = null;
        try {
            if(!f.getParentFile().exists()) {
                f.getParentFile().mkdirs();
            }
            out = new FileOutputStream(f);
            out.write(byteArray);
            out.flush();
            cacheFileNames.put(fileName, true);
            return new CacheFile(fileName);
        }catch(Exception e) {
            
            throw new RuntimeException(e);
        }finally {
            Utils.clean(out);
        }
        
    }
    
    private static String getAbsoluteCacheFilePath(String fileName) {
        String sysCacheBaseDir = Utils.getTmpDirRoot()+"/sysDataCache";
        return sysCacheBaseDir+"/"+fileName;
    }
    
    public static void removeCacheFile(String fileName) {
        if(StringUtils.isNoneBlank(fileName)) {
            cacheFileNames.remove(fileName);
            String absolutePath = getAbsoluteCacheFilePath(fileName);
            File f = new File(absolutePath);
            try {
                if(f.exists() && f.isFile()) {
                    f.delete();
                }
            }catch(Exception e) {
                //删除失败不做任何处理
                e.printStackTrace();
            }
        }
    }
    /**
     * 清空缓存
     */
    public static final void clearCache() {
        for(String fileName:cacheFileNames.keySet()) {
            removeCacheFile(fileName);
        }
        cacheFileNames.clear();
        cache.invalidateAll();
    }
    
    public static class CacheFile implements Serializable {
        private static final long serialVersionUID = -6926387004863371705L;
        private String fileName;
        public CacheFile(String fileName) {
            super();
            this.fileName = fileName;
        }
        public String getFileName() {
            return fileName;
        }
    }
}
拦截器

Hibernate的拦截器 监听实体变化

java 复制代码
public class SysEntityUpdateListener extends EmptyInterceptor {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7428554904158765594L;

	@Override
	public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
		super.onDelete(entity, id, state, propertyNames, types);
		SysDataChanged.changed();
	}

	@Override
	public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
			String[] propertyNames, Type[] types) {
		SysDataChanged.changed();
		return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);
		
	}

	@Override
	public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
		SysDataChanged.changed();
		return super.onSave(entity, id, state, propertyNames, types);
	}

	@Override
	public void postFlush(Iterator entities) {
		super.postFlush(entities);
	}

	@Override
	public int[] findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
			String[] propertyNames, Type[] types) {
		 
		return super.findDirty(entity, id, currentState, previousState, propertyNames, types);
	}

	@Override
	public void onCollectionRemove(Object collection, Serializable key) throws CallbackException {
		SysDataChanged.changed();
		super.onCollectionRemove(collection, key);
	}

	@Override
	public void onCollectionUpdate(Object collection, Serializable key) throws CallbackException {
		SysDataChanged.changed();
		super.onCollectionUpdate(collection, key);
	}

}
记录是否要清理缓存
java 复制代码
public class SysDataChanged {
	private static final ThreadLocal<Boolean> store = new ThreadLocal<Boolean>();
	/**
	 * 当前线程已经更改过基础数据
	 */
	public static final void changed() {
		store.set(true);
	}
	/**
	 * 重置
	 */
	public static final  void reset() {
		store.set(false);
	}
	/**
	 * 当前线程是否更改过基础数据
	 * @return
	 */
	public static final  boolean isChanged() {
		return Boolean.TRUE.equals(store.get());
	}

}

通过SysEntityUpdateListener监听实体变化,更改SysDataChanged.store.set(true)。当用户请求后端接口时,通过FireSysDataChangedEventFilter过滤器判断SysDataChanged.store.get()==true,从而触发restTemplate.getForObject(url, String.class)请求,更新各个项目本地的基础数据缓存SysDataCacheAspect.clearCache()。

相关推荐
J不A秃V头A24 分钟前
IntelliJ IDEA中设置激活的profile
java·intellij-idea
DARLING Zero two♡26 分钟前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
小池先生38 分钟前
springboot启动不了 因一个spring-boot-starter-web底下的tomcat-embed-core依赖丢失
java·spring boot·后端
CodeClimb41 分钟前
【华为OD-E卷-木板 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
odng44 分钟前
IDEA自己常用的几个快捷方式(自己的习惯)
java·ide·intellij-idea
CT随1 小时前
Redis内存碎片详解
java·开发语言
brrdg_sefg1 小时前
gitlab代码推送
java
hanbarger1 小时前
mybatis框架——缓存,分页
java·spring·mybatis
cdut_suye2 小时前
Linux工具使用指南:从apt管理、gcc编译到makefile构建与gdb调试
java·linux·运维·服务器·c++·人工智能·python
苹果醋32 小时前
2020重新出发,MySql基础,MySql表数据操作
java·运维·spring boot·mysql·nginx