google app engine笔记

1 创建应用的时候需要手机短信验证码,记得在手机号前面加上86.

2 安装google eclipse插件,最好是通过market安装,安装过程巨慢,需要耐心

3 由于dns被墙,需要绑定host方可访问:http://big-orange.appsp0t.com

只需ping 出www.google.cn的ip进行绑定即可

203.208.46.242 big-orange.appspot.com 

203.208.46.242 picasaweb.google.com

203.208.46.242 docs.google.com

4 文件上传可以考虑存储在gae默认提供的datastore的blob字段中。(独立一台作为文件服务器)

参考 http://www.ibm.com/developerworks/cn/opensource/os-cn-gaeflupl/

http://www.uml.org.cn/sjjm/201204054.asp(good)

今天尝试spring mvc版的文件上传功能,很不容易啊。spring mvc自带的文件上传请求解析器依赖于apache common fileupload,而fileupload做解析的时候用到了rmi。rmi是gae环境下禁用的类。所以这边需要自定义的文件上传解析器,刚好有个开源项目可以满足需求 https://github.com/pjesi/springextras,需要引入其中的两个类

  • StreamingMultipartResolver:对 request 中的内容进行处理,比如设置上传文件大小的最大值、编码等;
  • StreamingMultipartFile:这就是 type=file 的输入框中提交的文件,其中包含了文件名、文件大小以及文件内容的字节数组。
  • 实践
	@RequestMapping(value = "/add.htm", method = RequestMethod.POST)
	public void addImage(HttpServletRequest request, String path1, String path2) {

		// 转型为MultipartHttpRequest(重点的所在)
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		// 获得第1张图片(根据前台的name名称得到上传的文件)
		MultipartFile imgFile1 = multipartRequest.getFile("picUrl");
		try {
			String url = picasaManager.uploadPic(imgFile1.getBytes());
			ItemDO itemDO = new ItemDO();
			itemDO.setId(Long.valueOf(request.getParameter("id")));
			itemDO.setTitle(request.getParameter("title"));
			itemDO.setPrice(Double.valueOf(request.getParameter("price")));
			itemDO.setPicUrl(url);
			itemManager.addItemDO(itemDO);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
 

spring mvc需要配置为

<?xml version="1.0" encoding="UTF-8"?>
<beans default-autowire="byName" xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
 
    <!-- Scans within the base package of the application for @Components to configure as beans -->
    <!-- @Controller, @Service, @Configuration, etc. -->
    <context:component-scan base-package="com.orange.control" />
 
    <!-- Enables the Spring MVC @Controller programming model -->
    <mvc:annotation-driven /> 
    <bean id="multipartResolver" class="is.hax.spring.web.multipart.StreamingMultipartResolver" />
 	<import resource="biz-context.xml"/> 
</beans>
 

5 静态文件,和样式文件,可以考虑放到另外一台gae应用上。(独立一台作为静态文件服务器)

6 图片可以考虑使用https://picasaweb.google.com免费图片空间,或者baidu的http://hi.baidu.com/hill007299/albumcreate/multipicture/album

参考 http://jerryllx.iteye.com/blog/444057

http://www.guan8.net/Java/517220.html

实践证明用picasa是靠谱的

代码

public class DefaultPicasaManager implements PicasaManager {
	String username = "[email protected]";// 用户名
	String passwd = "XXX"; // 密码
	String albumid = "5751935385548943857"; // 相簿ID
	PicasawebService picasawebService = new PicasawebService("orange");
	String albumPostUrl = "http://picasaweb.google.com/data/feed/api/user/" + username + "/albumid/" + albumid;

	public DefaultPicasaManager() {
		try {
			picasawebService.setUserCredentials(username, passwd);
		} catch (AuthenticationException e) {
			e.printStackTrace();
		}
	}

	@Override
	public String uploadPic(byte[] bytes) {
		try {
			PhotoEntry photoEntry = createPhotoEntry(bytes);
			// 上传图片
			PhotoEntry returnedPhoto = picasawebService.insert(new URL(albumPostUrl), photoEntry);
			MediaContent content1 = (MediaContent) returnedPhoto.getContent();
			return content1.getUri();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}

	private PhotoEntry createPhotoEntry(byte[] mediaBytes) {
		PhotoEntry photoEntry = new PhotoEntry();
		photoEntry.setTitle(new PlainTextConstruct("orange"));
		photoEntry.setDescription(new PlainTextConstruct("orange"));
		photoEntry.setClient("big-orange");
		MediaContent content = new MediaContent();
		String mediaType = "image/jpeg";
		MediaSource v = new MediaByteArraySource(mediaBytes, mediaType);
		content.setMediaSource(v);
		photoEntry.setContent(content);
		return photoEntry;
	}
}
 

打印图片链接http://lh4.ggpht.com/-8rpAseX3DrU/T9MBqQCn7YI/AAAAAAAAABU/PicJHg4sea8/longji.jpg

一个账号有1G的免费空间,可以考虑多申请几个账号,图片随机存储在不同账号上。

通过这个可以拿到相册id(albumid)

http://picasaweb.google.com/data/feed/api/user/[email protected]?kind=album

(使用http://code.google.com/apis/gdata/ ,因为它依赖google的核心库,需要同时下载http://code.google.com/p/guava-libraries/,然后把jar导入eclipse)

7 全文检索功能

最新版本的已经提供

http://www.caijixia.net/xingyezixun/2012052551449.html

https://developers.google.com/appengine/docs/java/search/overview

public class DefaultSearchManager implements SearchManager {
	/**
	 * The index used by this application. Since we only have one index we
	 * create one instance only. We build an index with the default consistency,
	 * which is Consistency.PER_DOCUMENT. These types of indexes are most
	 * suitable for streams and feeds, and can cope with a high rate of updates.
	 */
	private static final Index INDEX = SearchServiceFactory.getSearchService().getIndex(
			IndexSpec.newBuilder().setName("shared_index"));

	@Override
	public boolean indexItem(ItemDO itemDO) {
		try {
			int rating = 1;
			Document.Builder docBuilder = Document.newBuilder()
					.addField(Field.newBuilder().setName("title").setText(itemDO.getTitle()))
					.addField(Field.newBuilder().setName("price").setNumber(itemDO.getPrice()))
					.addField(Field.newBuilder().setName("picUrl").setText(itemDO.getPicUrl()))
					.addField(Field.newBuilder().setName("id").setNumber(itemDO.getId()))
					.addField(Field.newBuilder().setName("rating").setNumber(rating));
			Document doc = docBuilder.build();
			INDEX.add(doc);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	@Override
	public List<ItemDO> queryItemDOs(String key) {
		int limit = 10;
		List<Document> found = new ArrayList<Document>();
		try {
			// Rather than just using a query we build a search request.
			// This allows us to specify other attributes, such as the
			// number of documents to be returned by search.
			Query query = Query.newBuilder().setOptions(QueryOptions.newBuilder().setLimit(limit).build()).build(key);
			Results<ScoredDocument> results = INDEX.search(query);
			return convertToItemDO(results);
		} catch (Exception e) {
			return null;
		}

	}

	private List<ItemDO> convertToItemDO(Results<ScoredDocument> results) {
		List<ItemDO> itemDOs = new ArrayList<ItemDO>();
		for (ScoredDocument scoredDoc : results) {
			ItemDO tempItemDO = new ItemDO();
			tempItemDO.setTitle(scoredDoc.getOnlyField("title").getText());
			tempItemDO.setPicUrl(scoredDoc.getOnlyField("picUrl").getText());
			tempItemDO.setPrice(scoredDoc.getOnlyField("price").getNumber());
			tempItemDO.setId(scoredDoc.getOnlyField("id").getNumber().longValue());
			itemDOs.add(tempItemDO);
		}
		return itemDOs;
	}
}
 

8 缓存使用memcache。

public class DefaultCacheService implements CacheService {
	MemcacheService memcache = MemcacheServiceFactory.getMemcacheService("orange");

	@Override
	public Object get(String key) {
		Object r = null;
		try {
			r = memcache.get(key);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return r;
	}

	@Override
	public boolean delete(String key) {
		memcache.delete(key);
		return true;
	}

	@Override
	public boolean put(String key, Serializable o, int exp) {
		try {
			if (exp > 0) {
				memcache.put(key, o, Expiration.byDeltaSeconds(exp));
			} else {
				memcache.put(key, o);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return true;
	}

}
 

9 持久层服务使用datastore,基于big-table

public class DefaultItemManager implements ItemManager {

	PersistenceManager persistenceManager = JDOHelper.getPersistenceManagerFactory("transactions-optional")
			.getPersistenceManager();
	CacheService cacheService;
	String prefix = "ITEM_";

	@Override
	public ItemDO getItemDOById(long id) {
		try {
			String key = prefix + id;
			ItemDO itemDO = (ItemDO) cacheService.get(key);
			if (itemDO != null) {
				return itemDO;
			}
			itemDO = persistenceManager.getObjectById(ItemDO.class, id);
			if (itemDO != null) {
				cacheService.put(key, itemDO, 1000);
			}
			return itemDO;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public boolean addItemDO(ItemDO itemDO) {
		persistenceManager.makePersistent(itemDO);
		String key = prefix + itemDO.getId();
		cacheService.delete(key);
		return true;
	}

	@Override
	public List<ItemDO> getItemDOsByQuery() {
		return null;
	}

	public void setCacheService(CacheService cacheService) {
		this.cacheService = cacheService;
	}
}

猜你喜欢

转载自hill007299.iteye.com/blog/1463506
今日推荐