使用Springboot开发系统配置工作简洁,提供丰富的注解,开发工程师可以快速完成项目的开发工作,不仅提高项目开发效率,系统维护工作也更加简化,本例使用SpringBoot完成多对多的案例,本例要求表单数据必须保持到消息服务器RabbitMQ中,设计定时器从队列中获取消息并解析到数据库,所有与数据库操作的业务模块要求使用Dubbo服务完成,也就是Web端系统只包含Spring Controller层业务逻辑,Mapper层和Service层都由Dubbo托管,这样设计是为了提供项目高可用和负载均衡,Dubbo服务可以利用Dubbo框架提供集群服务。

本例要求:

  1. 安装Dubbo注册中心ZooKeeper
  2. 安装RabbitMQ服务
  3. 可选部署Dubbo控制台程序

架构图

Dubbo服务端程序

新建Maven POM文件


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>GuFang</groupId><artifactId>HrServer</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>HrServer</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.9.RELEASE</version><relativePath/></parent><dependencies><dependency><groupId>com.alibaba.spring.boot</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>1.0.1</version></dependency><!-- <dependency><groupId>com.alibaba.spring.boot</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.0.1-SNAPSHOT</version></dependency>--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.0</version></dependency><dependency><groupId>com.101tec</groupId><artifactId>zkclient</artifactId><version>0.10</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.11</version><exclusions><exclusion>  <groupId>com.alibaba</groupId><artifactId>jconsole</artifactId></exclusion>  <exclusion><groupId>com.alibaba</groupId><artifactId>tools</artifactId></exclusion></exclusions></dependency><dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <dependency><groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- 分页插件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.1.2</version></dependency></dependencies>
</project>

Application.yml配置文件

