好设计,迁移不费劲

前言

虽然java的口号:Write Once, Run Anywhere ,但现实很残酷!不同的操作系统、不同的容器总是让我们:Write Once,Debug Anywhere。所以关键还是要看设计,好的设计能减少迁移成本。

最近需要将roller迁移到百度云中,发现roller设计的真不错。非常容易就看迁移到云中了。

迁移的主要是数据,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作为存储图片的服务器了。

好设计,迁移不费劲,布布扣,bubuko.com

时间: 2024-08-02 23:03:41

好设计,迁移不费劲的相关文章

第05章 EntityFramework6:Code Frist实体关系设计--迁移数据库--初始化数据

1.写作背景 在写这篇文章前,本想继续补充完前面介绍到WebApi知识点,但下面的讲解,要进行实体/模型设计,并对数据进行CRUD实际操作了,所以先介绍一下EF基本使用啦! 本章为何不以最新版的EF7(下一章也会介绍它)先讲? 一是EF7还处于beta阶段,功能也没有开发完毕,生产环境应用有诸多问题: 二是EF7想比之前的版本变化还是很多的,我们先从代码对比上了解,以便你以后从EF6升级到EF7: 三是EF6目前也不能在ASP.NET 5类型项目中使用,但它对ASP.NET 5以外的类型项目非常

NET架构设计、框架设计系列文章总结

NET架构设计.框架设计系列文章总结 从事.NET开发到现在已经有七个年头了.慢慢的可能会很少写.NET文章了.不知不觉竟然走了这么多年,热爱.NET热爱c#.突然想对这一路的经历进行一个总结. 是时候开始下一阶段的旅途,希望这些文章可以在发挥点价值作用. 架构设计: ElasticSearch大数据分布式弹性搜索引擎使用 (推荐) DDD实施经验分享-价值导向.从上往下进行(圈内第一个吃螃蟹DDD实施方案)(推荐) 软件工程-思考项目开发那些事(一)(推荐) SOA架构设计经验分享-架构.职责

【Android应用开发技术:用户界面】界面导航设计

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells 设计开发App的起初步骤之一就是决定用户能够在App上看到什么和做什么,一旦我们知道了用户在App上和哪种内容互动,我们就可以去设计用户在App上的不同内容块之间的切换.进入和回退. 一 多视窗布局 小尺寸屏幕只适合每次展示单个纵向内容视窗,一个列表或列表项的具体信息,这种设

云上迁移(分享十)

根据公司业务发展,公司计划发展云上迁移项目,云上迁移,顾名思义是把原有的系统迁移到公有云或者私有云上,也许是P2V或者V2V模式,都有可能.最近我也是这负责这个这个云上迁移方案流程制定,也就此与大家分享. 云上迁移分6个阶段:系统评估与分析.方案设计.云平台环境准备.实施阶段.验证阶段和业务割接 评估与分析 在系统评估与分析阶段,应确定迁移范围和目标,利用调查问卷.系统评估工具和访谈等评估形式,对应用系统进行评估,分析和汇总系统需求,形成调研报告. 方案设计 在方案设计阶段,针对项目范围内的物理

ios app初始化和数据迁移的设计思路

整体思路 一般app启动之后,都有一个初始化的过程. 此外兴许app升级,还须要考虑数据迁移.所以初始化和数据迁移的框架.在初期的版本号就要考虑好 总结一下我们的app採取的方案: 1.在持久化的文件夹内(比方UserDefaults或者Documents文件夹),用一个字段保存老版本 2.在開始初始化之前,读取老版本.以及当前版本 3.假设该应用是第一次载入,那么老版本就取不到(由于是初次载入,这个字段还没有保存),那么就能够运行初始化过程.假设取到了老版本.就不运行初始化 4.初始化完毕之后

各开源框架使用与设计总结

一.框架课程总结 框架.设计模式和队列是5月份公开课的三个主题,第一周讲设计模式,第二.四周讲框架,第三周讲队列.框架讲了两周,介绍了框架的概念.PHP框架的应用范围,以及常用的PHP框架,今天是框架的最后一讲,是对整个框架系列课程的汇总,同时和大家讨论一些框架之外.或者框架之下的技术. 今天要讨论的分为这几个方面,总结框架系列课程.探讨框架可能存在,或者解决不了的问题,以及其解决方案和当前的探索. 在框架第一讲中,志华老师也站得高度很高,讲述了框架.架构的概念,以及对比了它的异同.总结来讲就是

Lucene 4.X 倒排索引原理与实现: (1) 词典的设计

词典的格式设计 词典中所保存的信息主要是三部分: Term字符串 Term的统计信息,比如文档频率(Document Frequency) 倒排表的位置信息 其中Term字符串如何保存是一个很大的问题,根据上一章基本原理的表述中,我们知道,写入文件的Term是按照字典顺序排好序的,那么如何将这些排好序的Term保存起来呢? 1. 顺序列表式 一个直观的想法就是顺序列表的方式,即每个Term都占用相同的空间,然后大家依次排列下来,如图所示: 这种方式查找起来也很方便,由于Term是排好序的,而且每

在线数据迁移经验:如何为正在飞行的飞机更换引擎

在线数据迁移,是指将正在提供线上服务的数据,从一个地方迁移到另一个地方,整个迁移过程中要求不停机,服务不受影响.根据数据所处层次,可以分为cache迁移和存储迁移:根据数据迁移前后的变化,又可以分为平移和转移. 平移是指迁移前后数据组织形式不变,比如Mysql从1个实例扩展为4个实例,Redis从4个端口扩展到16个端口,HBase从20台机器扩展到 30台机器等等.如果在最初的设计里就为以后的扩容缩容提供了方便,那么数据迁移工作就会简单很多,比如Mysql已经做了分库分表,扩展实例的时候,只需

中小型商城系统中的分类/产品属性/扩展属性的数据库设计

声明:之所以定位在"中小型"商城系统,而非“大型”(指淘宝.拍拍这类巨无霸),理由很简单----我一直都呆在(创业型的)小公司,没见过这些大家伙是怎么设计的:) 正文: 之前发表过一篇"商城系统中[商品扩展属性]的表单生成及客户端验证",部分童鞋对于后台数据库的设计比较感兴趣,于是今天把这部分也补上. 一.产品分类设计越来越多的商城系统都热衷于选择“无限级分类”的设计,我也不例外,因为它方便扩展.这部分就不详细展开了,详见 无限级分类(非递归算法/存储过程版/GUI