本项目是在上一篇搭建的SSM框架的基础上做的,同样是一个非maven的传统web项目。
与传统软件行业不同的是,互联网产品多是高并发的。高并发就需要从硬件和软件两方面共同来解决。阿里巴巴的大牛攻城狮们提供了一套解决高并发的框架---Dubbo。看过相关的文章,个人的理解就是,将我们传统所写的单一服务做成Dubbo服务,并将该服务发布注册,阿里dubbo团队推荐的是zookeeper,将dubbo服务注册在zookeeper中,每个dubbo服务都会有服务的发布者和服务的消费者,发布者将服务发布在zookeeper中,消费者去zookeeper中获取自己需要的服务。从而实现程序的解耦。当请求的并发量增加时,采用消息队列,将所有的请求仍在队列中,按照资源的先后顺序请求服务。从而解决高并发的问题。 以上只是个人对于Dubbo粗浅的认识,欢迎纠正。
好了,废话不多说。本文是在同一个项目之下,创建了一个dubbo服务,并用main方法模拟这个服务的消费者。
开始之前 推荐两篇文章,里面详细的讲了 如何配置zookeeper服务器,和dubbo admin服务(查看dubbo服务数量)。这里就不多说了哈。
【Dubbo实战1】http://blog.csdn.net/hejingyuan6/article/details/47403299#t1
【Dubbo实战2】https://www.cnblogs.com/Javame/p/3632473.html
开始正题,在上一篇的搭建好的框架的基础上进行修改。
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>这个 标签可能会报错,处理办法如下:
<dubbo:application>标签报错处理办法:http://blog.csdn.net/gjldwz/article/details/50555922
如果按照上述方法处理完了 还是报错,请查看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服务,欢迎有问题一起探讨。源码下载地址