server:port: 9090context-path: /spring:#Dubbo 1.0.1集成dubbo:appname: dubbo-serviceregistry: zookeeper://192.168.137.1:2181protocol: dubboport: 20880#Dubbo 2.1.0集成
#  dubbo:
#    application:
#      name: dubbo-service
#    registry:
#      address: zookeeper://192.168.137.1:2181
#    protocol:
#      name: dubbo
#      port: 20880#数据源配置datasource:name: w1url: jdbc:mysql://127.0.0.1:3306/w1?useUnicode=true&characterEncoding=utf8username: rootpassword: roottype: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.DrivermaxActive: 20initialSize: 1maxWait: 60000minIdle: 1#Mybatis实体类配置
mybatis:mapper-locations: classpath:mapper/*.xml

新建实体类
MenuInfo.java 菜单表实体类

package com.test.bean;import java.io.Serializable;//菜单表实体类
public class MenuInfo implements Serializable{private Integer id = null;private String name = null;private Integer price = null;//冗余字段,存放材料名称,以逗号分隔private String sname = null;//冗余字段,存放材料ID,以逗号分隔private String sid = null;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getPrice() {return price;}public void setPrice(Integer price) {this.price = price;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}public String getSid() {return sid;}public void setSid(String sid) {this.sid = sid;}}

StaffInfo.java 材料表实体类

package com.test.bean;import java.io.Serializable;//材料表实体类
public class StaffInfo  implements Serializable{private Integer id = null;private String name = null;//冗余字段,代表前台页面Checkbox控件是否选中,true为选中private String checked = "";public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getChecked() {return checked;}public void setChecked(String checked) {this.checked = checked;}}

M2SInfo.java 中间关联表(关联菜单与材料表,实现多对多业务)

package com.test.bean;import java.io.Serializable;//菜单关联材料的实体类
public class M2SInfo  implements Serializable{//菜单表IDprivate Integer mid = null;//材料表IDprivate Integer sid = null;public Integer getMid() {return mid;}public void setMid(Integer mid) {this.mid = mid;}public Integer getSid() {return sid;}public void setSid(Integer sid) {this.sid = sid;}}

新建Mybatis Mapper.xml
Mapper.xml文件需要位于src/main/resources/mapper目录下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mapper.MenuMapper"><select id="findMenu" resultType="com.test.bean.MenuInfo">select * from t_menu where name like '%${name}%'</select><select id="findStaff" resultType="com.test.bean.StaffInfo">select * from t_staff</select><insert id="saveMenu" parameterType="com.test.bean.MenuInfo"useGeneratedKeys="true" keyColumn="id" keyProperty="id">insert into t_menu(name,price) values(#{name},#{price})</insert><update id="updateMenu" parameterType="com.test.bean.MenuInfo">update t_menu set name=#{name},price=#{price} where id=#{id}</update><delete id="deleteMenu" parameterType="Integer">delete from t_menu where id=#{id}</delete><insert id="saveM2S" parameterType="com.test.bean.M2SInfo">insert into t_m2s(mid,sid) values(#{mid},#{sid})</insert><delete id="deleteM2S" parameterType="Integer">delete from t_m2s where mid=#{id}</delete><select id="findMenu2" resultType="com.test.bean.MenuInfo">select a.*,b.sname,b.sid from t_menu a left join(select group_concat(s.name) sname,group_concat(s.id) sid,m2s.mid from t_staff s,t_m2s m2s where s.id=m2s.sid group by m2s.mid) bon a.id=b.mid where a.name like '%${name}%' or b.sname like '%${name}%'</select><select id="getMenuById" resultType="com.test.bean.MenuInfo">select a.*,b.sname,b.sid from t_menu a left join(select group_concat(s.name) sname,group_concat(s.id) sid,m2s.mid from t_staff s,t_m2s m2s where s.id=m2s.sid group by m2s.mid) bon a.id=b.mid where a.id=#{id}</select>
</mapper>

数据库SQL脚本

create table t_menu(id int auto_increment primary key,name varchar(40),price int);create table t_staff(id int auto_increment primary key,name varchar(40));create table t_m2s(mid int,sid int);insert into t_staff(name) values('鸡肉');
insert into t_staff(name) values('花生米');
insert into t_staff(name) values('猪肉');
insert into t_staff(name) values('木耳');insert into t_menu(name,price) value('宫保鸡丁',18);
insert into t_menu(name,price) value('土豆丝',20);insert into t_m2s (mid,sid) values (1,1);
insert into t_m2s (mid,sid) values (1,4);insert into t_m2s (mid,sid) values (2,2);
insert into t_m2s (mid,sid) values (2,3);关联中间表与材料表,获取材料名称,材料ID和菜单IDselect s.name,s.id,m2s.mid from t_staff s,t_m2s m2s where s.id=m2s.sidselect group_concat(s.name) sname,group_concat(s.id) sid,m2s.mid from t_staff s,t_m2s m2s where s.id=m2s.sid group by m2s.midselect a.*,b.sname,b.sid from t_menu a left join
(select group_concat(s.name) sname,group_concat(s.id) sid,m2s.mid from t_staff s,t_m2s m2s where s.id=m2s.sid group by m2s.mid) b
on a.id=b.mid;

新建Mybatis接口
MenuMapper.java需要创建在包com.test.mapper下

package com.test.mapper;import java.util.List;import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import com.test.bean.M2SInfo;
import com.test.bean.MenuInfo;
import com.test.bean.StaffInfo;//Mybatis接口主键,Springboot自动扫描
@Mapper
public interface MenuMapper {//根据菜单名称查询菜单结果,@Param("name")标注参数名可以使用在SQL语句中public List<MenuInfo> findMenu(@Param("name") String name);//返回全部材料列表public List<StaffInfo> findStaff();//保存菜单对象public void saveMenu(MenuInfo mi);//更新菜单对象public void updateMenu(MenuInfo mi);//根据菜单ID删除记录,@Param("id")标注参数名可以使用在SQL中public void deleteMenu(@Param("id") Integer mid);//保存中间表public void saveM2S(M2SInfo m2s);//根据菜单ID删除中间表public void deleteM2S(@Param("id") Integer mid);//返回多表关联查询数据public List<MenuInfo> findMenu2(@Param("name") String name);//根据菜单ID返回菜单对象,需要多表关联查询public MenuInfo getMenuById(@Param("id") Integer mid);
}

新建服务类接口
MenuService.java 创建在包com.test.service下

package com.test.service;import java.util.List;import org.apache.ibatis.annotations.Param;import com.github.pagehelper.PageInfo;
import com.test.bean.M2SInfo;
import com.test.bean.MenuInfo;
import com.test.bean.StaffInfo;public interface IMenuService {//根据菜单名称查询菜单结果public List<MenuInfo> findMenu(String name);//返回全部材料列表public List<StaffInfo> findStaff();//保存菜单对象,返回保存对象,使用Dubbo远程调用需要返回对象IDpublic MenuInfo saveMenu(MenuInfo mi);//更新菜单对象public void updateMenu(MenuInfo mi);//根据菜单ID删除记录public void deleteMenu(Integer mid);//保存中间表public void saveM2S(M2SInfo m2s);//根据菜单ID删除中间表public void deleteM2S(Integer mid);//返回多表关联查询数据public List<MenuInfo> findMenu2(String name);//根据菜单ID返回菜单对象,需要多表关联查询public MenuInfo getMenuById(Integer mid);//返回分页菜单数据public PageInfo getPageMenu(String name,Integer page,Integer rows);
}

新建服务实现类
MenuServiceImpl.java 创建在包com.test.service.impl下

package com.test.service.impl;import java.util.List;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.test.bean.M2SInfo;
import com.test.bean.MenuInfo;
import com.test.bean.StaffInfo;
import com.test.mapper.MenuMapper;
import com.test.service.IMenuService;//Dubbo服务注解
@com.alibaba.dubbo.config.annotation.Service(interfaceClass = IMenuService.class)
//Spring服务主键
@Service
public class MenuServiceImpl implements IMenuService{private Logger log = LoggerFactory.getLogger(MenuServiceImpl.class);//注入Mapper对象@Autowiredprivate MenuMapper mapper;//@Transactional代表需要开启事务控制@Override@Transactional(readOnly=true,propagation=Propagation.REQUIRES_NEW)public List<MenuInfo> findMenu(String name) {return mapper.findMenu(name);}@Override@Transactional(readOnly=true,propagation=Propagation.REQUIRES_NEW)public PageInfo getPageMenu(String name,Integer page,Integer rows) {System.out.println("name="+name+",page="+page+",rows="+rows);PageHelper.startPage(page, rows);List<MenuInfo> menuList = findMenu2(name);PageInfo pi = new PageInfo(menuList);return pi;}@Overridepublic List<StaffInfo> findStaff() {return mapper.findStaff();}@Transactional@Overridepublic MenuInfo saveMenu(MenuInfo mi) {mapper.saveMenu(mi);return mi;}@Overridepublic void updateMenu(MenuInfo mi) {mapper.updateMenu(mi);}@Overridepublic void deleteMenu(Integer mid) {mapper.deleteMenu(mid);}@Overridepublic void saveM2S(M2SInfo m2s) {mapper.saveM2S(m2s);}@Overridepublic void deleteM2S(Integer mid) {mapper.deleteM2S(mid);}@Overridepublic List<MenuInfo> findMenu2(String name) {return mapper.findMenu2(name);}@Overridepublic MenuInfo getMenuById(Integer mid) {return mapper.getMenuById(mid);}}

创建SpringBoot启动类
Starter.java,它最好放置在根包目录,这样可以省略很多注解配置工作

package com.test;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;//SpringBoot核心注解,自动扫描本来所在包下的所有子包
//相当于@Configuration + @EnableAutoConfiguration + @ComponentScan
@SpringBootApplication
//开启Dubbo配置
@EnableDubboConfiguration
public class Starter {public static void main(String[] args) {SpringApplication.run(Starter.class, args);}
}

启动Dubbo服务

在Zookeeper服务注册信息

SpringBoot Web端系统

新建Maven webapp项目

POM.xml文件配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.test</groupId><artifactId>Test_DubboWeb</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>Test_DubboWeb Maven Webapp</name><url>http://maven.apache.org</url><!-- 定义公共资源版本 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.6.RELEASE</version><relativePath/> </parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 添加springboot对AOP的支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!-- 添加springboot对redis的支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 添加springboot对freemarker的支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><!-- 添加springboot对测试的支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!-- 添加springboot对在线开发的支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional><scope>true</scope></dependency><!-- 添加springboot对amqp的支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <!--<scope>provided</scope>--></dependency> <dependency><groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency><!-- <dependency><groupId>com.alibaba.spring.boot</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.0.1-SNAPSHOT</version></dependency>--><dependency><groupId>com.alibaba.spring.boot</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>1.0.1</version></dependency><dependency><groupId>com.101tec</groupId><artifactId>zkclient</artifactId><version>0.10</version></dependency><!-- 分页插件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.1.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.11</version><exclusions><exclusion>  <groupId>com.alibaba</groupId><artifactId>jconsole</artifactId></exclusion>  <exclusion><groupId>com.alibaba</groupId><artifactId>tools</artifactId></exclusion></exclusions></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency></dependencies><build><finalName>Test_DubboWeb</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork>true</fork></configuration></plugin></plugins></build>
</project>

Application.properties 文件配置

#SpringBoot启动端口和项目路径
server.port=6060
server.context-path=/#spring.resources.static-locations=/css,/images,/img,/js#SpringMVC中JSP视图配置
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp#Http编码配置
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true#Rabbitmq消息服务器配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/#数据源配置
spring.datasource.name=w1
spring.datasource.url=jdbc:mysql://localhost:3306/w1?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.maxActive=20
spring.datasource.initialSize=1
spring.datasource.maxWait=60000
spring.datasource.minIdle=1#Dubbo 1.0.1集成
spring.dubbo.appname=dubbo-consumer
spring.dubbo.registry=zookeeper://192.168.137.1:2181
spring.dubbo.protocol=dubbo
spring.dubbo.port=20880#Dubbo 2.1.0集成
#spring.dubbo.application.name=dubbo-consumer
#spring.dubbo.registry.address=zookeeper://192.168.137.1:2181
#spring.dubbo.protocol.name=dubbo
#spring.dubbo.protocol.port=20880#日志配置
logging.file=d:/springboot.log
logging.level.com.test.mapper=INFO
logging.level.com.hk.servlet=DEBUG
logging.level.com.test.service.impl=DEBUG

新建Dubbo.properties配置文件,位于src/main/resources目录下

#Dubbo QOS Server Port
dubbo.qos.port=20221

Dubbo服务接口类可以在Web端新建,也可导入Dubbo服务的Jar包

新建Controller类

package com.test.ctrl;import java.util.List;import javax.servlet.http.HttpServletRequest;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import com.alibaba.dubbo.config.annotation.Reference;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.test.bean.MenuInfo;
import com.test.bean.StaffInfo;
import com.test.service.IMenuService;
import com.test.util.PageUtil;@Controller
public class MenuCtrl {@Reference(check=false)private IMenuService serv;@Autowiredprivate SendMsg sendmsg;@RequestMapping("/test")public String test(HttpServletRequest req,Integer page,Integer rows){return "add";}//跳转菜单列表的方法//接收前台参数page,rows@RequestMapping("/list")public String list(HttpServletRequest req,Integer page,Integer rows){if(page == null)page = 1;if(rows == null)rows = 4;String name = req.getParameter("name");return toListPage(req,page,rows,name);}@ResponseBody@RequestMapping("/list2")public List<MenuInfo> list2(HttpServletRequest req,Integer page,Integer rows){if(page == null)page = 1;if(rows == null)rows = 4;PageInfo pi = serv.getPageMenu("", page, rows);List<MenuInfo> menuList2 = pi.getList();//当前页显示记录集合return menuList2;}//删除方法,通过id删除菜单和中间表@RequestMapping("/delete")public String delete(HttpServletRequest req,Integer page,Integer rows){if(page == null)page = 1;if(rows == null)rows = 4;String[] ids = req.getParameterValues("id");if(ids != null){for(String id:ids){Integer mid = new Integer(id);serv.deleteMenu(mid);serv.deleteM2S(mid);}}return toListPage(req,1,4,null);}//跳转到新增页面@RequestMapping("/add")public String add(HttpServletRequest req){List<StaffInfo> staffList = serv.findStaff();req.setAttribute("staffList", staffList);return "add";}//跳转到修改页面@RequestMapping("/modify")public String modify(HttpServletRequest req){String id = req.getParameter("id");Integer mid = new Integer(id);MenuInfo menu = serv.getMenuById(mid);req.setAttribute("menu", menu);String sid = menu.getSid();//1,2,3System.out.println("sid="+sid);List<StaffInfo> staffList = serv.findStaff();for(StaffInfo si:staffList){String sid2 = si.getId().toString();if(sid.indexOf(sid2)>=0)si.setChecked("checked");}req.setAttribute("staffList", staffList);return "add";}//跳转到查看页面@RequestMapping("/view")public String view(HttpServletRequest req){String id = req.getParameter("id");Integer mid = new Integer(id);MenuInfo menu = serv.getMenuById(mid);req.setAttribute("menu", menu);String sid = menu.getSid();//1,2,3System.out.println("sid="+sid);List<StaffInfo> staffList = serv.findStaff();for(StaffInfo si:staffList){String sid2 = si.getId().toString();if(sid.indexOf(sid2)>=0)si.setChecked("checked");}req.setAttribute("staffList", staffList);return "view";}//保存菜单数据到Rabbitmq队列,返回到列表页面@RequestMapping("/save")public String save(HttpServletRequest req,MenuInfo mi){sendmsg.send(mi);return toListPage(req,1,4,null);}//公共方法,统一返回到列表页面private String toListPage(HttpServletRequest req,Integer page,Integer rows,String name){if(page == null)page = 1;if(rows == null)rows = 4;if(name == null)name = "";System.out.println("page===="+page+",rows==="+rows+",name="+name);PageInfo pi = serv.getPageMenu(name, page, rows);List<MenuInfo> menuList2 = pi.getList();//当前页显示记录集合Long total = pi.getTotal();//数据库表全部记录数req.setAttribute("menuList", menuList2);System.out.println("menuList2===="+menuList2.size());String url = "/list";PageUtil pu = new PageUtil(url,page,rows,total);req.setAttribute("pageDiv", pu.toHtml());req.setAttribute("name", name);return "menu";}
}

新建集成Rabbitmq工具类

package com.test.ctrl;import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import com.test.bean.MenuInfo;
import com.test.util.RabbitmqConf;@Component
public class SendMsg {@Autowiredprivate AmqpTemplate amqp;public void send(MenuInfo mi){amqp.convertAndSend(RabbitmqConf.QUEUE1,mi);}
}

RabbitMq消息接收器可以有两种方式,可以通过定时器接收消息并处理,也可以设计监听器接受消息并处理,两种处理消息方式是互斥的

定时器消息接收器

package com.test.util;import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import com.alibaba.dubbo.config.annotation.Reference;
import com.rabbitmq.client.ConnectionFactory;
import com.test.bean.M2SInfo;
import com.test.bean.MenuInfo;
import com.test.service.IMenuService;@Component
public class CrontabGetMsg {@Autowiredprivate AmqpTemplate amqp;@Reference(check=false)private IMenuService serv;//秒 分 时 日 月 周 年//每五秒接收一次消息@Scheduled(cron="0/5 * * ? * *")public void getMsg(){//System.out.println("getMsg() "+new java.sql.Timestamp(System.currentTimeMillis()));try{Message msg = amqp.receive(RabbitmqConf.QUEUE1);if(msg == null)return;byte[] data = msg.getBody();Object obj = toObject(data);if(obj instanceof MenuInfo){MenuInfo mi = (MenuInfo)obj;String sid = mi.getSid();Integer id = mi.getId();System.out.println("getMsg id="+id+",name="+mi.getName()+",sid="+sid);if(id == null)//新增{mi = serv.saveMenu(mi);System.out.println("saveMenu genId = "+mi.getId());}else//更新{serv.updateMenu(mi);//删除原来关联中间表数据serv.deleteM2S(mi.getId());}String[] dim = sid.split(",");for(String sid2:dim){M2SInfo m2s = new M2SInfo();m2s.setSid(new Integer(sid2));m2s.setMid(mi.getId());serv.saveM2S(m2s);}}}catch(Exception e){e.printStackTrace();}}public Object toObject(byte[] data){try{ByteArrayInputStream bais = new ByteArrayInputStream(data);ObjectInputStream ois = new ObjectInputStream(bais);Object obj = ois.readObject();bais.close();return obj;}catch(Exception e){e.printStackTrace();}return null;}}

消息监听器

package com.test.util;import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import com.test.bean.M2SInfo;
import com.test.bean.MenuInfo;
import com.test.service.IMenuService;@Component
public class RabbitmqListener {@Autowiredprivate IMenuService serv;@RabbitListener(queues="test_queue1")public void receive(Message msg){try{byte[] data = msg.getBody();Object obj = toObject(data);if(obj instanceof MenuInfo){MenuInfo mi = (MenuInfo)obj;String sid = mi.getSid();Integer id = mi.getId();System.out.println("getMsg id="+id+",name="+mi.getName());if(id == null)//新增{serv.saveMenu(mi);}else//更新{serv.updateMenu(mi);//删除原来关联中间表数据serv.deleteM2S(mi.getId());}String[] dim = sid.split(",");for(String sid2:dim){M2SInfo m2s = new M2SInfo();m2s.setSid(new Integer(sid2));m2s.setMid(mi.getId());serv.saveM2S(m2s);}}}catch(Exception e){e.printStackTrace();}}public Object toObject(byte[] data){try{ByteArrayInputStream bais = new ByteArrayInputStream(data);ObjectInputStream ois = new ObjectInputStream(bais);Object obj = ois.readObject();bais.close();return obj;}catch(Exception e){e.printStackTrace();}return null;}
}

RabbitMq配置类,配置交换机与队列

package com.test.util;import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitmqConf {public static String QUEUE1 = "test_queue1";public static String EXCHANGE1 = "test_exg1";@Beanpublic Queue queue1(){return new Queue(QUEUE1);}@Beanpublic DirectExchange exg1(){return new DirectExchange(EXCHANGE1);}@Beanpublic Binding directBinding1() {return BindingBuilder.bind(queue1()).to(exg1()).with("java");}}

编写分页工具类

package com.test.util;public class PageUtil {private Integer page = 1;//默认显示第一页private Integer rows = 4;//每页显示记录数private Long total = null;//总行数private String url = null;//点击页码跳转urlpublic PageUtil(String url,Integer page,Integer rows,Long total){this.url = url;this.page = page;this.rows = rows;this.total = total;}public String toHtml(){StringBuffer sb = new StringBuffer();//计算总页数int pages = 0;if(total % rows == 0)pages = total.intValue() / rows;elsepages = (total.intValue() / rows) + 1;sb.append("<div id='pagediv'>\r\n");String firstUrl = null;if(url.indexOf("?")>0)firstUrl = url + "&page=1&rows="+rows;elsefirstUrl = url + "?page=1&rows="+rows;sb.append("<a href='"+firstUrl+"'>首页</a>\r\n");String backUrl = null;if(url.indexOf("?")>0)backUrl = url + "&page="+(page==1?1:(page-1))+"&rows="+rows;elsebackUrl = url + "?page="+(page==1?1:(page-1))+"&rows="+rows;sb.append("<a href='"+backUrl+"'>上一页</a>\r\n");for(int i=1;i<=pages;i++){String pageUrl = null;if(url.indexOf("?")>0)pageUrl = url + "&page="+i+"&rows="+rows;elsepageUrl = url + "?page="+i+"&rows="+rows;if(i == page)sb.append("<a href='"+pageUrl+"'><b><font color='red'>"+i+"</font></b></a>\r\n");elsesb.append("<a href='"+pageUrl+"'>"+i+"</a>\r\n");}String nextUrl = null;if(url.indexOf("?")>0)nextUrl = url + "&page="+(page==pages?pages:(page+1))+"&rows="+rows;elsenextUrl = url + "?page="+(page==pages?pages:(page+1))+"&rows="+rows;sb.append("<a href='"+nextUrl+"'>下一页</a>\r\n");String lastUrl = null;if(url.indexOf("?")>0)lastUrl = url + "&page="+pages+"&rows="+rows;elselastUrl = url + "?page="+pages+"&rows="+rows;sb.append("<a href='"+lastUrl+"'>尾页</a>\r\n");sb.append("&nbsp;&nbsp;&nbsp;&nbsp;第"+page+"/"+pages+"页\r\n");sb.append("&nbsp;&nbsp;&nbsp;&nbsp;共"+total+"条记录\r\n");sb.append("</div>\r\n");return sb.toString();}
}

菜单页面

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!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">
<title>菜单列表</title>
<link rel="stylesheet" type="text/css" href="/js/base.css">
<script type="text/javascript" src="/js/jquery.min.js"></script>
<script>function doquery()
{listfrm.submit();
}
function dodelete()
{listfrm.action = '/delete'listfrm.submit();
}
function selectall()
{$('input[name="id"]').each(function(){this.checked = $('#idall').prop("checked");})
}
function doadd()
{var url = '/add';window.open(url,'_self');
}
function doedit(id)
{var url = '/modify?id='+id;window.open(url,'_self');
}
function doview(id)
{var url = '/view?id='+id;window.open(url,'_self');
}
function dorefresh()
{var url = '/list';window.open(url,'_self');
}
function dosingledel(id)
{listfrm.action = '/delete?id='+idlistfrm.submit();
}</script>
</head>
<body>
<form id="listfrm" action="/list" method="post">
<input type="text" id="name" name="name" value="${name }"/>
<input type="button" onclick="doquery()" value="查询"/>
<input type="button" onclick="dodelete()" value="批量删除"/>
<input type="button" onclick="doadd()" value="添加"/>
<input type="button" onclick="dorefresh()" value="刷新"/>
<table><tr><th><input type="checkbox" id="idall" name="idall" onclick="selectall()">全选</th><th>编号</th><th>名称</th><th>材料</th><th>价格</th><th>操作</th></tr><c:forEach items="${menuList}" var="m"><tr><td><input type="checkbox" id="id" name="id" value="${m.id }"></td><td>${m.id }</td><td>${m.name }</td><td>${m.sname }</td><td>${m.price }</td><td><input type="button" value="编辑" onclick="doedit(${m.id })"/><input type="button" value="查看" onclick="doview(${m.id })"/><input type="button" value="删除" onclick="dosingledel(${m.id })"/></td></tr></c:forEach>
</table>${pageDiv }
</form>
</body>
</html>

添加页面

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!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">
<title>菜单</title>
<link rel="stylesheet" type="text/css" href="/js/base.css">
<script type="text/javascript" src="/js/jquery.min.js"></script>
<script>function dosave()
{addfrm.submit();
}</script>
</head>
<body>
<form id="addfrm" action="/save" method="post">
<table><input type="hidden" id="id" name="id" value="${menu.id}"/><tr><td>菜单名称</td><td><input type="text" id="name" name="name" value="${menu.name}"/></td></tr><tr><td>价格</td><td><input type="text" id="price" name="price" value="${menu.price}"/></td></tr><tr><td>材料</td><td><c:forEach items="${staffList }" var="s"><input type="checkbox" id="sid" name="sid" value="${s.id }" ${s.checked}>${s.name}</c:forEach></td></tr>
</table>
<input type="button" onclick="dosave()" value="保存">
<input type="button" onclick="window.open('/list','_self')" value="返回">
</form>
</body>
</html>

查看页面

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!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">
<title>菜单</title>
<link rel="stylesheet" type="text/css" href="/js/base.css">
<script type="text/javascript" src="/js/jquery.min.js"></script>
<script>function dosave()
{addfrm.submit();
}</script>
</head>
<body>
<form id="addfrm" action="/save" method="post">
<table><input type="hidden" id="id" name="id" value="${menu.id}"/><tr><td>菜单名称</td><td><input type="text" id="name" name="name" value="${menu.name}"/></td></tr><tr><td>价格</td><td><input type="text" id="price" name="price" value="${menu.price}"/></td></tr><tr><td>材料</td><td><c:forEach items="${staffList }" var="s"><input type="checkbox" id="sid" name="sid" value="${s.id }" ${s.checked}>${s.name}</c:forEach></td></tr>
</table>
<input type="button" onclick="window.open('/list','_self')" value="返回">
</form>
</body>
</html>

通用CSS

@charset "utf-8";
/* CSS Document */body{margin:0 auto;padding:0;  font-family:'Microsoft YaHei', arial, tahoma, \5b8b\4f53, sans-serif;font-size:14px;
}
a {text-decoration:none;color:black;
}
div{margin:0 auto;
}
#pagediv{margin:0 auto;text-align:center;valign:middle;background-color:yellow;height:30px;line-height:30px;border:1px solid black}table {width:100%;font-family:verdana,arial,sans-serif;font-size:11px;color:#333333;border-width:1px;border-color:#666666;border-collapse:collapse;
}
table tr:nth-child(odd) td{background:#ccc;
}
table tr:hover td{background:pink;}
table th {border-width:1px;padding:8px;border-style:solid;border-color:#666666;background-color:yellow;
}
table th {font-size:15px;color:blue;
}
table td {border-width:1px;padding:8px;border-style:solid;border-color:#666666;background-color:#ffffff;
}

