1. 程式人生 > >【SSM框架】Spring整合Dubbo服務(附帶原始碼)

【SSM框架】Spring整合Dubbo服務(附帶原始碼)

        本專案是在上一篇搭建的SSM框架的基礎上做的,同樣是一個非maven的傳統web專案。

與傳統軟體行業不同的是,網際網路產品多是高併發的。高併發就需要從硬體和軟體兩方面共同來解決。阿里巴巴的大牛攻城獅們提供了一套解決高併發的框架---Dubbo。看過相關的文章,個人的理解就是,將我們傳統所寫的單一服務做成Dubbo服務,並將該服務釋出註冊,阿里dubbo團隊推薦的是zookeeper,將dubbo服務註冊在zookeeper中,每個dubbo服務都會有服務的釋出者和服務的消費者,釋出者將服務釋出在zookeeper中,消費者去zookeeper中獲取自己需要的服務。從而實現程式的解耦。當請求的併發量增加時,採用訊息佇列,將所有的請求仍在佇列中,按照資源的先後順序請求服務。從而解決高併發的問題。 以上只是個人對於Dubbo粗淺的認識,歡迎糾正。

        好了,廢話不多說。本文是在同一個專案之下,建立了一個dubbo服務,並用main方法模擬這個服務的消費者。

開始之前 推薦兩篇文章,裡面詳細的講了 如何配置zookeeper伺服器,和dubbo admin服務(檢視dubbo服務數量)。這裡就不多說了哈。

        開始正題,在上一篇的搭建好的框架的基礎上進行修改。

1、建立Dubbo單獨的程式碼包

  建立單獨的程式碼包,將原先的Test下的包移到這個下面。


  建立DubboAppNewsService介面類:

注意:@Server是org.springframework.stereotype.Service包下的,不是 dubbo包下的。

package com.weikai.dubboServer.service;


import org.springframework.stereotype.Service;

import com.weikai.common.AppReply;
import com.weikai.dubboServer.entity.DubboAppNews;

@Service
public interface DubboAppNewsService {

	public AppReply<DubboAppNews> findAll(String pageSize,String pageNumber);
}

  建立DubboAppNewsService介面實現類DubboAppNewsServiceImpl:
package com.weikai.dubboServer.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.weikai.common.AppReply;
import com.weikai.dubboServer.dao.DubboAppNewsDao;
import com.weikai.dubboServer.entity.DubboAppNews;
import com.weikai.dubboServer.service.DubboAppNewsService;
import com.weikai.test.entity.AppNews;

@Service
public class DubboAppNewsServiceImpl implements DubboAppNewsService {
	
	@Resource
	private DubboAppNewsDao dao;
	
	@Override
	@SuppressWarnings("null")
	public AppReply<DubboAppNews> findAll(String pageSize,String pageNumber){
		AppReply<DubboAppNews> reply = new AppReply<DubboAppNews>();
		Map<String, Object> parpam = new HashMap<String, Object>();
		List<AppNews> appList = null;
		parpam.put("pageNumber", (Integer.parseInt(pageNumber)-1) * Integer.parseInt(pageSize));
		parpam.put("pageSize", Integer.valueOf(pageSize));
		appList = dao.findAll(parpam);
		if(appList != null || appList.size() > 0){
			reply.setCode("0");
			reply.setMsg("查詢資料成功!");
			reply.setObj(appList);
		}else{
			reply.setCode("1");
			reply.setMsg("查詢資料為空!");
			reply.setObj(new ArrayList<AppNews>());
		}
		return reply;
	}
}

  建立DubboAppNewsDao介面和對應表的實體類:

  實體類是資料庫中自己的表,這裡就不展示實體類了,可以根據自己專案的實際情況修改這兩部分內容。同時記得修改mapper檔案。

package com.weikai.dubboServer.dao;

import java.util.List;
import java.util.Map;

import com.weikai.test.entity.AppNews;

public interface DubboAppNewsDao {
	
	public List<AppNews> findAll(Map<String, Object> parpam);
}


2、注入dubbo服務提供者

  建立好service層後,需要將service層注入到Spring中 並做成dubbo服務,對外暴露介面。

  首先建立一個spring-context-dubbo-myProvider.xml,這裡注意名字,因為之前的專案web.xml中是採用萬用字元配置的,所以這個時候只需要起名為spring-context-*.xml即可,並且不用在配置web.xml檔案。

