├── src ├── test │ └── java │ │ ├── com │ │ └── liubo │ │ │ ├── proxy │ │ │ ├── Subject.java │ │ │ ├── Programmer.java │ │ │ ├── RealSubject.java │ │ │ ├── Hacker.java │ │ │ ├── Test.java │ │ │ ├── InvocationHandlerImpl.java │ │ │ └── Demo.java │ │ │ ├── concurrent │ │ │ ├── ProgressListener.java │ │ │ ├── Work.java │ │ │ ├── JoinTest.java │ │ │ ├── HelloWorld.java │ │ │ ├── Puzzle.java │ │ │ ├── Philosopher.java │ │ │ ├── Counting.java │ │ │ └── Downloader.java │ │ │ ├── time │ │ │ └── InstantTest.java │ │ │ └── rabbit │ │ │ ├── direct │ │ │ ├── DirectTest.java │ │ │ ├── EmitLogDirect.java │ │ │ ├── ChannelUtils.java │ │ │ └── ReceiveLogsDirect.java │ │ │ ├── pubsub │ │ │ ├── EmitLog.java │ │ │ └── ReceiverLogs.java │ │ │ ├── simple │ │ │ ├── Send.java │ │ │ └── Recv.java │ │ │ └── workqueue │ │ │ ├── NewTask.java │ │ │ └── Worker.java │ │ └── ManSender.java └── main │ ├── resources │ ├── person.sql │ ├── application.yml │ └── mapper │ │ └── PersonDao.xml │ └── java │ └── com │ └── liubo │ └── demo │ └── rabbitmq │ ├── DemoSpringbootApplication.java │ ├── person │ ├── dao │ │ └── PersonDao.java │ ├── controller │ │ └── PersonController.java │ └── service │ │ └── impl │ │ └── PersonServiceImpl.java │ ├── TestController.java │ ├── Receiver.java │ └── AmqpConfig.java ├── .gitignore ├── README.md ├── pom.xml └── LICENSE /src/test/java/com/liubo/proxy/Subject.java: -------------------------------------------------------------------------------- 1 | package com.liubo.proxy; 2 | 3 | /** 4 | * Created by hzlbo on 2017/1/17 0017. 5 | */ 6 | public interface Subject { 7 | String sayHello(); 8 | 9 | String sayGoodBye(); 10 | } 11 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/proxy/Programmer.java: -------------------------------------------------------------------------------- 1 | package com.liubo.proxy; 2 | 3 | /** 4 | * Created by hzlbo on 2017/1/17 0017. 5 | */ 6 | public class Programmer { 7 | public void code(){ 8 | System.out.println("I'am a Programmer"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | *.iml 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | /target 14 | /.idea 15 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/concurrent/ProgressListener.java: -------------------------------------------------------------------------------- 1 | package com.liubo.concurrent; 2 | 3 | /** 4 | * Created by hzlbo on 2017/1/5 0005. 5 | */ 6 | public class ProgressListener { 7 | 8 | public void onProgress(int n) { 9 | System.out.println("progress " + n + " %"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # demo_springboot_rabbitmq 2 | # springboot rabbitmq 消费者 3 | 4 | # 消费Rabbitmq消息,插入mysql 5 | 6 | 7 | 生产者 [代码](https://github.com/liubo6/demo_springboot_rabbitmq_producer) 8 | 9 | 消费者 [代码](https://github.com/liubo6/demo_springboot_rabbitmq) 10 | 11 | api工程 [代码](https://github.com/liubo6/demo_springboot_rabbitmq_api) 12 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/proxy/RealSubject.java: -------------------------------------------------------------------------------- 1 | package com.liubo.proxy; 2 | 3 | /** 4 | * Created by hzlbo on 2017/1/17 0017. 5 | */ 6 | public class RealSubject implements Subject { 7 | @Override 8 | public String sayHello() { 9 | return "hello"; 10 | } 11 | 12 | @Override 13 | public String sayGoodBye() { 14 | return "good bye"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/person.sql: -------------------------------------------------------------------------------- 1 | -- ---------------------------- 2 | -- Table structure for person 3 | -- ---------------------------- 4 | DROP TABLE IF EXISTS `person`; 5 | CREATE TABLE `person` ( 6 | `id` int(11) NOT NULL AUTO_INCREMENT, 7 | `userId` varchar(36) DEFAULT NULL, 8 | `userName` varchar(64) DEFAULT NULL, 9 | `age` int(3) DEFAULT NULL, 10 | PRIMARY KEY (`id`) 11 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 12 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/concurrent/Work.java: -------------------------------------------------------------------------------- 1 | package com.liubo.concurrent; 2 | 3 | /** 4 | * Created by hzlbo on 2017/1/6 0006. 5 | */ 6 | public class Work implements Runnable { 7 | @Override 8 | public void run() { 9 | try { 10 | Thread.sleep(1000); 11 | } catch (InterruptedException e) { 12 | e.printStackTrace(); 13 | } 14 | System.out.println(Thread.currentThread().getName()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/liubo/demo/rabbitmq/DemoSpringbootApplication.java: -------------------------------------------------------------------------------- 1 | package com.liubo.demo.rabbitmq; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | @SpringBootApplication 8 | @MapperScan("com.liubo.demo.rabbitmq.person.dao") 9 | public class DemoSpringbootApplication { 10 | public static void main(String[] args) { 11 | SpringApplication.run(DemoSpringbootApplication.class, args); 12 | } 13 | } -------------------------------------------------------------------------------- /src/test/java/com/liubo/time/InstantTest.java: -------------------------------------------------------------------------------- 1 | package com.liubo.time; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | /** 9 | * Created by hzlbo on 2017/1/16 0016. 10 | */ 11 | public class InstantTest { 12 | 13 | @Test 14 | public void instantTest() throws Exception { 15 | int threadPollSize = Runtime.getRuntime().availableProcessors() * 2; 16 | ExecutorService executor = Executors.newFixedThreadPool(threadPollSize); 17 | 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/concurrent/JoinTest.java: -------------------------------------------------------------------------------- 1 | package com.liubo.concurrent; 2 | 3 | /** 4 | * Created by hzlbo on 2017/1/6 0006. 5 | */ 6 | public class JoinTest { 7 | 8 | public static void main(String[] args) throws InterruptedException { 9 | Thread t1 = new Thread(new Work(),"t1"); 10 | Thread t2 = new Thread(new Work(),"t2"); 11 | Thread t3 = new Thread(new Work(),"t3"); 12 | 13 | t1.start(); 14 | t1.join(); 15 | t2.start(); 16 | t2.join(); 17 | t3.start(); 18 | t3.join(); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/rabbit/direct/DirectTest.java: -------------------------------------------------------------------------------- 1 | package com.liubo.rabbit.direct; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by hzlbo on 2016/12/22 0022. 7 | */ 8 | public class DirectTest { 9 | 10 | @Test 11 | public void testSend() throws Exception { 12 | EmitLogDirect.send("info", "信息"); 13 | EmitLogDirect.send("error", "错误信息"); 14 | EmitLogDirect.send("info", "信息"); 15 | EmitLogDirect.send("info", "信息"); 16 | } 17 | 18 | @Test 19 | public void testReceive() throws Exception { 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/concurrent/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package com.liubo.concurrent; 2 | 3 | /** 4 | * Created by hzlbo on 2017/1/3 0003. 5 | */ 6 | public class HelloWorld { 7 | 8 | public static void main(String[] args) throws InterruptedException { 9 | Thread myThread = new Thread() { 10 | @Override 11 | public void run() { 12 | System.out.println("Hello from new thread"); 13 | } 14 | }; 15 | myThread.start(); 16 | Thread.yield(); 17 | System.out.println("Hello from main thread"); 18 | myThread.join(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/liubo/demo/rabbitmq/person/dao/PersonDao.java: -------------------------------------------------------------------------------- 1 | package com.liubo.demo.rabbitmq.person.dao; 2 | 3 | import com.liubo.demo.rabbitmq.person.model.PersonDO; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.List; 7 | @Component 8 | public interface PersonDao { 9 | 10 | int addPerson(PersonDO personDO) throws Exception; 11 | 12 | int removePerson(String id) throws Exception; 13 | 14 | int modifyPerson(PersonDO person) throws Exception; 15 | 16 | PersonDO getPerson(String id) throws Exception; 17 | 18 | List queryPersonList(PersonDO person) throws Exception; 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/proxy/Hacker.java: -------------------------------------------------------------------------------- 1 | package com.liubo.proxy; 2 | 3 | import org.assertj.core.internal.cglib.proxy.MethodInterceptor; 4 | import org.assertj.core.internal.cglib.proxy.MethodProxy; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * Created by hzlbo on 2017/1/17 0017. 10 | */ 11 | public class Hacker implements MethodInterceptor { 12 | @Override 13 | public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 14 | System.out.println("I am a hacker start"); 15 | methodProxy.invokeSuper(o, objects); 16 | System.out.println("I am a hacker end"); 17 | return null; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/rabbit/direct/EmitLogDirect.java: -------------------------------------------------------------------------------- 1 | package com.liubo.rabbit.direct; 2 | 3 | import com.rabbitmq.client.Channel; 4 | 5 | /** 6 | * 直接交换机生产者 7 | * Created by hzlbo on 2016/12/22 0022. 8 | */ 9 | public class EmitLogDirect { 10 | private static final String EXCHANGE_NAME = "direct_logs"; 11 | 12 | public static void send(String routingKey, String message) throws Exception { 13 | //1 建立channel 14 | Channel channel = ChannelUtils.getInstance(); 15 | 16 | //2 声明交换机类型 17 | channel.exchangeDeclare(EXCHANGE_NAME, "direct", true); 18 | 19 | //3 发送消息 20 | channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes()); 21 | 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/proxy/Test.java: -------------------------------------------------------------------------------- 1 | package com.liubo.proxy; 2 | 3 | import org.assertj.core.internal.cglib.proxy.Enhancer; 4 | 5 | /** 6 | * Created by hzlbo on 2017/1/17 0017. 7 | */ 8 | public class Test { 9 | public static void main(String[] args) { 10 | Programmer programmer = new Programmer(); 11 | 12 | Hacker hacker = new Hacker(); 13 | //cglib 中加强器,用来创建动态代理 14 | Enhancer enhancer = new Enhancer(); 15 | //设置要创建动态代理的类 16 | enhancer.setSuperclass(programmer.getClass()); 17 | // 设置回调,这里相当于是对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实行intercept()方法进行拦截 18 | enhancer.setCallback(hacker); 19 | Programmer proxy = (Programmer) enhancer.create(); 20 | proxy.code(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/proxy/InvocationHandlerImpl.java: -------------------------------------------------------------------------------- 1 | package com.liubo.proxy; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * Created by hzlbo on 2017/1/17 0017. 8 | */ 9 | public class InvocationHandlerImpl implements InvocationHandler { 10 | 11 | private Object subject; 12 | 13 | public InvocationHandlerImpl(Object subject) { 14 | this.subject = subject; 15 | } 16 | 17 | @Override 18 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 19 | System.out.println("调用之前的工作"); 20 | System.out.println("Method :" + method); 21 | Object returnValue = method.invoke(subject, args); 22 | System.out.println("调用之后的工作"); 23 | return returnValue; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/proxy/Demo.java: -------------------------------------------------------------------------------- 1 | package com.liubo.proxy; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Proxy; 5 | 6 | /** 7 | * Created by hzlbo on 2017/1/17 0017. 8 | */ 9 | public class Demo { 10 | public static void main(String[] args) { 11 | Subject realSubject = new RealSubject(); 12 | InvocationHandler handler = new InvocationHandlerImpl(realSubject); 13 | ClassLoader loader = realSubject.getClass().getClassLoader(); 14 | Class[] interfaces = realSubject.getClass().getInterfaces(); 15 | 16 | Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler); 17 | System.out.println("动态代理对象的类型" + subject.getClass().getName()); 18 | 19 | String str = subject.sayHello(); 20 | System.out.println(str); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/concurrent/Puzzle.java: -------------------------------------------------------------------------------- 1 | package com.liubo.concurrent; 2 | 3 | /** 4 | * Created by hzlbo on 2017/1/4 0004. 5 | */ 6 | public class Puzzle { 7 | static boolean answerReady = false; 8 | static int answer = 0; 9 | 10 | static Thread t1 = new Thread() { 11 | @Override 12 | public void run() { 13 | answer = 40; 14 | answerReady = true; 15 | } 16 | }; 17 | 18 | static Thread t2 = new Thread() { 19 | @Override 20 | public void run() { 21 | if (answerReady) { 22 | System.out.println("answer is " + answer); 23 | } else { 24 | System.out.println("I don't know"); 25 | } 26 | } 27 | }; 28 | 29 | public static void main(String[] args) throws InterruptedException { 30 | t1.start(); 31 | t2.start(); 32 | t1.join(); 33 | t2.join(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/concurrent/Philosopher.java: -------------------------------------------------------------------------------- 1 | package com.liubo.concurrent; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Created by hzlbo on 2017/1/5 0005. 7 | */ 8 | public class Philosopher extends Thread { 9 | 10 | private Chopstick left, right; 11 | private Random random; 12 | 13 | 14 | public Philosopher(Chopstick left, Chopstick right) { 15 | this.left = left; 16 | this.right = right; 17 | random = new Random(); 18 | } 19 | 20 | class Chopstick { 21 | } 22 | 23 | @Override 24 | public void run() { 25 | try { 26 | while (true) { 27 | Thread.sleep(random.nextInt(100)); 28 | synchronized (left) { 29 | synchronized (right) { 30 | Thread.sleep(random.nextInt(100)); 31 | } 32 | } 33 | } 34 | } catch (InterruptedException e) { 35 | 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/liubo/demo/rabbitmq/TestController.java: -------------------------------------------------------------------------------- 1 | package com.liubo.demo.rabbitmq; 2 | 3 | import com.liubo.demo.rabbitmq.person.model.PersonDO; 4 | import org.springframework.amqp.core.Message; 5 | import org.springframework.amqp.core.MessageBuilder; 6 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RequestMethod; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | /** 13 | * Created by hzlbo on 2016/7/2. 14 | */ 15 | @RestController 16 | public class TestController { 17 | 18 | @Autowired 19 | RabbitTemplate rabbitTemplate; 20 | 21 | @RequestMapping(value = "/send", method = RequestMethod.GET) 22 | public String testSend() { 23 | Message message = MessageBuilder.withBody(new PersonDO("1", "10086", "liubo", 20).toString().getBytes()).setMessageId("123").build(); 24 | rabbitTemplate.convertAndSend(AmqpConfig.EXCHANGE, AmqpConfig.ROUTINGKEY, message); 25 | return "ok"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/rabbit/direct/ChannelUtils.java: -------------------------------------------------------------------------------- 1 | package com.liubo.rabbit.direct; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import com.rabbitmq.client.Connection; 5 | import com.rabbitmq.client.ConnectionFactory; 6 | 7 | import java.io.IOException; 8 | import java.util.concurrent.TimeoutException; 9 | 10 | /** 11 | * Created by hzlbo on 2016/12/22 0022. 12 | */ 13 | public class ChannelUtils { 14 | 15 | private static Channel channel = null; 16 | 17 | public static Channel getInstance() throws IOException, TimeoutException { 18 | return getChannel(); 19 | } 20 | 21 | private static Channel getChannel() throws IOException, TimeoutException { 22 | //建立连接工厂 23 | ConnectionFactory factory = new ConnectionFactory(); 24 | //设置连接地址 25 | factory.setHost("seaof-153-125-234-173.jp-tokyo-10.arukascloud.io"); 26 | factory.setPort(31084); 27 | //获取连接 28 | Connection connection = factory.newConnection(); 29 | //获取渠道 30 | Channel channel = connection.createChannel(); 31 | return channel; 32 | } 33 | 34 | public static void close() throws IOException, TimeoutException { 35 | channel.close(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/concurrent/Counting.java: -------------------------------------------------------------------------------- 1 | package com.liubo.concurrent; 2 | 3 | /** 4 | * Created by hzlbo on 2017/1/3 0003. 5 | */ 6 | public class Counting { 7 | public static void main(String[] args) throws InterruptedException { 8 | class Counter { 9 | private int count = 0; 10 | 11 | public synchronized void increment() { 12 | ++count; 13 | } 14 | 15 | public int getCount() { 16 | return count; 17 | } 18 | } 19 | final Counter counter = new Counter(); 20 | 21 | class CountingThread extends Thread { 22 | @Override 23 | public void run() { 24 | for (int i = 0; i < 10000; i++) { 25 | counter.increment(); 26 | } 27 | } 28 | } 29 | 30 | long st = System.currentTimeMillis(); 31 | CountingThread t1 = new CountingThread(); 32 | CountingThread t2 = new CountingThread(); 33 | t1.start(); 34 | t2.start(); 35 | t1.join(); 36 | t2.join(); 37 | System.out.println(counter.getCount()); 38 | System.out.println(System.currentTimeMillis() - st); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/rabbit/pubsub/EmitLog.java: -------------------------------------------------------------------------------- 1 | package com.liubo.rabbit.pubsub; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import com.rabbitmq.client.Connection; 5 | import com.rabbitmq.client.ConnectionFactory; 6 | import org.apache.commons.lang3.RandomStringUtils; 7 | 8 | /** 9 | * 发布订阅生产者 10 | * Created by hzlbo on 2016/12/22 0022. 11 | */ 12 | public class EmitLog { 13 | private static final String EXCHANGE_NAME = "logs"; 14 | 15 | public static void main(String[] args) throws Exception { 16 | 17 | //建立连接工厂 18 | ConnectionFactory factory = new ConnectionFactory(); 19 | //设置连接地址 20 | factory.setHost("seaof-153-125-234-173.jp-tokyo-10.arukascloud.io"); 21 | factory.setPort(31084); 22 | //获取连接 23 | Connection connection = factory.newConnection(); 24 | //获取渠道 25 | Channel channel = connection.createChannel(); 26 | 27 | //声明交换机类型 28 | channel.exchangeDeclare(EXCHANGE_NAME, "fanout"); 29 | 30 | //产生随机数字 31 | String message = RandomStringUtils.randomNumeric(8); 32 | 33 | channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes()); 34 | 35 | channel.close(); 36 | connection.close(); 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/rabbit/direct/ReceiveLogsDirect.java: -------------------------------------------------------------------------------- 1 | package com.liubo.rabbit.direct; 2 | 3 | import com.rabbitmq.client.*; 4 | 5 | import java.io.IOException; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | import java.util.concurrent.TimeoutException; 9 | 10 | /** 11 | * Created by hzlbo on 2016/12/22 0022. 12 | */ 13 | public class ReceiveLogsDirect { 14 | private static final String EXCHANGE_NAME = "direct_logs"; 15 | /** 16 | * 添加main参数 绑定不同队列 17 | * @param args 18 | * @throws Exception 19 | */ 20 | public static void main(String[] args) throws IOException, TimeoutException { 21 | //1 建立channel 22 | Channel channel = ChannelUtils.getInstance(); 23 | String queueName = channel.queueDeclare().getQueue(); 24 | 25 | List bindkeys = Arrays.asList(args); 26 | for (String bindKey : bindkeys) { 27 | channel.queueBind(queueName, EXCHANGE_NAME, bindKey); 28 | } 29 | Consumer consumer = new DefaultConsumer(channel) { 30 | 31 | @Override 32 | public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { 33 | String message = new String(body, "UTF-8"); 34 | System.out.println("[reviced]" + message); 35 | } 36 | }; 37 | channel.basicConsume(queueName, true, consumer); 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/liubo/demo/rabbitmq/person/controller/PersonController.java: -------------------------------------------------------------------------------- 1 | package com.liubo.demo.rabbitmq.person.controller; 2 | 3 | import com.liubo.demo.rabbitmq.person.model.PersonDO; 4 | import com.liubo.demo.rabbitmq.person.service.PersonService; 5 | import org.springframework.util.Assert; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import javax.annotation.Resource; 12 | 13 | /** 14 | * Created by hzlbo on 2016/7/5. 15 | */ 16 | @RestController 17 | @RequestMapping(value = "/person") 18 | public class PersonController { 19 | 20 | @Resource 21 | private PersonService personService; 22 | 23 | @RequestMapping(method = RequestMethod.POST) 24 | public PersonDO addPerson(PersonDO personDO) throws Exception { 25 | Assert.notNull(personDO, "对象不能为空"); 26 | boolean result = personService.addPerson(personDO); 27 | if (result){ 28 | return personService.getPerson(personDO.getId()); 29 | } 30 | return new PersonDO(); 31 | } 32 | 33 | 34 | @RequestMapping(value = "/{id}", method = RequestMethod.GET) 35 | public PersonDO getPerson(@PathVariable String id) throws Exception { 36 | 37 | Assert.hasText(id, "ID不能为空"); 38 | return personService.getPerson(id); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/rabbit/simple/Send.java: -------------------------------------------------------------------------------- 1 | package com.liubo.rabbit.simple; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import com.rabbitmq.client.Connection; 5 | import com.rabbitmq.client.ConnectionFactory; 6 | 7 | import java.io.IOException; 8 | import java.util.concurrent.TimeoutException; 9 | 10 | /** 11 | * 简单发送例子 12 | * Created by hzlbo on 2016/12/22 0022. 13 | */ 14 | public class Send { 15 | //队列名称 16 | private final static String QUEUE_NAME = "hello"; 17 | 18 | 19 | public static void main(String[] args) throws IOException, TimeoutException { 20 | 21 | //建立连接工厂 22 | ConnectionFactory factory = new ConnectionFactory(); 23 | //设置连接地址 24 | factory.setHost("seaof-153-125-234-173.jp-tokyo-10.arukascloud.io"); 25 | factory.setPort(31084); 26 | //获取连接 27 | Connection connection = factory.newConnection(); 28 | //获取渠道 29 | Channel channel = connection.createChannel(); 30 | //声明队列,如果不存在就新建 31 | //参数1队列名称;参数2是否持久化;参数3排他性队列,连接断开自动删除;参数4是否自动删除;参数5.参数 32 | channel.queueDeclare(QUEUE_NAME, false, false, false, null); 33 | //发送的消息 34 | String message = Thread.currentThread().getName() + "Hello "; 35 | 36 | //参数1 交换机;参数2 路由键;参数3 基础属性;参数4 消息体 37 | channel.basicPublish("", QUEUE_NAME, null, message.getBytes()); 38 | System.out.println(Thread.currentThread().getName() + "[send]" + message); 39 | channel.close(); 40 | connection.close(); 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/rabbit/pubsub/ReceiverLogs.java: -------------------------------------------------------------------------------- 1 | package com.liubo.rabbit.pubsub; 2 | 3 | import com.rabbitmq.client.*; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * 发布订阅消费者 9 | * Created by hzlbo on 2016/12/22 0022. 10 | */ 11 | public class ReceiverLogs { 12 | private static final String EXCHANGE_NAME = "logs"; 13 | 14 | 15 | public static void main(String[] args) throws Exception { 16 | //建立连接工厂 17 | ConnectionFactory factory = new ConnectionFactory(); 18 | //设置连接地址 19 | factory.setHost("seaof-153-125-234-173.jp-tokyo-10.arukascloud.io"); 20 | factory.setPort(31084); 21 | //获取连接 22 | Connection connection = factory.newConnection(); 23 | //获取渠道 24 | Channel channel = connection.createChannel(); 25 | 26 | //声明交换机类型 27 | channel.exchangeDeclare(EXCHANGE_NAME, "fanout"); 28 | 29 | String queueName = channel.queueDeclare().getQueue(); 30 | channel.queueBind(queueName, EXCHANGE_NAME, ""); 31 | System.out.println("waiting for messages"); 32 | 33 | Consumer consumer = new DefaultConsumer(channel) { 34 | 35 | @Override 36 | public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { 37 | 38 | String message = new String(body, "UTF-8"); 39 | System.out.println("[reviced]" + message); 40 | } 41 | }; 42 | channel.basicConsume(queueName, true, consumer); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/concurrent/Downloader.java: -------------------------------------------------------------------------------- 1 | package com.liubo.concurrent; 2 | 3 | import java.io.*; 4 | import java.net.URL; 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * Created by hzlbo on 2017/1/5 0005. 9 | */ 10 | public class Downloader extends Thread { 11 | private InputStream in; 12 | private OutputStream out; 13 | private ArrayList listeners; 14 | 15 | 16 | public Downloader(URL url, String outputFileName) throws IOException { 17 | in = url.openConnection().getInputStream(); 18 | out = new FileOutputStream(outputFileName); 19 | listeners = new ArrayList<>(); 20 | } 21 | 22 | public synchronized void addListener(ProgressListener listener) { 23 | listeners.add(listener); 24 | } 25 | 26 | public synchronized void removeListener(ProgressListener listener) { 27 | listeners.remove(listener); 28 | } 29 | 30 | private synchronized void updateProgress(int n) { 31 | for (ProgressListener listener : listeners) { 32 | listener.onProgress(n); 33 | } 34 | } 35 | 36 | @Override 37 | public void run() { 38 | int n = 0; 39 | int total = 0; 40 | byte[] buffer = new byte[1024]; 41 | 42 | try { 43 | while ((n = in.read(buffer)) != -1) { 44 | out.write(buffer, 0, n); 45 | total += n; 46 | updateProgress(total); 47 | } 48 | out.flush(); 49 | } catch (IOException e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #########################--mysql--######################## 2 | spring: 3 | datasource: 4 | name: test 5 | url: jdbc:mysql://seaof-153-125-234-174.jp-tokyo-10.arukascloud.io:31719/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false 6 | username: root 7 | password: liubo 8 | #Spring Boot默认的数据源是:org.apache.tomcat.jdbc.pool.DataSource 9 | type: com.alibaba.druid.pool.DruidDataSource 10 | sql-script-encoding: utf-8 11 | driver-class-name: com.mysql.jdbc.Driver 12 | maxActive: 50 13 | initialSize: 5 14 | #配置获取连接等待超时的时间 15 | maxWait: 60000 16 | minIdle: 5 17 | timeBetweenEvictionRunsMillis: 60000 18 | #配置一个连接在池中最小生存的时间,单位是毫秒 19 | minEvictableIdleTimeMillis: 300000 20 | validationQuery: select 'x' 21 | testWhileIdle: true 22 | testOnBorrow: false 23 | testOnReturn: false 24 | #打开PSCache,并且指定每个连接上PSCache的大小 25 | poolPreparedStatements: true 26 | maxOpenPreparedStatements: 20 27 | 28 | rabbitmq: 29 | host: seaof-153-125-234-175.jp-tokyo-10.arukascloud.io 30 | port: 31827 31 | password: guest 32 | username: guest 33 | virtual-host: / 34 | listener: 35 | auto-startup: true 36 | server: 37 | port: 8088 38 | display-name: "liubo-loan" 39 | tomcat: 40 | accesslog: 41 | directory: /opt/logs/ 42 | prefix: acesslog 43 | suffix: .log 44 | # 使用druid数据源 45 | #########################--mysql end--######################## 46 | mybatis: 47 | mapperLocations: classpath:mapper/*.xml 48 | typeAliasesPackage: com.liubo.demo -------------------------------------------------------------------------------- /src/main/resources/mapper/PersonDao.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INSERT INTO person(userId,userName,age) VALUES 6 | (#{userId},#{userName},#{age}) 7 | 8 | 9 | 10 | DELETE FROM person WHERE id=#{id} 11 | 12 | 13 | 14 | UPDATE person 15 | 16 | 17 | userName=#{userName}, 18 | 19 | 20 | age=#{age}, 21 | 22 | 23 | 24 | 25 | 26 | 27 | 31 | 32 | 49 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/rabbit/simple/Recv.java: -------------------------------------------------------------------------------- 1 | package com.liubo.rabbit.simple; 2 | 3 | import com.rabbitmq.client.*; 4 | 5 | import java.io.IOException; 6 | import java.util.concurrent.TimeoutException; 7 | 8 | /** 9 | * 简单接收例子 10 | * Created by hzlbo on 2016/12/22 0022. 11 | */ 12 | public class Recv { 13 | //队列名称 14 | private final static String QUEUE_NAME = "hello"; 15 | 16 | public static void main(String[] args) throws IOException, TimeoutException { 17 | //建立连接工厂 18 | ConnectionFactory factory = new ConnectionFactory(); 19 | //设置连接地址 20 | factory.setHost("seaof-153-125-234-173.jp-tokyo-10.arukascloud.io"); 21 | factory.setPort(31084); 22 | //获取连接 23 | Connection connection = factory.newConnection(); 24 | //获取渠道 25 | Channel channel = connection.createChannel(); 26 | //声明队列,如果不存在就新建 27 | //参数1队列名称;参数2是否持久化;参数3排他性队列,连接断开自动删除;参数4是否自动删除;参数5.参数 28 | channel.queueDeclare(QUEUE_NAME, false, false, false, null); 29 | 30 | System.out.println("[recv] wating for messages"); 31 | Consumer consumer = new DefaultConsumer(channel) { 32 | /** 33 | * No-op implementation of {@link Consumer#handleDelivery}. 34 | * 35 | * @param consumerTag 36 | * @param envelope 37 | * @param properties 38 | * @param body 39 | */ 40 | @Override 41 | public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { 42 | String message = new String(body, "UTF-8"); 43 | System.out.println("[recevied ]" + message); 44 | } 45 | }; 46 | //参数1,队列名称;参数2,是否自动确认;参数3 消费者 47 | channel.basicConsume(QUEUE_NAME, true, consumer); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/rabbit/workqueue/NewTask.java: -------------------------------------------------------------------------------- 1 | package com.liubo.rabbit.workqueue; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import com.rabbitmq.client.Connection; 5 | import com.rabbitmq.client.ConnectionFactory; 6 | import com.rabbitmq.client.MessageProperties; 7 | 8 | import java.io.IOException; 9 | import java.util.concurrent.ThreadLocalRandom; 10 | import java.util.concurrent.TimeoutException; 11 | 12 | /** 13 | * 简单生产者生成复杂消息 14 | * Created by hzlbo on 2016/12/22 0022. 15 | */ 16 | public class NewTask { 17 | //队列名称 18 | private final static String QUEUE_NAME = "hello"; 19 | 20 | 21 | public static void main(String[] args) throws IOException, TimeoutException { 22 | 23 | //建立连接工厂 24 | ConnectionFactory factory = new ConnectionFactory(); 25 | //设置连接地址 26 | factory.setHost("seaof-153-125-234-173.jp-tokyo-10.arukascloud.io"); 27 | factory.setPort(31084); 28 | //获取连接 29 | Connection connection = factory.newConnection(); 30 | //获取渠道 31 | Channel channel = connection.createChannel(); 32 | //声明队列,如果不存在就新建 33 | //参数1队列名称;参数2是否持久化;参数3排他性队列,连接断开自动删除;参数4是否自动删除;参数5.参数 34 | channel.queueDeclare(QUEUE_NAME, false, false, false, null); 35 | //发送的消息 36 | for (int i = 0; i < 10; i++) { 37 | 38 | String message = "Hello"; 39 | int num = ThreadLocalRandom.current().nextInt(10); 40 | String append = ""; 41 | for (int j = 0; j < num; j++) { 42 | append = append + "."; 43 | } 44 | message = message + (append); 45 | 46 | //参数1 交换机;参数2 路由键;参数3 基础属性,(持久化方式);参数4 消息体 47 | channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes()); 48 | System.out.println(Thread.currentThread().getName() + "[send]" + message); 49 | } 50 | channel.close(); 51 | connection.close(); 52 | 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/liubo/demo/rabbitmq/person/service/impl/PersonServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.liubo.demo.rabbitmq.person.service.impl; 2 | 3 | import com.liubo.demo.rabbitmq.person.dao.PersonDao; 4 | import com.liubo.demo.rabbitmq.person.model.PersonDO; 5 | import com.liubo.demo.rabbitmq.person.service.PersonService; 6 | import org.springframework.stereotype.Service; 7 | 8 | import javax.annotation.Resource; 9 | import java.util.List; 10 | 11 | /** 12 | * Created by hzlbo on 2016/7/5. 13 | */ 14 | @Service 15 | public class PersonServiceImpl implements PersonService { 16 | 17 | @Resource 18 | private PersonDao personDao; 19 | 20 | /** 21 | * 添加 22 | * 23 | * @param personDO 24 | * @return 25 | * @throws Exception 26 | */ 27 | @Override 28 | public boolean addPerson(PersonDO personDO) throws Exception { 29 | boolean result = personDao.addPerson(personDO) > 0; 30 | return result; 31 | } 32 | 33 | /** 34 | * 删除 35 | * 36 | * @param id 37 | * @return 38 | * @throws Exception 39 | */ 40 | @Override 41 | public boolean removePerson(String id) throws Exception { 42 | return personDao.removePerson(id) > 0; 43 | } 44 | 45 | /** 46 | * 修改 47 | * 48 | * @param person 49 | * @return 50 | * @throws Exception 51 | */ 52 | @Override 53 | public boolean modifyPerson(PersonDO person) throws Exception { 54 | return personDao.modifyPerson(person) > 0; 55 | } 56 | 57 | /** 58 | * 根据ID查询 59 | * 60 | * @param id 61 | * @return 62 | * @throws Exception 63 | */ 64 | @Override 65 | public PersonDO getPerson(String id) throws Exception { 66 | return personDao.getPerson(id); 67 | } 68 | 69 | /** 70 | * 查询列表 71 | * 72 | * @param person 73 | * @return 74 | * @throws Exception 75 | */ 76 | @Override 77 | public List queryPersonList(PersonDO person) throws Exception { 78 | return personDao.queryPersonList(person); 79 | } 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/com/liubo/rabbit/workqueue/Worker.java: -------------------------------------------------------------------------------- 1 | package com.liubo.rabbit.workqueue; 2 | 3 | import com.rabbitmq.client.*; 4 | 5 | import java.io.IOException; 6 | import java.util.concurrent.TimeUnit; 7 | import java.util.concurrent.TimeoutException; 8 | 9 | /** 10 | * 多消费者消费消息,手动确认消息 11 | * Created by hzlbo on 2016/12/22 0022. 12 | */ 13 | public class Worker { 14 | //队列名称 15 | private final static String QUEUE_NAME = "hello"; 16 | 17 | public static void main(String[] args) throws IOException, TimeoutException { 18 | //建立连接工厂 19 | ConnectionFactory factory = new ConnectionFactory(); 20 | //设置连接地址 21 | factory.setHost("seaof-153-125-234-173.jp-tokyo-10.arukascloud.io"); 22 | factory.setPort(31084); 23 | //获取连接 24 | Connection connection = factory.newConnection(); 25 | //获取渠道 26 | Channel channel = connection.createChannel(); 27 | //声明队列,如果不存在就新建 28 | //参数1队列名称;参数2是否持久化;参数3排他性队列,连接断开自动删除;参数4是否自动删除;参数5.参数 29 | channel.queueDeclare(QUEUE_NAME, false, false, false, null); 30 | //一次只接受一个未处理的消息 31 | channel.basicQos(1); 32 | final Consumer consumer = new DefaultConsumer(channel) { 33 | 34 | @Override 35 | public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { 36 | String message = new String(body, "UTF-8"); 37 | System.out.println("[recevied ]" + message); 38 | try { 39 | doWork(message); 40 | } finally { 41 | System.out.println("[recevied] Done"); 42 | channel.basicAck(envelope.getDeliveryTag(), false); 43 | } 44 | } 45 | }; 46 | //参数1,队列名称;参数2,是否自动确认;参数3 消费者 47 | //收动确认消息 48 | boolean autoAck = false; 49 | channel.basicConsume(QUEUE_NAME, autoAck, consumer); 50 | } 51 | 52 | 53 | private static void doWork(String task) { 54 | for (char c : task.toCharArray()) { 55 | if (c == '.') { 56 | try { 57 | //模拟耗时操作 58 | TimeUnit.SECONDS.sleep(1); 59 | } catch (InterruptedException e) { 60 | e.printStackTrace(); 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/ManSender.java: -------------------------------------------------------------------------------- 1 | 2 | import com.liubo.demo.rabbitmq.AmqpConfig; 3 | import com.rabbitmq.client.Channel; 4 | import com.rabbitmq.client.Connection; 5 | import com.rabbitmq.client.ConnectionFactory; 6 | import org.springframework.amqp.core.Message; 7 | import org.springframework.amqp.core.MessageProperties; 8 | 9 | 10 | /** 11 | * Created by Administrator on 2016/5/12. 12 | */ 13 | public class ManSender { 14 | 15 | protected Channel channel; 16 | protected Connection connection; 17 | protected String queueName; 18 | 19 | // 消息队列名称 20 | private final static String userName = "guest"; 21 | private final static String password = "guest"; 22 | private final static String virtualHost = "/"; 23 | private final static int port = 5672; 24 | private final static String host = "127.0.0.1"; 25 | 26 | public ManSender(String queueName) throws Exception { 27 | this.queueName = queueName; 28 | // 创建链接工厂 29 | ConnectionFactory factory = new ConnectionFactory(); 30 | factory.setHost(host); 31 | factory.setPort(port); 32 | factory.setVirtualHost(virtualHost); 33 | factory.setUsername(userName); 34 | factory.setPassword(password); 35 | // 创建链接 36 | connection = factory.newConnection(); 37 | 38 | // 创建消息信道 39 | channel = connection.createChannel(); 40 | 41 | // 生命消息队列 42 | channel.queueDeclare(queueName, true, false, false, null); 43 | } 44 | 45 | /** 46 | * 方法说明 关闭channel和connection。并非必须,因为隐含是自动调用的。 47 | * 48 | * @throws Exception 49 | * @author liubo 50 | * @version create time:2015年8月7日 下午9:59:41 51 | */ 52 | public void close() throws Exception { 53 | this.channel.close(); 54 | this.connection.close(); 55 | } 56 | 57 | 58 | public void sendMessage(Message object) throws Exception { 59 | // 发布消息,第一个参数表示路由(Exchange名称),未""则表示使用默认消息路由 60 | channel.basicPublish(AmqpConfig.EXCHANGE, AmqpConfig.ROUTINGKEY, null, 61 | object.getBody()); 62 | 63 | } 64 | 65 | public static void main(String[] args) throws Exception { 66 | ManSender manSender = new ManSender("spring-boot-queue"); 67 | String str = "hello,this is a message"; 68 | byte[] bytes = str.getBytes(); 69 | Message message = new Message(bytes, new MessageProperties()); 70 | for (int i = 0; i < 10; i++) { 71 | manSender.sendMessage(message); 72 | } 73 | manSender.close(); 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/liubo/demo/rabbitmq/Receiver.java: -------------------------------------------------------------------------------- 1 | package com.liubo.demo.rabbitmq; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.liubo.demo.rabbitmq.person.dao.PersonDao; 5 | import com.liubo.demo.rabbitmq.person.model.PersonDO; 6 | import com.rabbitmq.client.Channel; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.amqp.core.Message; 10 | import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener; 11 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | 14 | import javax.annotation.Resource; 15 | import java.io.IOException; 16 | 17 | 18 | /** 19 | * 监听的业务类,实现接口MessageListener 20 | * Created by hzlbo on 2016/7/1. 21 | */ 22 | 23 | //@RabbitListener(containerFactory = "rabbitListenerContainer", queues = AmqpConfig.QUEUE_NAME) 24 | public class Receiver implements ChannelAwareMessageListener { 25 | public Logger logger = LoggerFactory.getLogger(this.getClass()); 26 | 27 | 28 | @Resource 29 | private PersonDao personDao; 30 | 31 | @Autowired 32 | private RabbitTemplate template; 33 | 34 | @Override 35 | public void onMessage(Message message, Channel channel) throws Exception { 36 | 37 | try { 38 | 39 | logger.info("##### = {}", new String(message.getBody())); 40 | 41 | ObjectMapper objectMapper = new ObjectMapper(); 42 | PersonDO personDO = objectMapper.readValue(new String(message.getBody()), PersonDO.class); 43 | //模拟耗时操作 44 | //TimeUnit.SECONDS.sleep(10); 45 | boolean result = personDao.addPerson(personDO) > 0; 46 | if (!result) { 47 | logger.error("消息消费失败"); 48 | } else { 49 | logger.info("消息消费成功"); 50 | } 51 | channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);//手动消息应答 52 | } catch (IOException e) { 53 | logger.error(e.getMessage(), e); 54 | // channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);//true 重新放入队列 55 | channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);//对于处理不了的异常消息 56 | ObjectMapper objectMapper = new ObjectMapper(); 57 | PersonDO personDO = objectMapper.readValue(new String(message.getBody()), PersonDO.class); 58 | //发送到失败队列 59 | template.convertAndSend(AmqpConfig.EXCHANGE, AmqpConfig.ROUTINGKEY_FAIL, personDO); 60 | } 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.liubo.demo 5 | rabbitmq 6 | jar 7 | 1.0-SNAPSHOT 8 | rabbitmq_demo 9 | http://maven.apache.org 10 | 11 | 12 | 1.8 13 | 1.4.2.RELEASE 14 | 15 | 16 | 17 | 18 | junit 19 | junit 20 | 4.12 21 | test 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-web 26 | ${springboot.version} 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-amqp 31 | ${springboot.version} 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | ${springboot.version} 38 | test 39 | 40 | 41 | 42 | org.mybatis.spring.boot 43 | mybatis-spring-boot-starter 44 | 1.1.1 45 | 46 | 47 | 48 | mysql 49 | mysql-connector-java 50 | 5.1.39 51 | 52 | 53 | com.alibaba 54 | druid 55 | 1.0.21 56 | 57 | 58 | org.springframework 59 | spring-test 60 | 4.1.7.RELEASE 61 | test 62 | 63 | 64 | 65 | com.liubo.demo 66 | rabbitmq_api 67 | 1.0-SNAPSHOT 68 | 69 | 70 | org.apache.commons 71 | commons-lang3 72 | 3.4 73 | 74 | 75 | 76 | 77 | 78 | org.springframework.boot 79 | spring-boot-maven-plugin 80 | ${springboot.version} 81 | 82 | -Dfile.encoding=UTF-8 83 | 84 | 85 | 86 | 87 | repackage 88 | 89 | 90 | 91 | 92 | 93 | 94 | org.springframework.boot 95 | spring-boot-maven-plugin 96 | 97 | 98 | org.springframework 99 | springloaded 100 | 1.2.6.RELEASE 101 | 102 | 103 | 104 | 105 | 106 | 107 | org.apache.maven.plugins 108 | maven-compiler-plugin 109 | 110 | 1.8 111 | 1.8 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /src/main/java/com/liubo/demo/rabbitmq/AmqpConfig.java: -------------------------------------------------------------------------------- 1 | package com.liubo.demo.rabbitmq; 2 | 3 | 4 | import org.springframework.amqp.core.*; 5 | import org.springframework.amqp.rabbit.annotation.EnableRabbit; 6 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; 7 | import org.springframework.amqp.rabbit.connection.ConnectionFactory; 8 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 9 | import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; 10 | import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter; 11 | import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; 12 | import org.springframework.amqp.support.converter.MessageConverter; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.beans.factory.config.ConfigurableBeanFactory; 15 | import org.springframework.context.annotation.Bean; 16 | import org.springframework.context.annotation.Configuration; 17 | import org.springframework.context.annotation.Scope; 18 | import org.springframework.web.filter.CharacterEncodingFilter; 19 | 20 | @EnableRabbit 21 | @Configuration 22 | public class AmqpConfig { 23 | public static final String EXCHANGE = "spring.boot.direct"; 24 | public static final String ROUTINGKEY_FAIL = "spring.boot.routingKey.failure"; 25 | public static final String ROUTINGKEY = "spring.boot.routingKey"; 26 | public static final String QUEUE_NAME = "spring.demo"; 27 | public static final String QUEUE_NAME_FAIL = "spring.demo.failure"; 28 | 29 | //RabbitMQ的配置信息 30 | @Value("${spring.rabbitmq.host}") 31 | private String host; 32 | @Value("${spring.rabbitmq.port}") 33 | private Integer port; 34 | @Value("${spring.rabbitmq.username}") 35 | private String username; 36 | @Value("${spring.rabbitmq.password}") 37 | private String password; 38 | @Value("${spring.rabbitmq.virtual-host}") 39 | private String virtualHost; 40 | 41 | 42 | //建立一个连接容器,类型数据库的连接池 43 | @Bean 44 | public ConnectionFactory connectionFactory() { 45 | CachingConnectionFactory connectionFactory = 46 | new CachingConnectionFactory(host, port); 47 | connectionFactory.setUsername(username); 48 | connectionFactory.setPassword(password); 49 | connectionFactory.setVirtualHost(virtualHost); 50 | connectionFactory.setPublisherConfirms(true);// 确认机制 51 | //发布确认,template要求CachingConnectionFactory的publisherConfirms属性设置为true 52 | return connectionFactory; 53 | } 54 | 55 | // RabbitMQ的使用入口 56 | @Bean 57 | @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 58 | //必须是prototype类型 59 | public RabbitTemplate rabbitTemplate() { 60 | RabbitTemplate template = new RabbitTemplate(this.connectionFactory()); 61 | template.setMessageConverter(this.jsonMessageConverter()); 62 | template.setMandatory(true); 63 | return template; 64 | } 65 | 66 | /** 67 | * 交换机 68 | * 针对消费者配置 69 | * FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念 70 | * HeadersExchange :通过添加属性key-value匹配 71 | * DirectExchange:按照routingkey分发到指定队列 72 | * TopicExchange:多关键字匹配 73 | */ 74 | @Bean 75 | public DirectExchange exchange() { 76 | return new DirectExchange(EXCHANGE); 77 | } 78 | 79 | /** 80 | * 队列 81 | * 82 | * @return 83 | */ 84 | @Bean 85 | public Queue queue() { 86 | return new Queue(QUEUE_NAME, true); //队列持久 87 | 88 | } 89 | 90 | @Bean 91 | public Queue queueFail() { 92 | return new Queue(QUEUE_NAME_FAIL, true); //队列持久 93 | 94 | } 95 | /** 96 | * 绑定 97 | * 98 | * @return 99 | */ 100 | @Bean 101 | public Binding binding(Queue queue, DirectExchange exchange) { 102 | return BindingBuilder.bind(queue()).to(exchange()).with(AmqpConfig.ROUTINGKEY); 103 | } 104 | 105 | @Bean 106 | public Binding bindingFail(Queue queue, DirectExchange exchange) { 107 | return BindingBuilder.bind(queueFail()).to(exchange()).with(AmqpConfig.ROUTINGKEY_FAIL); 108 | } 109 | @Bean 110 | public MessageConverter jsonMessageConverter() { 111 | return new Jackson2JsonMessageConverter(); 112 | } 113 | 114 | /** 115 | * 声明一个监听容器 116 | * 117 | * @return 118 | */ 119 | // @Bean(name="rabbitListenerContainer") 120 | // public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() { 121 | // SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); 122 | // factory.setMessageConverter(jsonMessageConverter()); 123 | // factory.setConnectionFactory(connectionFactory()); 124 | // factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);//设置消费者手动应答 125 | // factory.setPrefetchCount(1);//从代理接收消息的数目。这个值越大,发送消息就越快,但是导致非顺序处理的风险就越高 126 | // 127 | // return factory; 128 | // } 129 | 130 | @Bean 131 | Receiver receiver(){ 132 | return new Receiver(); 133 | } 134 | 135 | @Bean 136 | MessageListenerAdapter listenerAdapter(Receiver receiver) { 137 | return new MessageListenerAdapter(receiver, "onMessage"); 138 | } 139 | 140 | @Bean 141 | public SimpleMessageListenerContainer messageListenerContainer(MessageListenerAdapter listenerAdapter) { 142 | SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); 143 | container.setConnectionFactory(connectionFactory()); 144 | container.setQueueNames(AmqpConfig.QUEUE_NAME); 145 | container.setExposeListenerChannel(true); 146 | container.setMaxConcurrentConsumers(1); 147 | container.setConcurrentConsumers(1); 148 | container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认 149 | container.setMessageListener(listenerAdapter); 150 | return container; 151 | } 152 | 153 | 154 | 155 | @Bean 156 | public CharacterEncodingFilter characterEncodingFilter() { 157 | CharacterEncodingFilter filter = new CharacterEncodingFilter(); 158 | filter.setEncoding("UTF-8"); 159 | filter.setForceEncoding(true); 160 | return filter; 161 | } 162 | 163 | } 164 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------