Web项目的SpringBoot启动类

package com.test;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;@SpringBootApplication
@EnableDubboConfiguration
public class Starter extends SpringBootServletInitializer{@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application){return application.sources(Starter.class);}public static void main(String[] args) {SpringApplication.run(Starter.class, args);}
}

启动Web项目

测试效果

代码下载
Dubbo Service 代码:https://github.com/qixiangchen/Menu_DubboService.git
Web 代码:https://github.com/qixiangchen/Menu_DubboWeb.git

使用SpringBoot完成RabbitMQ与Dubbo框架集成例程相关推荐

  1. dubbo框架集成spring,springmvc,mybatis框架

    一.建一个接口工程,接口工程名字dubbo-interface dubbo-interface接口工程的pom依赖 <?xml version="1.0" encoding= ...

  2. SpringBoot集成Dubbo框架

    1. Dubbo框架 Dubbo框架是一个高性能.重量轻.基于java的RPC框架.Dubbo提供了三个关键功能,包括基于接口的远程调用.容错和负载平衡,以及自动服务注册和发现.Dubbo可以和Spr ...

  3. 【dubbo】springboot集成dubbo框架

    1. dubbo介绍 dubbo是一款开源rpc框架,提供rpc调用诸多组件.支持服务注册与发现.服务负载均衡.服务容错.服务降级处理.服务失败尝试机制.服务监控等组件. 当我们项目拆分成微服务时,A ...

  4. SpringCloud基础组件总结,与Dubbo框架、SpringBoot框架对比分析

    一.基础组件总结 1.文章阅读目录 1).基础组件 Eureka组件,服务注册与发现 Ribbon和Feign组件,实现负载均衡 Hystrix组件,实现服务熔断 Turbine组件,实现微服务集群监 ...

  5. SpringBoot和RabbitMQ集成

    SpringBoot和RabbitMQ的集成: 步骤 自动配置 123456789101112131415161718192021222324252627 @Bean public CachingCo ...

  6. SpringBoot从入门到精通教程(三十一)- 爬虫框架集成

    需求背景 SpringBoot用法:爬虫框架集成 业务场景 以抓取"今日头条"新闻举例说明 技术点 1. 集成爬虫框架webmagic(更多了解webmagic,可以去官方地址) ...

  7. Springboot 最简单的整合Dubbo框架实战案例

    分布式框架,目前比较热门的是springcloud和dubbo,虽然本人也是用cloud比较多,但是避免不了,有的项目就是需要用dubbo. 那么现在就给大家整一篇,简单清晰的spirngboot从零 ...

  8. 详细总结:分布式, Nginx Linux Redis 微服务 Dubbo框架 Quartz定时任务

    目录 1.1 概念 2.1分布式概念 2.2分布式项目拆分 2.3分布式项目总结 2.3 分布式事务 3.1 Nginx配置文件介绍 3.2 实现负载均衡(Tomcat高可用) 3.3 常见面试题 4 ...

  9. RabbitMq详解+SpringBoot整合RabbitMq快速入门

    1概述: 1.1.什么是MQ 消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已. 其主要用途:不同进程Pro ...

  10. SpringBoot整合RabbitMQ,实现单机抢票系统

    MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取队列中的消息. 消息 ...

