REF: http://www.lunatech-research.com/playframework-file-upload-blob
我对这个例子中的一点感到不安
#{list items:models.User.findAll(), as:'user'}
<img src="@{userPhoto(user.id)}">
#{/list}
此时我已经持有用户对象(包括图像blob)。然而,userPhoto()方法再次进入后端以获取Image user.photo
public static void userPhoto(long id) {
final User user = User.findById(id);
notFoundIfNull(user);
response.setContentTypeIfNotSet(user.photo.type());
renderBinary(user.photo.get());
}
有什么方法可以避免这种不必要的findById调用?
答案 0 :(得分:5)
您实际上并没有实际持有用户对象,因为在浏览器尝试从@{userPhoto(user.id)}
生成的URL加载图像时发送的单独请求中调用了userPhoto操作。
当然,您可以use the cache存储来自每个用户的照片Blob的数据,这样可以降低您在图像请求中转到数据库的可能性。在这种情况下,它比它的价值更麻烦,因为你只是对用户对象进行简单的主键查找,而且应该相对便宜。 Plus Blob不可序列化,因此您必须单独提取每条信息。
但是,如果你尝试它可能看起来像这样:
// The action that renders your list of images
public static void index() {
List<User> users = User.findAll();
for (User user : users) {
cachePhoto(user.photo);
}
render(users);
}
// The action that returns the image data to display
public static void userPhoto(long id) {
InputStream photoStream;
String path = Cache.get("image_path_user_" + id);
String type = Cache.get("image_type_user_" + id);
// Was the data we needed in the cache?
if (path == null || type == null) {
// No, we'll have to go to the database anyway
User user = User.findById(id);
notFoundIfNull(user);
cachePhoto(user.photo);
photoStream = user.photo.get();
type = user.photo.type();
} else {
// Yes, just generate the stream directly
try {
photoStream = new FileInputStream(new File(path));
} catch (Exception ex) {
throw new UnexpectedException(ex);
}
}
response.setContentTypeIfNotSet(type);
renderBinary(photoStream);
}
// Convenience method for caching the photo information
private static void cachePhoto(Blob photo) {
if (photo == null) {
return;
}
Cache.set("image_path_user_" + user.id,
photo.getFile.getAbsolutePath());
Cache.set("image_type_user_" + user.id,
photo.getType());
}
然后,您仍然需要担心在添加,更新和删除操作中适当填充/无效缓存。否则,您的缓存将被陈旧的数据污染。