1. 程式人生 > >好設計,遷移不費勁

好設計,遷移不費勁

filepath quota metadata sage comm div prop extend ssa

前言

盡管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了。

好設計,遷移不費勁