3

Spring MVC コントローラーを使用していくつかのアセットを提供しようとしています。私のアセットはデータベースで管理されているため、この方法で提供する必要があります。このサービスは、データベースからアセットのメタデータを検索し、ファイル システムからファイルを読み取り、応答を構築します。

これが私のコントローラーの外観です。

@Controller
@RequestMapping("/assets")
public class AssetController {

    @Autowired
    private AssetService assetService;

    @RequestMapping("/{assetName:.+}")
    public ResponseEntity<byte[]> getAsset(@PathVariable("assetName") String assetName) throws FileNotFoundException, IOException {
        Asset asset = assetService.findByName(assetName);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.valueOf(asset.getContentType()));
        headers.setCacheControl("max-age=1209600");
        headers.setLastModified(asset.getModifiedOn().getTime()); // always in the past

        return new ResponseEntity<byte[]>(assetService.toBytes(asset), headers, OK);
    }
}

シンプルで分かりやすいと思いませんか?ブラウザが画像をキャッシュすることを望むでしょう。Cache-Controlしかし、 、ExpiresLast-Modified-Onおよびのすべての組み合わせを試したにもかかわらずETag、成功しませんでした。

以下は、2 つの連続したリクエスト中に吐き出される HTTP ヘッダー (無関係なヘッダーを削除) です。

GET /adarshr-web/assets/Acer.png HTTP/1.1
Host: localhost:8080
Pragma: no-cache
Cache-Control: no-cache

HTTP/1.1 200 OK
Cache-Control: max-age=1209600
Last-Modified: Sun, 21 Jul 2013 11:56:32 GMT
Content-Type: image/png
Date: Tue, 23 Jul 2013 21:22:58 GMT
----------------------------------------------------------

GET /adarshr-web/assets/Acer.png HTTP/1.1
Host: localhost:8080
If-Modified-Since: Sun, 21 Jul 2013 11:56:32 GMT
Cache-Control: max-age=0

HTTP/1.1 200 OK <-- Why not 304 Not Modified?
Cache-Control: max-age=1209600
Last-Modified: Sun, 21 Jul 2013 11:56:32 GMT
Content-Type: image/png
Date: Tue, 23 Jul 2013 21:23:03 GMT

ただし、次のような URL で同じシーケンス (最初の要求では Ctrl + F5、後続の要求では F5) を試すと、

応答がブラウザーによってキャッシュされていることを示すこれら (Facebook URL に表示) などのヘッダーが表示されます。

GET /rsrc.php/v2/yI/r/0PsXdTWc41M.png HTTP/1.1
Host: fbstatic-a.akamaihd.net
Pragma: no-cache
Cache-Control: no-cache

HTTP/1.1 200 OK
Content-Type: image/png
Last-Modified: Sat, 15 Jun 2013 00:48:42 GMT
Cache-Control: public, max-age=31535893
Expires: Wed, 23 Jul 2014 21:27:47 GMT
Date: Tue, 23 Jul 2013 21:29:34 GMT
----------------------------------------------------------

GET /rsrc.php/v2/yI/r/0PsXdTWc41M.png HTTP/1.1
Host: fbstatic-a.akamaihd.net
If-Modified-Since: Sat, 15 Jun 2013 00:48:42 GMT
Cache-Control: max-age=0

HTTP/1.1 304 Not Modified <-- Note this
Content-Type: image/png
Last-Modified: Sat, 15 Jun 2013 00:48:42 GMT
Cache-Control: public, max-age=31535892
Expires: Wed, 23 Jul 2014 21:27:47 GMT
Date: Tue, 23 Jul 2013 21:29:35 GMT

ノート:

  • <mvc:resources />コントローラーでまったく同じことを行っているため、Spring 構成にセクションがありません。追加しても変わりません。
  • org.springframework.web.servlet.mvc.WebContentInterceptor上記の理由により、Spring 構成で再び定義されていません。ゲインなしで1つ追加してみました。
  • https://developers.google.com/speed/docs/best-practices/cachingで説明されているすべての方法を試しました。
  • これをすべてのブラウザで複製できます。
4

1 に答える 1

4

最後に変更されたもののチェックを実装する必要がありますが、幸いなことに、Spring はそれを非常に簡単にします。

Spring Framework リファレンスから

@RequestMapping
public String myHandleMethod(WebRequest webRequest, Model model) {

    long lastModified = // 1. application-specific calculation

    if (request.checkNotModified(lastModified)) {
        // 2. shortcut exit - no further processing necessary
        return null;
     }

    // 3. or otherwise further request processing, actually preparing content
    model.addAttribute(...);
    return "myViewName";
}
于 2013-07-24T23:18:53.310 に答える