前言
尽管java的口号:Write Once, Run Anywhere ,但现实非常残酷。不同的操作系统、不同的容器总是让我们:Write Once,Debug Anywhere。所以关键还是要看设计。好的设计能降低迁移成本。
近期须要将roller迁移到百度云中,发现roller设计的真不错。很easy就看迁移到云中了。
迁移的主要是数据,roller使用mysql,而百度云也提高mysql。这个基本不须要考虑迁移。主要是roller的图片上传功能:
1、怎样将已经上传的图片迁移到百度的bcs中?
2、怎样以最小的代价让将上传图片的功能迁移到百度bcs中?
添加一个切换开关:roller.properties
baiduyun.accessKey=dtjTg3L9xm
baiduyun.secretKey=9V1L9mul9IVb
baiduyun.bucket=hello
enabled.use.baiduyun=true
扩展存储文件的实现类
package org.apache.roller.weblogger.business;
import java.io.InputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.roller.weblogger.config.WebloggerConfig;
import org.apache.roller.weblogger.pojos.FileContent;
import org.apache.roller.weblogger.pojos.MediaFile;
import org.apache.roller.weblogger.pojos.Weblog;
import org.apache.roller.weblogger.util.RollerMessages;
import com.baidu.inf.iis.bcs.BaiduBCS;
import com.baidu.inf.iis.bcs.auth.BCSCredentials;
import com.baidu.inf.iis.bcs.model.Empty;
import com.baidu.inf.iis.bcs.model.ObjectMetadata;
import com.baidu.inf.iis.bcs.model.X_BS_ACL;
import com.baidu.inf.iis.bcs.request.PutObjectRequest;
/**
* Manages contents of the file uploaded to Roller weblogs.
*
* This base implementation writes file content to a file system.
*/
public class BaiduYunFileContentManagerImpl extends FileContentManagerImpl {
private static Log log = LogFactory.getLog(BaiduYunFileContentManagerImpl.class);
private String host = "bcs.duapp.com";
private String accessKey = "";
private String secretKey = "";
private String bucket = "";
private BaiduBCS baiduBCS = null;
/**
* Create file content manager.
*/
public BaiduYunFileContentManagerImpl() {
accessKey = WebloggerConfig.getProperty("baiduyun.accessKey");
secretKey = WebloggerConfig.getProperty("baiduyun.secretKey");
bucket = WebloggerConfig.getProperty("baiduyun.bucket");
BCSCredentials credentials = new BCSCredentials(accessKey, secretKey);
baiduBCS = new BaiduBCS(credentials, host);
baiduBCS.setDefaultEncoding("UTF-8"); // Default UTF-8
}
/**
* @see org.apache.roller.weblogger.model.FileContentManager#getFileContent(weblog, java.lang.String)
*/
public FileContent getFileContent(Weblog weblog, String fileId)
throws FileNotFoundException, FilePathException {
log.info("=====================get file content:" + fileId);
final InputStream is = baiduBCS.getObject(bucket, getObjectStoragePath(weblog, fileId)).getResult().getContent();
return new FileContent(weblog, fileId, null) {
private InputStream ins = is;
@Override
public InputStream getInputStream() {
return ins;
}
};
}
private String getObjectStoragePath(Weblog weblog ,String fileId) {
return '/' + weblog.getHandle() + '/' + fileId;
}
public void saveFileContent(Weblog weblog, MediaFile mediaFile)
throws FileNotFoundException, FilePathException, FileIOException {
log.info("==========saveFileContent start ->" + mediaFile.getId());
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType(mediaFile.getContentType());
objectMetadata.setContentLength(mediaFile.getLength());
PutObjectRequest request = new PutObjectRequest(bucket,
getObjectStoragePath(weblog, mediaFile.getId()),
mediaFile.getInputStream(),
objectMetadata);
ObjectMetadata result = baiduBCS.putObject(request).getResult();
log.info(result);
baiduBCS.putObjectPolicy(bucket, getObjectStoragePath(weblog, mediaFile.getId()),X_BS_ACL.PublicRead);
log.info("==========saveFileContent end");
}
/**
* @see org.apache.roller.weblogger.model.FileContentManager#deleteFile(weblog, java.lang.String)
*/
public void deleteFile(Weblog weblog, String fileId)
throws FileNotFoundException, FilePathException, FileIOException {
log.info("==========deleteFile start:" + fileId);
Empty result = baiduBCS.deleteObject(bucket, getObjectStoragePath(weblog, fileId)).getResult();
baiduBCS.deleteObject(bucket, getObjectStoragePath(weblog, fileId) + "_sm").getResult();
log.info(result);
log.info("==========deleteFile start");
}
/**
* @see org.apache.roller.weblogger.model.FileContentManager#overQuota(weblog)
*/
public boolean overQuota(Weblog weblog) {
return false;
}
@Override
public boolean canSave(Weblog weblog, String fileName, String contentType,
long size, RollerMessages messages) {
return true;
}
}
改动ioc注入:
JPAWebloggerModule.java
if(WebloggerConfig.getBooleanProperty("enabled.use.baiduyun")) {
binder.bind(FileContentManager.class).to( BaiduYunFileContentManagerImpl.class);
}
else {
binder.bind(FileContentManager.class).to( FileContentManagerImpl.class);
}
最后想说的是这种方法參数设计不太好,应该把MediaFile作为參数。而非用其个别字段(fileId和inputstream)
public void saveFileContent(Weblog weblog,
String fileId,
InputStream is)
throws FileNotFoundException, FilePathException, FileIOException;
这样,roller就能够把百度bcs作为存储图片的server了。