dubbox2.8.4例子教程一
简介
Dubbo是一个来自阿里巴巴的开源分布式服务框架,当当根据自身的需求,为Dubbo实现了一些新的功能,包括REST风格远程调用、Kryo/FST序列化等等。并将其命名为Dubbox(即Dubbo eXtensions),教程一就写生产者,教程二就写消费者
一、生产者工程结构
二、Simple.java(测试普通dubbo功能)
package bhz.entity; import java.io.Serializable;
import java.util.Map; public class Simple implements Serializable
{
private static final long serialVersionUID = -4914434736682797743L;
private String name;
private int age;
private Map<String,Integer> map;
public Simple(){ }
public Simple(String name,int age,Map<String,Integer> map){
this.name = name;
this.age = age;
this.map = map;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public Map<String, Integer> getMap() {
return map;
} public void setMap(Map<String, Integer> map) {
this.map = map;
} }
2、User.java(测试dubbox特有的rest服务)
package bhz.entity; import java.io.Serializable; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement; import org.codehaus.jackson.annotate.JsonProperty; @XmlRootElement
public class User implements Serializable
{ /**
*
*/
private static final long serialVersionUID = 1L; @NotNull
private String id; @NotNull
@Size(min = 6, max = 50)
private String name; public User() {
} public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} }
3、dubbo-provider.xml(生产者核心配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"> <!-- 引入properties配置文件 -->
<util:properties id="zcparams" location="classpath:params.properties"></util:properties> <!-- 指定dubbox生产者名称 -->
<dubbo:application name="provider" owner="programmer" organization="dubbox"/> <!-- zookeeper注册中心 -->
<dubbo:registry address="zookeeper://192.168.0.4:2181?backup=192.168.0.5:2181,192.168.0.6:2181"/> <dubbo:annotation package="bhz.service" />
<!-- kryo实现序列化-->
<dubbo:protocol name="dubbo" serialization="kryo" optimizer="bhz.utils.SerializationOptimizerImpl" /> <!--指定 rest服务 -->
<dubbo:protocol name="rest" server="tomcat" port="8888" contextpath="provider" accepts="500" /> </beans>
4、SimpleService.java
package bhz.service; import bhz.entity.Simple;
/**
* 测试普通dubbo服务
* @author Administrator
*
*/
public interface SimpleService { public String sayHello(String name); public Simple getSimple();
}
5、UserService.java
package bhz.service; import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType; import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType; import bhz.entity.User;
/**
* 功能:本类测试dubbox的rest服务
* @author Administrator
*
*/
@Path("/userService")
@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML}) // @Consumes 注释代表的是一个资源可以接受的 MIME 类型
@Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8}) //@Produces 注释代表的是一个资源可以返回的 MIME 类型
public interface UserService {
@GET
@Path("/testget")
public void testget(); @GET
@Path("/getUser")
public User getUser(); @GET
@Path("/get/{id : \\d+}")
public User getUser(@PathParam(value = "id") Integer id); @GET
@Path("/get/{id : \\d+}/{name : [a-zA-Z][0-9]}")
public User getUser(@PathParam(value = "id") Integer id, @PathParam(value = "name") String name); @POST
@Path("/testpost")
public void testpost(); @POST
@Path("/postUser")
public User postUser(User user); @POST
@Path("/post/{id}")
public User postUser(@PathParam(value = "id") String id); }
6、SimpleServiceImpl.java
package bhz.service.impl; import java.util.HashMap;
import java.util.Map; import org.springframework.stereotype.Service; import bhz.entity.Simple;
import bhz.service.SimpleService;
//spring注解
//@Service("simpleService")
/*
* dubbo注解
* interfaceClass 指定服务接口
* protocol 指定协议
* retries 重试策略
*/
@com.alibaba.dubbo.config.annotation.Service(interfaceClass=bhz.service.SimpleService.class, protocol={"dubbo"}, retries=0)
public class SimpleServiceImpl implements SimpleService{ @Override
public String sayHello(String name) {
return "hello" + name;
} @Override
public Simple getSimple() {
Map<String,Integer> map = new HashMap<String, Integer>(2);
map.put("zhang0", 1);
map.put("zhang1", 2);
return new Simple("zhang3", 21, map);
} }
7、UserServiceImpl.java
package bhz.service.impl; import bhz.entity.User;
import bhz.service.UserService; //这个是dubbo的注解(同时提供dubbo本地,和rest方式)
@com.alibaba.dubbo.config.annotation.Service(interfaceClass=bhz.service.UserService.class, protocol = {"rest", "dubbo"}, retries=0)
public class UserServiceImpl implements UserService{ public void testget() {
//http://localhost:8888/provider/userService/getUser
System.out.println("测试...get");
} public User getUser() {
System.out.println("==========");
User user = new User();
user.setId("1001");
user.setName("张三");
return user;
} public User getUser(Integer id) {
System.out.println("测试传入int类型的id: " + id);
User user = new User();
user.setId("1001");
user.setName("张三");
return user;
} public User getUser(Integer id, String name) { System.out.println("测试俩个参数:");
System.out.println("id: " + id);
System.out.println("name: " + name);
User user = new User();
user.setId("1001");
user.setName("张三");
return user;
} public void testpost() {
System.out.println("测试...post");
} public User postUser(User user) {
System.out.println(user.getName());
System.out.println("测试...postUser");
User user1 = new User();
user1.setId("1001");
user1.setName("张三");
return user1;
} public User postUser(String id) {
System.out.println(id);
System.out.println("测试...post");
User user = new User();
user.setId("1001");
user.setName("张三");
return user;
} }
8、FastJsonConvert.java(fastJson转换工具类)
package bhz.utils; import java.util.List; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature; /**
* 功能:fastJson转换工具类
* @author jacky
*
*/
public class FastJsonConvert { private static final SerializerFeature[] featuresWithNullValue = { SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullBooleanAsFalse,
SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteNullStringAsEmpty }; /**
* JsonString 转换 Object
*
* @param <T>
* @param data
* @param clzss
* @return
*/
public static <T> T convertJSONToObject(String data, Class<T> clzss) {
try {
T t = JSON.parseObject(data, clzss);
return t;
} catch (Exception e) {
e.printStackTrace();
return null; }
}
/**
* JsonString 转换 List<Object>
*
* @param <T>
* @param data
* @param clzss
* @return
*/
public static <T> List<T> convertJSONToArray(String data, Class<T> clzss) {
try {
List<T> t = JSON.parseArray(data, clzss);
return t;
} catch (Exception e) {
e.printStackTrace();
return null; }
} /**
* 功能:把java对象序列化成json字符串
* @param obj java实体
* @return json字符串
*/
public static String convertObjectToJSON(Object obj) {
try {
String text = JSON.toJSONString(obj);
System.out.println(text);
return text;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} /**
* Object to JsonString
*
* @param <T>
* @param data
* @param valueType
* @return
*/
public static String convertObjectToJSONWithNullValue(Object obj) {
try {
String text = JSON.toJSONString(obj, featuresWithNullValue);
return text;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} public static void main(String[] args) {
System.err.println(System.getProperties());
}
}
9、HttpProxy.java(发送http请求,测试rest服务的工具类)
package bhz.utils; import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.EntityBuilder;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils; public class HttpProxy {
private static class SingletonHolder {
static final HttpProxy instance = new HttpProxy();
} public static HttpProxy getInstance() {
return SingletonHolder.instance;
} private static CloseableHttpClient httpClient; private static final String CONTENT_TYPE_JSON = "application/json"; static {
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(HttpProxyConfig.MAX_TOTAL_CONNECTIONS);
cm.setDefaultMaxPerRoute(HttpProxyConfig.MAX_ROUTE_CONNECTIONS); RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(HttpProxyConfig.CONNECT_TIMEOUT)
.setConnectTimeout(HttpProxyConfig.CONNECT_TIMEOUT)
.build();
//缓存
/*
CacheConfig cacheConfig = CacheConfig.custom()
.setMaxCacheEntries(1000)
.setMaxObjectSize(8192)
.build();
*/
httpClient = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(cm)
.build();
} public static HttpClient getHttpClient() {
return httpClient;
} /**
* <B>方法名称:</B>普通请求<BR>
* <B>概要说明:</B>普通请求<BR>
* @param requestUrl 请求路径
* @param requestContent 请求内容
* @return 返回响应结果
* @throws IOException
*/
public static String post(String requestUrl, String requestContent) throws IOException {
StringEntity requestEntity = new StringEntity(requestContent, Consts.UTF_8);
return execute(requestUrl,requestEntity);
} /**
* 功能:发送json请求
* @param requestUrl 请求路径url
* @param jsonContent json字符串
* @return 返回json字符串
* @throws IOException
*/
public static String postJson(String requestUrl, String jsonContent) throws IOException {
StringEntity requestEntity = new StringEntity(jsonContent, Consts.UTF_8);
requestEntity.setContentEncoding("UTF-8");
requestEntity.setContentType(CONTENT_TYPE_JSON);
return execute(requestUrl,requestEntity);
} /**
* <B>方法名称:</B>模拟表单上传<BR>
* <B>概要说明:</B>模拟表单上传<BR>
* @param requestUrl 请求路径
* @param params 属性参数
* @return 返回响应结果
* @throws IOException
*/
public static String post(String requestUrl, Map<String, String> params) throws IOException {
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
if (params != null) {
for (Map.Entry<String, String> entry : params.entrySet()) {
nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
}
EntityBuilder builder = EntityBuilder.create();
builder.setParameters(nvps);
HttpEntity httpEntity = builder.build();
return execute(requestUrl,httpEntity);
} /**
* <B>方法名称:</B>上传文件<BR>
* <B>概要说明:</B>上传文件<BR>
* @param requestUrl 请求路径
* @param localFile 文件位置
* @param username 用户名
* @param password 密码
* @return 响应信息
* @throws IOException
*/
public static String upload(String requestUrl, String localFile, String username, String password) throws IOException {
HttpPost httpPost = new HttpPost(requestUrl);
// 把文件转换成流对象FileBody
FileBody fileBody = new FileBody(new File(localFile));
StringBody usernameInp = new StringBody(username, ContentType.create("text/plain", Consts.UTF_8));
StringBody passwordInp = new StringBody(password, ContentType.create("text/plain", Consts.UTF_8));
HttpEntity httpEntity = MultipartEntityBuilder.create()
// 相当于<input type="file" name="file"/>
.addPart("file", fileBody)
// 相当于<input type="text" name="userName" value=userName>
.addPart("username", usernameInp)
.addPart("password", passwordInp)
.build();
return execute(requestUrl,httpEntity);
} /**
* 功能:执行请求方法
* @param requestUrl 请求路径Url
* @param httpEntity 封装好的http实体
* @return json字符串
* @throws IOException
*/
private static String execute(String requestUrl, HttpEntity httpEntity) throws IOException {
String result = null;
HttpPost httpPost = new HttpPost(requestUrl);
httpPost.setEntity(httpEntity);
try {
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
try {
HttpEntity entity = httpResponse.getEntity();
if (httpResponse.getStatusLine().getReasonPhrase().equals("OK") && httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(entity, "UTF-8");
}
//进行销毁
EntityUtils.consume(entity);
} finally {
if (null != httpResponse) {
httpResponse.close();
}
}
} finally {
if (null != httpPost) {
httpPost.releaseConnection();
}
}
return result;
}
/**
* 功能:发送http的get请求
* @param requestUrl 请求url
* @return 字符串
*/
public static String get(String requestUrl){
HttpGet httpGet = new HttpGet(requestUrl);
// 执行get请求.
CloseableHttpResponse response =null;
HttpEntity entity =null;
String result =null;
try {
response = httpClient.execute(httpGet);
entity = response.getEntity();
// 打印响应状态
System.out.println(response.getStatusLine());
if (entity != null) {
// 打印响应内容长度
System.out.println("Response content length: " + entity.getContentLength());
// 打印响应内容
result = EntityUtils.toString(entity);
System.out.println("Response content: " + result);
}
System.out.println("------------------------------------");
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
} }
10、HttpProxyConfig.java
package bhz.utils; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; /**
* <br>
* 类 名: HttpCallerConfig <br>
* 描 述: http属性配置参数 <br>
*/
@Component
public class HttpProxyConfig {
/**
* 最大连接数
*/
public static int MAX_TOTAL_CONNECTIONS = 800;
/**
* 每个路由最大连接数
*/
public static int MAX_ROUTE_CONNECTIONS = 400;
/**
* 连接超时时间
*/
public static int CONNECT_TIMEOUT = 10000;
/**
* 读取超时时间
*/
public static int READ_TIMEOUT = 10000; /**
* 设置 mAX_TOTAL_CONNECTIONS
*
* @param mAX_TOTAL_CONNECTIONS
*/
@Value("#{zcparams[max_total_connections]}")
private void setMAX_TOTAL_CONNECTIONS(int mAX_TOTAL_CONNECTIONS) {
MAX_TOTAL_CONNECTIONS = mAX_TOTAL_CONNECTIONS;
} /**
* 设置 mAX_ROUTE_CONNECTIONS
*
* @param mAX_ROUTE_CONNECTIONS
*/
@Value("#{zcparams[max_total_connections]}")
private void setMAX_ROUTE_CONNECTIONS(int mAX_ROUTE_CONNECTIONS) {
MAX_ROUTE_CONNECTIONS = mAX_ROUTE_CONNECTIONS;
} /**
* 设置 cONNECT_TIMEOUT
*
* @param cONNECT_TIMEOUT
*/
@Value("#{zcparams[connect_timeout]}")
private void setCONNECT_TIMEOUT(int cONNECT_TIMEOUT) {
CONNECT_TIMEOUT = cONNECT_TIMEOUT;
} /**
* 设置 rEAD_TIMEOUT
*
* @param rEAD_TIMEOUT
*/
@Value("#{zcparams[read_timeout]}")
private void setREAD_TIMEOUT(int rEAD_TIMEOUT) {
READ_TIMEOUT = rEAD_TIMEOUT;
} }
11、SerializationOptimizerImpl.java(自定义序列化实现类)
package bhz.utils; import java.util.Collection;
import java.util.LinkedList;
import java.util.List; import bhz.entity.Simple;
import bhz.entity.User; import com.alibaba.dubbo.common.serialize.support.SerializationOptimizer; public class SerializationOptimizerImpl implements SerializationOptimizer { public Collection<Class> getSerializableClasses() {
List<Class> classes = new LinkedList<Class>();
//这里可以把所有需要进行序列化的类进行添加
classes.add(User.class);
classes.add(Simple.class);
return classes;
}
}
12、log4j.properties
log4j.rootLogger=INFO, console, file log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d %p [%c] - %m%n log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
#log4j.appender.file.File=D:/002_developer/workspace_001/zcmoni.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %p [%c] - %m%n log4j.logger.org.springframework=WARN
13、params.properties
#HttpCaller
max_total_connections = 1600
max_route_connections = 1200
connect_timeout = 30000
read_timeout = 30000
14、Provider.java(启动dubbo服务类)
package bhz.test; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Provider { public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "dubbo-provider.xml" });
context.start();
System.in.read(); // 为保证服务一直开着,利用输入流的阻塞来模拟
}
}
15、HttpTest1.java(测试dubbox的rest服务类)
package bhz.test; import bhz.entity.User;
import bhz.utils.FastJsonConvert;
import bhz.utils.HttpProxy; public class HttpTest1 { public static void main(String[] args) throws Exception{
User user = new User();
user.setId("1001");
user.setName("李四");
String responseStr1 = HttpProxy.postJson("http://localhost:8888/provider/userService/postUser",
FastJsonConvert.convertObjectToJSON(user));
System.out.println("post请求返回的结果"+responseStr1);
System.out.println("========================");
String string = HttpProxy.get("http://localhost:8888/provider/userService/getUser");
System.out.println("get请求返回的结果"+string); }
}
16、测试结果
========================
HTTP/1.1 200 OK
Response content length: -1
Response content: {"id":"1001","name":"张三"}
------------------------------------
get请求返回的结果{"id":"1001","name":"张三"}
参考资料地址
http://dangdangdotcom.github.io/dubbox/
http://www.open-open.com/lib/view/open1417426480618.html
dubbox2.8.4例子教程一的更多相关文章
- CRL快速开发框架系列教程一(Code First数据表不需再关心)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- NGUI系列教程一
NGUI是Unity的一个插件,使用它来制作你的游戏UI必定将事半功倍.为什么这么说呢?首先我们说说GUI与NGUI的区别,GUI是Unity自带的绘制界面工具,它的成像原理是基于表层的,所以执行效率 ...
- Quartz教程一:使用quartz
原文链接 | 译文链接 | 翻译:nkcoder | 校对:方腾飞 本系列教程由quartz-2.2.x官方文档翻译.整理而来,希望给同样对quartz感兴趣的朋友一些参考和帮助,有任何不当或错误之处 ...
- redis学习教程一《Redis的安装和配置》
redis学习教程一<Redis的安装和配置> Redis的优点 以下是Redis的一些优点. 异常快 - Redis非常快,每秒可执行大约110000次的设置(SET)操作,每秒大约可执 ...
- Cobalt Strike使用教程一
Cobalt Strike使用教程一 0x00 简介 Cobalt Strike是一款基于java的渗透测试神器,常被业界人称为CS神器.自3.0以后已经不在使用Metasploit框架而作为 ...
- MVC5 + EF6 入门完整教程一:从0开始
第0课 从0开始 ASP.NET MVC开发模式和传统的WebForm开发模式相比,增加了很多"约定". 直接讲这些 "约定" 会让人困惑,而且东西太多容易忘记 ...
- Webpack使用教程一
过去数年间,web开发已经从包含少量JavaScript代码的应用发展到到拥有复杂JavaScript代码和代码之间依赖关系树的应用.手动维护这些复杂的代码依赖关系是很麻烦的.Webpack能分析项目 ...
- Webpack教程一
比较 如果你熟悉原来一系列的构建工具,grunt或者gulp之类的,这里有一篇webpack和他们比较的文章可以读一读. Webpack Compared 安装 先装好node和npm,因为webpa ...
- 【Cocos2d入门教程一】Cocos2d-x环境搭建
在进行Cocos2d游戏开发前 我们先来配置一下环境,我们先来准备一下工具,我们所需要的工具分别为: 1.Cocos2d引擎 2.JDK 3.SDK 4.NDK 5.ANT 6.ADT 1.下载Coc ...
随机推荐
- iOS开发之复制字符串到剪贴板
概述 一般有邀请复制链接需求功能,把字符串复制到系统剪贴板,供用户粘贴使用链接. 详细 代码下载:http://www.demodashi.com/demo/10714.html 一.主要思路 1.在 ...
- 不止是动态化:Weex项目和阿里无线技术开源方向
这是开发者正在书写的峥嵘岁月.受益开源,回馈社区.阿里巴巴集团已经开源115个项目,并正式加入FSF基金会,Apache基金会,linux 基金会和Xen的顾问团队,并在云栖大会北京峰会宣布AliSQ ...
- 用户研究Q&A(1)
近来,不少同事开始认同用户研究的价值,希望通过接触,理解和研究用户来获取提升产品的有效信息.这绝对是件好事,因为我一直抱持的理念是,研究并不是藏在实验室或者握在少部分人手中的稀罕货,更重要是一种理念和 ...
- 【laravel5.4】自定义公共函数的创建
原文地址:http://blog.csdn.net/qq_38125058/article/details/76862151 公共函数,简单来说就是在任何地方都可以直接使用这个函数.简单介绍两种实现方 ...
- jQuery正则:电话、身份证、邮箱简单校验
if (!(/^1[3,5,6,7,8,9]\d{9}$/).test(e.detail.value.data_phone)) { wx.showToast({ title: '请输入有效11位手机号 ...
- Ajax Control Toolkit 34个服务器端控件的使用
摘自:http://blog.csdn.net/yaoshuyun/article/details/2218633 1. Accordion[功能概述] Accordion可以让你设计多个panel ...
- iOS7 UIWebview加载进度条实现
不同于WKWebview,wk是有自己的加载进度值的,我们可以直接通过kvo检测到,并显示到进度条内. 但如果我们为了适配ios7,只能使用UIWebview了,这里的加载进度,就比较尴尬了 所以我们 ...
- Android开发之探秘蓝牙隐藏API
这次讲得深入些,探讨下蓝牙方面的隐藏API.用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在SDK中给出,那么如何去使用这两项功能呢 ...
- CoreText实现图文混排之文字环绕及点击算法
系列文章: CoreText实现图文混排:http://www.jianshu.com/p/6db3289fb05d CoreText实现图文混排之点击事件:http://www.jianshu.co ...
- 转: javascript动态添加、修改、删除对象的属性和方法
在其他语言中,对象一旦生成,就不可更改了,要为一个对象添加修改成员必须要在对应的类中修改,并重新实例化,而且程序必须经过重新编译.JavaScript 中却非如此,它提供了灵活的机制来修改对象的行为, ...