好设计,迁移不费劲

前言

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

posted @ 2017-06-12 13:33  lytwajue  阅读(170)  评论(0编辑  收藏  举报