在Guava中过期后如何刷新缓存中的键和值(春季)

时间:2018-07-27 13:10:33

标签: spring spring-mvc spring-boot guava google-guava-cache

因此,我正在研究Java(春季)中的缓存方法。番石榴看起来可以解决目的。

这是用例-

我从远程服务中查询一些数据。我的应用程序的配置字段类型。我的应用程序的每个入站请求都将使用此字段。每次都调用远程服务会很昂贵,因为它是一个不断变化的常量。

因此,在入站到我的应用程序的第一个请求上,当我调用远程服务时,我将缓存该值。我将此缓存的到期时间设置为30分钟。 30分钟后,当缓存过期并且有一个请求检索密钥的请求后,我希望进行回调或其他操作来调用远程服务并设置缓存并返回该密钥的值。

如何在Guava缓存中做到这一点?

1 个答案:

答案 0 :(得分:2)

这里我举一个例子,说明如何使用番石榴缓存。如果要处理CGraphicsPSO* pso = new CGraphicsPSO(); D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; // Input Layout std::vector<D3D12_INPUT_ELEMENT_DESC> elements; if (aPSODesc.inputLayout != nullptr) { auto& ilData = aPSODesc.inputLayout->desc; for (auto& element : ilData) { // All Data here is correct when breaking D3D12_INPUT_ELEMENT_DESC elementDesc; elementDesc.SemanticName = element.mySemanticName; elementDesc.SemanticIndex = element.mySemanticIndex; elementDesc.InputSlot = element.myInputSlot; elementDesc.AlignedByteOffset = element.myAlignedByteOffset; elementDesc.InputSlotClass = _ConvertInputClassificationDX12(element.myInputSlotClass); elementDesc.Format = _ConvertFormatDX12(element.myFormat); elementDesc.InstanceDataStepRate = element.myInstanceDataStepRate; elements.push_back(elementDesc); } D3D12_INPUT_LAYOUT_DESC inputLayout = {}; inputLayout.NumElements = (UINT)elements.size(); inputLayout.pInputElementDescs = elements.data(); psoDesc.InputLayout = inputLayout; } // TOPOLOGY switch (aPSODesc.topology) { default: case EPrimitiveTopology::TriangleList: psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; // <--- Always this option break; case EPrimitiveTopology::PointList: psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; break; case EPrimitiveTopology::LineList: psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; //case EPrimitiveTopology::Patch: // psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH; // break; } // Shaders if (aPSODesc.vs != nullptr) { D3D12_SHADER_BYTECODE vertexShaderBytecode = {}; vertexShaderBytecode.BytecodeLength = aPSODesc.vs->myByteCodeSize; vertexShaderBytecode.pShaderBytecode = aPSODesc.vs->myByteCode; psoDesc.VS = vertexShaderBytecode; } if (aPSODesc.ps != nullptr) { D3D12_SHADER_BYTECODE pixelShaderBytecode = {}; pixelShaderBytecode.BytecodeLength = aPSODesc.ps->myByteCodeSize; pixelShaderBytecode.pShaderBytecode = aPSODesc.ps->myByteCode; psoDesc.PS = pixelShaderBytecode; } psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; // format of the render target DXGI_SAMPLE_DESC sampleDesc = {}; sampleDesc.Count = 1; sampleDesc.Quality = 0; psoDesc.DepthStencilState.DepthEnable = FALSE; psoDesc.DepthStencilState.StencilEnable = FALSE; psoDesc.SampleDesc = sampleDesc; // must be the same sample description as the swapchain and depth/stencil buffer psoDesc.SampleMask = UINT_MAX; // sample mask has to do with multi-sampling. 0xffffffff means point sampling is done psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); // a default rasterizer state. psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); // a default blent state. psoDesc.NumRenderTargets = 1; // we are only binding one render target psoDesc.pRootSignature = myGraphicsRootSignature; psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; ID3D12PipelineState* pipelineState; HRESULT hr = myDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState)); pso->myPipelineState = pipelineState; if (FAILED(hr)) { delete pso; return nullptr; } return pso; ,则需要调用removal listener。我在这里运行一个线程,每30分钟清理一次呼叫。

cleanUp

输入并获取数据:

import com.google.common.cache.*;
import org.springframework.stereotype.Component;


import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Component
public class Cache {

public static LoadingCache<String, String> REQUIRED_CACHE;

public Cache(){
    RemovalListener<String,String> REMOVAL_LISTENER = new RemovalListener<String, String>() {
        @Override
        public void onRemoval(RemovalNotification<String, String> notification) {
            if(notification.getCause() == RemovalCause.EXPIRED){
                //do as per your requirement
            }
        }
    };

    CacheLoader<String,String> LOADER = new CacheLoader<String, String>() {
        @Override
        public String load(String key) throws Exception {
            return null; // return as per your requirement. if key value is not found
        }
    };

    REQUIRED_CACHE = CacheBuilder.newBuilder().maximumSize(100000000)
            .expireAfterWrite(30, TimeUnit.MINUTES)
            .removalListener(REMOVAL_LISTENER)
            .build(LOADER);

    Executors.newSingleThreadExecutor().submit(()->{
        while (true) {
            REQUIRED_CACHE.cleanUp(); // need to call clean up for removal listener
            TimeUnit.MINUTES.sleep(30L);
        }
    });
}
}