1

Grails プロジェクトで cached-resources プラグインを使用していますが、F5 キーでページを更新するたびに、http 応答コード 304 ではなく 200 でリソースがリロードされます。

4

2 に答える 2

2

cached -resources-1.0およびcache-headers-1.1.5プラグインのいくつかのメソッドをオーバーライドすることで、この問題を解決しました。

彼のプラグインを見てみましょう。cache-headersプラグインの CacheHeadersService に注意を払い、
void cache ( response, Map args)メソッドの代わりに、動的にvoid cache(req,response, Map args)メソッドを追加します (以下のクラスを参照)。リソースがブラウザによってキャッシュされている場合は 304。 また、 cached -resourcesプラグインのHashAndCacheResourceMapper、メソッドdef map(resource, config)をオーバーライドして、ne メソッドを使用します。
CacheHeadersService

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 に答える