spring-context-dubbo-myProvider.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服務,具體的實現bean -->  
    <bean id="dubboProvider" class="com.weikai.dubboServer.service.impl.DubboAppNewsServiceImpl" />  
    <!-- 提供方應用資訊,用於計算依賴關係 -->  
    <dubbo:application name="dubboProviderRef" />  
  
    <!-- 使用multicast廣播註冊中心暴露服務地址 -->  
    <!--<dubbo:registry address="multicast://224.5.6.7:1234" /> -->  
      
    <!-- 使用zookeeper註冊中心暴露服務地址  即zookeeper的所在伺服器ip地址和埠號 -->  
    <dubbo:registry address="zookeeper://172.16.67.183:2181" />  
  
    <!-- 用dubbo協議在20880埠暴露服務 -->  
    <dubbo:protocol name="dubbo" port="20888" />  

  <!-- 宣告需要暴露的服務介面 -->  
    <dubbo:service interface="com.weikai.dubboServer.service.DubboAppNewsService"  
        ref="dubboProvider" /> 
</beans>  

        這裡會出現一個問題,就是<dubbo:application>這個 標籤可能會報錯,處理辦法如下:

如果按照上述方法處理完了 還是報錯,請檢視xml中是否引入xmlns:dubbo="http://code.alibabatech.com/schema/dubbo 等標籤引入語句。

至此服務者已經處理完畢,啟動服務 即可在Dubbo admin中檢視到服務資訊。可以看到這個服務目前是沒有 消費者的。


3、建立消費者類。

    服務已經發布,必須要有消費者呼叫,所以我們在單個專案中使用main()方法呼叫服務。建立GetNewsConsumer這個類。並帶main方法。

    GetNewsConsumer類:

package com.weikai.dubboConsumer;

import java.util.List;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.weikai.common.AppReply;
import com.weikai.dubboServer.entity.DubboAppNews;
import com.weikai.dubboServer.service.DubboAppNewsService;


public class GetNewsConsumer {
	
	public static void main(String[] args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-dubbo-myConsumer.xml");
		String pageSize = "10";
		String pageNumber = "1";
		 ctx.start();
		 DubboAppNewsService dubboAppNewsService = (DubboAppNewsService) ctx.getBean("dubboProviderRef");
		AppReply<DubboAppNews> appReply = dubboAppNewsService.findAll(pageSize, pageNumber);
		@SuppressWarnings("unchecked")
		List<DubboAppNews> news = (List<DubboAppNews>)appReply.getObj();
		for (int i = 0; i < news.size(); i++) {
			System.out.print(news.get(i).getId());
			System.out.print("\t");
			System.out.print(news.get(i).getKeyword());
			System.out.print("\t");
			System.out.print(news.get(i).getTitle());
			System.out.print("\t");
			System.out.print(news.get(i).getThumbnailL());
			System.out.print("\t");
			System.out.print(news.get(i).getThumbnailM());
			System.out.print("\t");
			System.out.print(news.get(i).getDescrption());
			System.out.print("\t");
			System.out.print(news.get(i).getContent());
			System.out.println();
		}
		try {
			Thread.sleep(500000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		ctx.close();
	} 
	
}

4、將消費者註冊到容器中

        建立spring-dubbo-myConsumer.xml配置檔案,將消費者註冊到伺服器中。注意取名不能取spring-context-*開頭,因為這樣按照我們之前的配置Spring就會同時載入服務者和消費者這樣就會導致dubbo檔案兩次載入從而報錯。在同一個專案下部署dubbo時一定保證服務著在Spring啟動的時候 就啟動,而消費者 則在容器啟動後 再載入。 

spring-dubbo-myConsumer.xml檔案內容:

注意:服務者和消費者必須公用API,即必須指向同一個service。

<?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:application name="dubboConsumer" />  
  
    <!-- 使用zookeeper註冊中心暴露服務地址 -->  
    <!-- <dubbo:registry address="multicast://224.5.6.7:1234" /> -->  
    <dubbo:registry address="zookeeper://172.16.67.183:2181" />  
  
  	 <!-- 用dubbo協議在20880埠暴露服務 -->  
    <dubbo:protocol name="dubbo" port="20888" />  
  
    <!-- 生成遠端服務代理,可以像使用本地bean一樣使用demoService -->  
    <dubbo:reference id="dubboProviderRef"  
        interface="com.weikai.dubboServer.service.DubboAppNewsService" />  
</beans>  


4、測試

        測試步驟:

         1、啟動web專案,保證啟動不報錯,並在 dubbo admin中能夠看到釋出的服務。

          2、執行main方法。呼叫服務。

         啟動專案之前zookeeper服務必須啟動!!!

         測試結果:

    dubbo admin介面:

    由於我們短時間 執行了三次main方法,所以這裡會有三個消費者。


SSM完美集成了Dubbo服務,歡迎有問題一起探討。