最新文章

  1. php使用pdo操作mysql数据库实例_php5使用pdo连接数据库实例
  2. poj3692(二分图最大独立集)
  3. 《Java编码指南:编写安全可靠程序的75条建议》—— 指南20:使用安全管理器创建一个安全的沙盒...
  4. firefox input 缓存
  5. SylixOS 无Uboot版BSP
  6. 通过视觉直观感受7种常用的排序算法
  7. [蓝桥杯2017初赛]方格分割-dfs+思维
  8. 免otp动态密码登录堡垒机
  9. Go Web编程--使用bcrpyt哈希用户密码
  10. BeyondCompare3提示许可密钥过期完美解决方法:3281-0350
  11. 用excel绘制统计图
  12. 【C语言】乘法口诀表
  13. 中国网络游戏上市突击大事记
  14. EasyExcel如何返回业务处理中的错误信息
  15. Linux 各种安装包
  16. 编译linux内核3.0系统出现的警告信息(原创)
  17. 看epub电子书用什么阅读软件好?
  18. Shell实现命令先后执行
  19. AZBIL FL7S-1W6W-CN03
  20. Windows系统的静态路由配置

热门文章

  1. 英文文献pdf转成中文
  2. python截图(长图和短图)方法封装
  3. 易语言群控雷电_安卓群控系统雷电模拟器安卓多开模拟器多开群控系统企业自动化的营销系统软件-资源下载随便下源码网...
  4. 树状数组基础版解析+区间修改
  5. P2P继续停止...
  6. 航模的无刷电机到底是什么电机
  7. Chrome浏览器打不开网页,连设置都打不开的解决办法
  8. 计算机无法同步,在win7中,为什么电脑时间不能同步?
  9. 深度学习调参经验分享(遥感建筑提取)
  10. 机器学习考试 ppt