最近公司項目使用dubbo服務,於是就去網上搜索關於dubbo的相關資料,真的很多,但是對於很多人並不是很瞭解框架或者
不是太適合新手的片段代碼,於是我就根據項目的相關內容把dubbo部分單獨切出來,所有代碼可以運行。推薦先看一下
dubbo的一篇文章http://doc.okbase.net/congcong68/archive/112508.html 。
dubbo的介紹網上已經有很多了,我就不介紹它是什麼了,我主要介紹怎麼在項目中使用,怎麼讓一個小白會在項目中運用起
來,就像買一輛汽車,你肯定是先讓他跑起來,不會先把所有組件拆開來看看是怎麼安裝的吧。(如果你是,那麼恭喜你,你
已經是大神了),文字內容比較膚淺,適合初學者,如果有不當的地方歡迎指出來,留言
下面我就介紹一下我的項目結構
整個項目結構分爲3個部分,dubbo-client 是消費者或者是調用方的代碼(可以理解你自己的代碼),dubbo-service存放的是
dubbo的對外接口,只是接口的定義和基礎實體類已經一些公共工具類,如果你想做的更細,可以把基礎實體類和公共工具類
提取出來放在dubbo-domain中,dubbo-web存放的是dubbo的對外接口的實現和dubbo的生產者的配置信息。
那我們就開始對每個模塊單獨解釋,首先從最基礎的dubbo-service模塊解釋,一層層往上。
這裏我定一個一個User實體類,用於存放用戶基本信息,一個返回結果集的封裝類(可根據自己項目需求而定,不是必須要
有),最後定義一個接口UserService.java和平常的接口並沒有什麼差異,看下具體內容
- package com.lwl.dubbo.service;
- import com.lwl.dubbo.domain.User;
- import com.lwl.dubbo.rpc.RPCResponse;
- /**
- * 用戶的接口
- * @author Administrator
- * @create 2016-8-9 下午2:42:56
- * @version 1.0
- */
- public interface UserService {
- /**
- * 正常調用
- * @param id
- * @return
- * @author Administrator
- * @create 2016-8-9 上午10:16:50
- */
- public RPCResponse<User> findUserById(long id);
- /**
- * 調用該方法會拋出異常
- * @return
- * @author Administrator
- * @create 2016-8-9 上午10:17:33
- */
- public RPCResponse<User> findUserThrowsException();
- }
定義了2個接口方法,第一個方法是根據ID 獲取用戶信息,第二個方法比較特殊,因爲我在實現的時候是讓他直接拋出異常,
這樣比較更加有代表性。好了,dubbo-service這個項目已經結束了,如果你需要更多的接口,請自行添加即可。然後把這項目
maven打包成JAR包供dubbo-web和dubbo-client依賴。
那接下來我們就要讓dubbo服務先啓起來,開啓dubbo-web的項目,首先介紹一下dubbo-web的項目結構
dubbo-web的結構要比dubbo-service複雜一點,但是對於已經開發過J2EE的各位看客來說,這個其實很簡單的。還記得上一
個dubbo-service項目的完成之後我們把他打包成一個JAR包了嘛,這時候我們就有使用這個JAR了,在pom文件中引入這個文
件即可。
然後UserServiceImpl實現dubbo-service接口中的UserService.java接口,接下來就是UserDao和UserDaoImpl這2個和數據庫打
交道的類了,但是我爲了項目整潔去除了和數據庫的交流,如果看客需要則自行添加即可。
那我們看下UserServiceImpl.java幹了什麼事情呢?
- package com.lwl.dubbo.service.impl;
- import javax.annotation.Resource;
- import org.springframework.stereotype.Service;
- import com.lwl.dubbo.dao.UserDao;
- import com.lwl.dubbo.domain.User;
- import com.lwl.dubbo.rpc.RPCResponse;
- import com.lwl.dubbo.service.UserService;
- @Service("userService")
- public class UserServiceImpl implements UserService {
- @Resource(name="userDao")
- private UserDao userDao;
- @Override
- public RPCResponse<User> findUserById(long id) {
- //這裏使用封裝類,而不是DAO繼續使用封裝類,是爲了DAO層更好的複用起來
- RPCResponse<User> response = new RPCResponse<User>();
- try {
- //DAO層和我們之前開發的模式一樣,沒有使用封裝類
- User result = userDao.findUserById(id);
- response.setResult(result);
- } catch (Exception e) {
- e.printStackTrace();
- response.setSuccess(false);
- response.setErrorMessage(e.getMessage());
- }
- return response;
- }
- //調用這個方法 會拋出異常
- @Override
- public RPCResponse<User> findUserThrowsException() {
- RPCResponse<User> response = new RPCResponse<User>();
- try {
- User result = userDao.findUserThrowsException();
- response.setResult(result);
- } catch (Exception e) {
- e.printStackTrace();
- response.setSuccess(false);
- response.setErrorMessage(e.getMessage());
- }
- return response;
- }
- }
看到這個類調用了DAO層的接口,但是DAO層並沒有使用封裝類,這是因爲爲了更好的複用DAO層的代碼,所有就在接口實現層做封裝。
那DAO層的實現層是怎麼實現的呢?
- package com.lwl.dubbo.dao.impl;
- import org.springframework.stereotype.Repository;
- import com.lwl.dubbo.dao.UserDao;
- import com.lwl.dubbo.domain.User;
- /**
- * DAO數據層操作
- * @author Administrator
- * @create 2016-8-9 上午10:30:03
- * @version 1.0
- */
- @Repository("userDao")
- public class UserDaoImpl implements UserDao {
- /**
- * 通過模擬數據庫數據,返回結果
- * 看客可以根據自己需要 從數據庫獲取數據然後返回
- * @param id
- * @return
- * @author Administrator
- * @create 2016-8-9 上午10:31:34
- */
- @Override
- public User findUserById(long id) {
- User info = new User();
- info.setId(id);
- info.setEmail("[email protected]");
- info.setMobile("13844445555");
- info.setUsername("宇宙最帥");
- info.setPassword("12345600");
- return info;
- }
- @Override
- public User findUserThrowsException() {
- //讓程序出錯,便於返回測試
- int i = 1/0;
- System.out.println(i);
- return null;
- }
- }
和想像的一樣吧,就是我們平常開發中的那些代碼,並沒有什麼特殊。好了代碼都寫完了,接下來纔是重點,怎麼讓他和dubbo服務有關聯,首先當然要引入dubbo的jar包,然後在給服務添加配置
文件。
下面是dubbo的配置文件dubbo_config.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"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://code.alibabatech.com/schema/dubbo
- http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
- <!--
- dubbo:registry 標籤一些屬性的說明:
- 1)register是否向此註冊中心註冊服務,如果設爲false,將只訂閱,不註冊。
- 2)check註冊中心不存在時,是否報錯。
- 3)subscribe是否向此註冊中心訂閱服務,如果設爲false,將只註冊,不訂閱。
- 4)timeout註冊中心請求超時時間(毫秒)。
- 5)address可以Zookeeper集羣配置,地址可以多個以逗號隔開等。
- dubbo:service標籤的一些屬性說明:
- 1)interface服務接口的路徑
- 2)ref引用對應的實現類的Bean的ID
- 3)registry向指定註冊中心註冊,在多個註冊中心時使用,值爲<dubbo:registry>的id屬性,多個註冊中心ID用逗號分隔,如果不想將該服務註冊到任何registry,可將值設爲N/A
- 4)register 默認true ,該協議的服務是否註冊到註冊中心。
- -->
- <!-- 提供方應用信息,用於計算依賴關係 -->
- <dubbo:application name="dobbu-web"/>
- <dubbo:registry address="N/A"/>
- <!-- 用dubbo協議在20880端口暴露服務 -->
- <dubbo:protocol name="dubbo" port="20880"/>
- <!-- 等待時間,重試2次 -->
- <dubbo:provider timeout="120000" retries="0"/>
- <!-- 啓動時不檢查消費者 -->
- <dubbo:consumer check="false" timeout="120000" retries="0" lazy="true"/>
- <!-- 基礎信息 -->
- <dubbo:service ref="userService"
- interface="com.lwl.dubbo.service.UserService"/>
- </beans>
每個都有註釋,如果對dubbo的標籤不是很明白的看客,可以看看本文一開始推薦的那篇文章看看。接下里就是在applicationContext.xml文件中引入dubbo的配置文件即可:
<import resource="classpath:dubbo_config.xml"/>
好了,dubbo-web的開發已經完成了,現在運行一下,如果沒有問題就打包成WAR包,發佈服務吧!
最後一個dubbo-client項目了,然後你發佈服務了,肯定要有人來訂閱吧,就好像你在賣東西,沒有人來你這裏買,你是不是很
不開心啊。所以服務起來了,我們就要利用起來。
dubbo-client項目看上去和平常項目沒什麼區別,只是多了一個dubbo的配置文件,用於訂閱dubbo服務而已,當然dubbo-clien
t項目也要依賴dubbo的JAR 和 dubbo-service ,將這2個添加到pom文件中。
來我們先看一下項目的結構
項目的關鍵至於dubbo-config配置文件,該文件告訴你訂閱了哪些接口和哪個dubbo服務。項目主要有一個控制器和前端返回封裝類,各自的代碼是:
- package com.lwl.dubbo.controller;
- import javax.annotation.Resource;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.ResponseBody;
- import com.lwl.dubbo.domain.User;
- import com.lwl.dubbo.respone.ResultRespone;
- import com.lwl.dubbo.rpc.RPCResponse;
- import com.lwl.dubbo.service.UserService;
- @Controller
- @RequestMapping("/user")
- public class UserController {
- @Resource(name="userService")
- private UserService userService;
- @ResponseBody
- @RequestMapping(value="/id",method=RequestMethod.POST)
- public ResultRespone findUserById(long id){
- ResultRespone respone = new ResultRespone();
- RPCResponse<User> result = userService.findUserById(id);
- if(result.isSuccess()){
- respone.setData(result.getResult());
- }else{
- respone.setSuccess(false);
- respone.setMsg(result.getErrorMessage());
- }
- return respone;
- }
- @ResponseBody
- @RequestMapping(value="/exception",method=RequestMethod.POST)
- public ResultRespone findUserThrowsException(){
- ResultRespone respone = new ResultRespone();
- RPCResponse<User> result = userService.findUserThrowsException();
- if(result.isSuccess()){
- respone.setData(result.getResult());
- }else{
- respone.setSuccess(false);
- respone.setMsg(result.getErrorMessage());
- }
- return respone;
- }
- }
然後前端使用html + ajax 請求後臺控制器,代碼如下index.html:
- package com.lwl.dubbo.respone;
- /**
- * 用於將結果集返回給前端
- * @author Administrator
- * @create 2016-8-9 下午12:21:24
- * @version 1.0
- */
- public class ResultRespone {
- private boolean success = true;//是否成功
- private String msg;//錯誤信息或者提示信息
- private Object data;//數據結果集
- public boolean isSuccess() {
- return success;
- }
- public void setSuccess(boolean success) {
- this.success = success;
- }
- public String getMsg() {
- return msg;
- }
- public void setMsg(String msg) {
- this.msg = msg;
- }
- public Object getData() {
- return data;
- }
- public void setData(Object data) {
- this.data = data;
- }
- }
運行結果:
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <script type="text/javascript" src="resources/jquery-1.8.3.min.js"></script>
- </head>
- <body>
- <input type="button" value="根據ID獲取用戶對象" id="findUserById" />
- <input type="button" value="findUserThrowsException" id="findUserThrowsException" />
- <script type="text/javascript">
- $("#findUserById").click(function(){
- var data = {id : 102};
- ajaxDo("/dubbo-client/user/id",data);
- });
- $("#findUserThrowsException").click(function(){
- ajaxDo("/dubbo-client/user/exception",null);
- });
- function ajaxDo(url,data){
- $.ajax({
- url:url ,
- type: "post",
- dataType: "json",
- data: data,
- success:function(result){
- if(result.success){
- var obj = JSON.stringify(result.data);
- alert(obj);
- }else{
- alert(result.msg);
- }
- }
- });
- }
- </script>
- </body>
- </html>
好了,整個dubbo的服務以及完成了,稍後會將使用的代碼上傳到GIT上,到時候如果有需要的看客可以自己去查看,我也只是一個初學者,如果有不當的地方請指出來,文字內容比較淺,膚淺,沒什麼深奧的,我只是希望能幫到那些不知道怎麼用的
人。
項目已經上傳到github上,有需要的可以移步到https://github.com/1181888200/dubbo.git