参考:http://www.lunatech-research.com/playframework-file-upload-blob
我对这个例子中的一点感到不安
#{list items:models.User.findAll(), as:'user'}
<img src="@{userPhoto(user.id)}">
#{/list}此时,我已经持有user对象(包括图像blob)。然而,userPhoto()方法再次进入后端以获取图像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调用吗?
发布于 2011-06-18 12:15:42
但是,您实际上不再持有user对象,因为当浏览器试图从@{userPhoto(user.id)}生成的userPhoto加载图像时,将在一个单独的请求中调用该请求。
当然,您可以使用use the cache来存储每个用户的照片Blob中的数据,这将减少您必须在图像请求时访问数据库的可能性。不过,在这种情况下,这会带来更多麻烦,因为您只是对user对象执行简单的主键查找,而且这样做的成本应该相对较低。另外,Blobs是不可序列化的,因此您必须单独提取每条信息。
不过,如果您尝试这样做,它可能会如下所示:
// 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());
}然后,您仍然需要考虑在添加、更新和删除操作中适当地填充/无效缓存。否则你的缓存将会被陈旧的数据污染。
https://stackoverflow.com/questions/6392215
复制相似问题