RabbitMQ是消息服务器,主要解决应用间解耦问题,消息异步处理和高并发场景下对关系数据库缓冲作用,比如电商系统中的秒杀设计。本例程中使用SpringBoot集成RabbitMQ解决高并发数据存储对关系数据库的缓冲问题。前端页面提交数据直接进入RabbitMQ队列,设计消息定时处理器或者消息监听器获取消息并保持到数据库。
本例要求:
1.安装RabbitMQ
2.使用SpringBoot框架
新建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>Proj_SpringRabbitmq</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Proj_SpringRabbitmq 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对mybatis的支持 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</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>
<!-- 添加springboot对solr的支持 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
</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>
<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.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils-core</artifactId>
<version>1.8.3</version>
</dependency>
</dependencies>
<build>
<finalName>Proj_SpringRabbitmq</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
Applicaton.properties文件
#SpringBoot启动端口和项目路径
server.port=8080
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
#数据源配置
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
#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=/
#Mybatis实体类配置
mybatis.mapper-locations=classpath:mapper/*.xml
#pagehelper分页插件
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
#日志配置
logging.file=d:/springboot.log
logging.level.com.test.mapper=INFO
logging.level.com.hk.servlet=DEBUG
logging.level.com.test.service.impl=DEBUG
菜单实体类
MeunInfo.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{
//菜单表ID
private Integer mid = null;
//材料表ID
private 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接口
扫描二维码关注公众号,回复:
3136500 查看本文章
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);
}
Mybatis Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//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) b
on 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) b
on 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和菜单ID
select s.name,s.id,m2s.mid from t_staff s,t_m2s m2s where s.id=m2s.sid
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
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) b
on a.id=b.mid;
服务接口
package com.test.service;
import java.util.List;
import org.apache.ibatis.annotations.Param;
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();
//保存菜单对象
public void 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);
}
服务实现类
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.test.bean.M2SInfo;
import com.test.bean.MenuInfo;
import com.test.bean.StaffInfo;
import com.test.mapper.MenuMapper;
import com.test.service.IMenuService;
@Service
public class MenuServiceImpl implements IMenuService{
private Logger log = LoggerFactory.getLogger(MenuServiceImpl.class);
@Autowired
private MenuMapper mapper;
@Override
@Transactional(readOnly=true,propagation=Propagation.REQUIRES_NEW)
public List<MenuInfo> findMenu(String name) {
return mapper.findMenu(name);
}
@Override
public List<StaffInfo> findStaff() {
return mapper.findStaff();
}
@Transactional
@Override
public void saveMenu(MenuInfo mi) {
mapper.saveMenu(mi);
}
@Override
public void updateMenu(MenuInfo mi) {
mapper.updateMenu(mi);
}
@Override
public void deleteMenu(Integer mid) {
mapper.deleteMenu(mid);
}
@Override
public void saveM2S(M2SInfo m2s) {
mapper.saveM2S(m2s);
}
@Override
public void deleteM2S(Integer mid) {
mapper.deleteM2S(mid);
}
@Override
public List<MenuInfo> findMenu2(String name) {
return mapper.findMenu2(name);
}
@Override
public MenuInfo getMenuById(Integer mid) {
return mapper.getMenuById(mid);
}
}
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;
//RabbitMQ配置类,替代XML配置
@Configuration
public class RabbitmqConf {
public static String QUEUE1 = "test_queue1";
public static String EXCHANGE1 = "test_exg1";
//生成队列test_queue1
@Bean
public Queue queue1()
{
return new Queue(QUEUE1);
}
//生成交换机test_exg1
@Bean
public DirectExchange exg1()
{
return new DirectExchange(EXCHANGE1);
}
//绑定队列与交换机
@Bean
public Binding directBinding1() {
return BindingBuilder.bind(queue1()).to(exg1()).with("java");
}
}
RabbitMQ消息接收器,有两种解决方案
1、使用定时器定时接收消息
2、使用消息监听器接收消息,两者互斥,只能选择其一
定时器接收消息
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.rabbitmq.client.ConnectionFactory;
import com.test.bean.M2SInfo;
import com.test.bean.MenuInfo;
import com.test.service.IMenuService;
@Component
public class CrontabGetMsg {
@Autowired
private AmqpTemplate amqp;
@Autowired
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());
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;
}
}
消息监听器
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 {
@Autowired
private 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;
}
}
定义发送消息工具类
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 {
//注入消息模板
@Autowired
private AmqpTemplate amqp;
public void send(MenuInfo mi)
{
amqp.convertAndSend(RabbitmqConf.QUEUE1,mi);
}
}
定义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 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 {
@Autowired
private IMenuService serv;
@Autowired
private SendMsg sendmsg;
//跳转菜单列表的方法
//接收前台参数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);
}
//删除方法,通过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,3
System.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,3
System.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);
PageHelper.startPage(page, rows);
List<MenuInfo> menuList = serv.findMenu2(name);
System.out.println("menuList===="+menuList.size());
PageInfo pi = new PageInfo(menuList);
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";
}
}
分页工具类
package com.test.util;
public class PageUtil {
private Integer page = 1;//默认显示第一页
private Integer rows = 4;//每页显示记录数
private Long total = null;//总行数
private String url = null;//点击页码跳转url
public 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;
else
pages = (total.intValue() / rows) + 1;
sb.append("<div id='pagediv'>\r\n");
String firstUrl = null;
if(url.indexOf("?")>0)
firstUrl = url + "&page=1&rows="+rows;
else
firstUrl = 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;
else
backUrl = 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;
else
pageUrl = url + "?page="+i+"&rows="+rows;
if(i == page)
sb.append("<a href='"+pageUrl+"'><b><font color='red'>"+i+"</font></b></a>\r\n");
else
sb.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;
else
nextUrl = 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;
else
lastUrl = url + "?page="+pages+"&rows="+rows;
sb.append("<a href='"+lastUrl+"'>尾页</a>\r\n");
sb.append(" 第"+page+"/"+pages+"页\r\n");
sb.append(" 共"+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='+id
listfrm.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
base.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;
}
SpringBoot启动类
package com.test.util;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.amqp.core.Queue;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication //SpringBoot程序固定注解
@MapperScan("com.test.mapper") //扫描Mybatis定义Mapper接口
@ComponentScan("com.test.ctrl,com.test.service.impl,com.test.util") //扫描Spring包路径
@EnableScheduling
public class Starter {
public static void main(String[] args) {
SpringApplication.run(Starter.class,args);
}
}
代码下载:
https://github.com/qixiangchen/Proj_SpringRabbitmq.git