我在我的 Grails 项目中使用缓存资源插件,但每次我用 F5 刷新页面时,它都会使用 http 响应代码 200 而不是 304 重新加载资源。我错过了什么吗?
问问题
989 次
2 回答
2
通过覆盖cached-resources-1.0和cache-headers-1.1.5插件中的一些方法解决了这个问题。
看看他的插件。
请注意缓存头插件中的 CacheHeadersService ,void cache (response, Map args)方法,而不是我添加动态void cache(req,response, Map args)方法(请参见下面的类),它查看请求标头并发送如果资源被浏览器缓存,则为 304。
还有缓存资源插件中的HashAndCacheResourceMapper,方法def map(resource, config)我重写以使用我的 ne 方法
缓存头服务。
在 BootStrap 中运行方法void cacheResources(GrailsApplication application)将更改应用到您的项目。
class CustomCachedResourcesProcessor {
public static void cacheResources(GrailsApplication application){
addMethodsToMapResources(application)
application.mainContext.grailsResourceProcessor.reloadAll()
}
private static void addMethodsToMapResources(GrailsApplication application){
addCacheMethod()
application.getClassForName("org.grails.plugin.cachedresources.HashAndCacheResourceMapper").metaClass.map{resource, config->
if (log.debugEnabled) {
log.debug "Hashing resources to unique names..."
}
resource.processedFile = renameToHashOfContents(resource.processedFile, resource.processedFileExtension)
resource.updateActualUrlFromProcessedFile()
// Do all the horrible cache header stuff
resource.requestProcessors << { req, resp ->
if (log.debugEnabled) {
log.debug "Setting caching headers on ${req.requestURI}"
}
cacheHeadersService.cache(req,resp, [neverExpires: true, shared: true])
}
}
}
private static void addCacheMethod(){
CacheHeadersService.metaClass.cache{request,response, Map args->
if (!enabled) {
return
}
def store = args.store
def share = args.shared
def validFor = args.validFor
def validUntil = args.validUntil
def neverExpires = args.neverExpires
def requiresAuth = args.auth
def now = new Date()
def expiresOn
def maxage
if (validFor != null) {
expiresOn = new Date(now.time + validFor*1000L)
maxage = Math.max(0, validFor)
} else if (validUntil != null) {
expiresOn = validUntil
maxage = Math.round( Math.max(0, validUntil.time-now.time) / 1000L)
} else if (neverExpires) {
// HTTP 1.1 spec says SHOULD NOT set more than 1 yr in future
// @todo Investigate if impls of servletresponse.setDateHeader() are using efficient threadlocals,
// and if so change to use those
expiresOn = now + 365
maxage = Math.round( Math.max(0, expiresOn.time-now.time) / 1000L)
}
def cacheControl = []
// Now set the headers
if ((store != null) && !store) {
cacheControl << 'no-store'
}
// Always set private if no explicit share - help grails devs by defaulting to safest
if (share) {
cacheControl << 'public'
// Note, for authentication sites we still need to add no-cache to force verification
// to which the app can return "not modified" if it handles etag/lastmod
if (requiresAuth) {
cacheControl << 'no-cache'
}
} else {
cacheControl << 'private'
}
if (maxage != null) {
if (share) {
cacheControl << "s-maxage=$maxage"
}
// Always set max-age anyway, even if shared. Browsers may not pick up on s-maxage
cacheControl << "max-age=$maxage"
}
if (cacheControl) {
response.setHeader('Cache-Control', cacheControl.join(', '))
}
if (expiresOn != null) {
response.setDateHeader('Expires', expiresOn.time)
}
def possibleTags = request.getHeader('If-None-Match')
def modifiedDate = -1
try {
modifiedDate = request.getDateHeader('If-Modified-Since')
} catch (IllegalArgumentException iae) {
log.error ("Couldn't parse If-Modified-Since header", iae)
}
def lastModChanged = false
if (possibleTags || (modifiedDate != -1)) {
if (modifiedDate != -1) {
def compareDate = new Date(modifiedDate)
if (compareDate > now) {
lastModChanged = true
}
}
if (!lastModChanged) {
response.sendError(304) // Not modified
return false
}
}
// Always set last modified for courtesy and older clients,
// only if not already set by application (load balancers need identical lastmods)
if (!response.containsHeader('Last-Modified')) {
lastModified(response, now)
}
}
}
}
让我知道您对此有何看法。
于 2012-10-19T14:46:11.880 回答
0
我添加了相同的代码,但没有工作。我正在使用 Grails 2.1.4 Groovy 2.0.4 apache-tomcat-7.0.37 jdk 1.7 Windows 7
在 Config.groovy
// changed
grails.resources.modules = {
'core' {
defaultBundle 'core-ui'
resource url: '/css/cisco_base.css', attrs: [ media: 'screen' ]
resource url: '/css/cl.min.css', attrs: [ media: 'screen' ]
resource url: '/css/errors.css', attrs: [ media: 'screen' ]
resource url: '/css/jquery.multiselect.css', attrs: [ media: 'screen' ]
resource url: '/css/main.css', attrs: [ media: 'screen' ]
resource url: '/css/masterbrand.min.css', attrs: [ media: 'screen' ]
resource url: '/css/mcd.min.css', attrs: [ media: 'screen' ]
resource url: '/css/mobile.css', attrs: [ media: 'screen' ]
resource url: '/css/Sampleapp.css', attrs: [ media: 'screen' ]
resource url: '/css/style.css', attrs: [ media: 'screen' ]
resource url: '/css/table.css', attrs: [ media: 'screen' ]
wrapper: { s -> "<!--[if lt IE 8]>$s<![endif]-->"
}
//resource url: '/css/all.css', attrs: [ media: 'screen' ]
//resource url: '/css/lt7.css', attrs: [ media: 'screen' ],
}
'ui' {
defaultBundle 'core-ui'
resource url: '/js/SampleApp.js', disposition: 'head'
}
}
// changed
我得到了你的代码(上面)并放在 src/groovy/com.sample.resources 中。
I am testing like this,
1. With my changes I am creating a war file with maven package.
2. Deploying in tomcat.
3. Open browser and login to SampleGrailsApp(just open few pages in SampleGrailsApp).
4. After, changing some code(in SampleApp.js, i added alert() method to every function in that file) in js/css files in tomcat/webapps/SampleGrailsApp folder.
5. Check those changes are reflecting or not in browser.
I checked by -- opening the SampleApp in another tab -- Not reflecting changes.
-- Clean the browser cache -- Not reflecting changes.
-- Close all browsers and opened new browser -- Not reflecting changes.
于 2013-04-04T15:50:55.347 回答