简介
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