change to springboot

This commit is contained in:
ehlxr 2021-08-29 12:23:13 +08:00
parent e76d89f774
commit cc5cbc1ebb
25 changed files with 761 additions and 265 deletions

122
pom.xml
View File

@ -37,9 +37,33 @@
<jdk.verion>1.8</jdk.verion> <jdk.verion>1.8</jdk.verion>
<powermock.version>1.7.1</powermock.version> <powermock.version>1.7.1</powermock.version>
<kotlin.version>1.3.61</kotlin.version> <kotlin.version>1.3.61</kotlin.version>
</properties>
<spring-boot.version>2.2.6.RELEASE</spring-boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.jcraft</groupId> <groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId> <artifactId>jsch</artifactId>
@ -69,6 +93,12 @@
<groupId>org.apache.shiro</groupId> <groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId> <artifactId>shiro-core</artifactId>
<version>1.4.2</version> <version>1.4.2</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency> </dependency>
<!-- spring begin--> <!-- spring begin-->
@ -174,12 +204,12 @@
<groupId>redis.clients</groupId> <groupId>redis.clients</groupId>
<artifactId>jedis</artifactId> <artifactId>jedis</artifactId>
<version>3.4.1</version> <version>3.4.1</version>
</dependency> <exclusions>
<exclusion>
<dependency> <artifactId>slf4j-api</artifactId>
<groupId>org.springframework.boot</groupId> <groupId>org.slf4j</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId> </exclusion>
<version>2.5.2</version> </exclusions>
</dependency> </dependency>
<dependency> <dependency>
@ -188,11 +218,11 @@
<version>8.0.16</version> <version>8.0.16</version>
</dependency> </dependency>
<!-- servlet --> <!-- Servlet -->
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version> <version>3.1.0</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@ -240,10 +270,32 @@
<version>3.1.6</version> <version>3.1.6</version>
</dependency> </dependency>
<!--<dependency>-->
<!-- <groupId>org.apache.activemq</groupId>-->
<!-- <artifactId>activemq-all</artifactId>-->
<!-- <version>5.13.3</version>-->
<!--</dependency>-->
<!-- activemq依赖包 -->
<dependency> <dependency>
<groupId>org.apache.activemq</groupId> <groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId> <artifactId>activemq-broker</artifactId>
<version>5.13.3</version> </dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-spring</artifactId>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>javax.jms-api</artifactId>
</dependency> </dependency>
<dependency> <dependency>
@ -302,12 +354,32 @@
<groupId>com.rabbitmq</groupId> <groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId> <artifactId>amqp-client</artifactId>
<version>4.8.0</version> <version>4.8.0</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.hbase</groupId> <groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId> <artifactId>hbase-client</artifactId>
<version>1.3.5</version> <version>1.3.5</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
@ -377,4 +449,30 @@
<!-- </snapshots>--> <!-- </snapshots>-->
<!-- </repository>--> <!-- </repository>-->
<!--</repositories>--> <!--</repositories>-->
<build>
<!--单元测试时引用src/main/resources下的资源文件-->
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
<testResource>
<directory>src/main/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -0,0 +1,39 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author ehlxr
* @since 2021-08-29 09:35.
*/
@SpringBootApplication
public class BuddApplication {
public static void main(String[] args) {
SpringApplication.run(BuddApplication.class, args);
}
}

View File

@ -0,0 +1,72 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.redis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* @author ehlxr
* @since 2021-08-29 12:18.
*/
@Component
public class Main implements ApplicationListener<ContextRefreshedEvent> {
private static final Logger log = LoggerFactory.getLogger(Main.class);
@Autowired
@Qualifier("lettuceDAOImpl")
private RedisDAO redisDAO;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Runnable runnable = () -> {
String uuid = UUID.randomUUID().toString();
log.info("{} retry lock...", Thread.currentThread().getName());
Boolean lock = redisDAO.getDistributedLock("lock", uuid, 30_000);
if (lock) {
log.info("{} get lock!", Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(1);
// ...
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
Boolean locak = redisDAO.releaseDistributedLock("lock", uuid);
log.info("{} release lock {}", Thread.currentThread().getName(), locak);
}
}
};
new Thread(runnable, "t1").start();
new Thread(runnable, "t2").start();
}
}

View File

@ -73,7 +73,6 @@ public interface RedisDAO {
/** /**
* 获取分布式锁 * 获取分布式锁
* *
* @param logId 日志 id
* @param key key * @param key key
* @param value value需要保证全局唯一用来删除分布式锁时判断身份使用 * @param value value需要保证全局唯一用来删除分布式锁时判断身份使用
* @param expireTime 锁过期时间毫秒防止业务崩溃未删除锁导致死锁 * @param expireTime 锁过期时间毫秒防止业务崩溃未删除锁导致死锁
@ -84,7 +83,6 @@ public interface RedisDAO {
/** /**
* 释放分布式锁 * 释放分布式锁
* *
* @param logId 日志 id
* @param key key * @param key key
* @param value value需要和获取锁时传入的一致 * @param value value需要和获取锁时传入的一致
* @return 是否释放成功锁 * @return 是否释放成功锁
@ -95,7 +93,6 @@ public interface RedisDAO {
* 分布式限流队列在时间窗口内包含该时间点判断是否达到限流的阀值 * 分布式限流队列在时间窗口内包含该时间点判断是否达到限流的阀值
* 本接口实现的方法通过加锁避免并发问题性能不高只是为了说明限流逻辑如何实现 * 本接口实现的方法通过加锁避免并发问题性能不高只是为了说明限流逻辑如何实现
* *
* @param logId 日志 id
* @param key key * @param key key
* @param count 限流阀值 * @param count 限流阀值
* @param timeWindow 限流时间窗口 * @param timeWindow 限流时间窗口
@ -107,7 +104,6 @@ public interface RedisDAO {
* 分布式限流队列在时间窗口内包含该时间点判断是否达到限流的阀值 * 分布式限流队列在时间窗口内包含该时间点判断是否达到限流的阀值
* 本接口实现的方法通过 Lua 脚本避免并发问题性能较高 * 本接口实现的方法通过 Lua 脚本避免并发问题性能较高
* *
* @param logId 日志 id
* @param key key * @param key key
* @param count 限流阀值 * @param count 限流阀值
* @param timeWindow 限流时间窗口 * @param timeWindow 限流时间窗口

View File

@ -0,0 +1,31 @@
package io.github.ehlxr.redis;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @author ehlxr
*/
@Configuration
public class RedisTemplateConfig {
@Bean(name = "redisTemplate")
public RedisTemplate<String, String> getRedisTemplate(RedisConnectionFactory factory) {
return buildRedisTemplateByString(factory);
}
/**
* 构建 redisTemplate 使用 string序列化
*/
public RedisTemplate<String, String> buildRedisTemplateByString(RedisConnectionFactory factory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
return redisTemplate;
}
}

View File

@ -27,7 +27,6 @@ package io.github.ehlxr.redis.impl;
import io.github.ehlxr.redis.RedisDAO; import io.github.ehlxr.redis.RedisDAO;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.JedisCluster; import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.params.SetParams; import redis.clients.jedis.params.SetParams;
@ -41,10 +40,11 @@ import java.util.List;
* @author ehlxr * @author ehlxr
* @since 2021-07-15 22:44. * @since 2021-07-15 22:44.
*/ */
// @Component("jedisDAOImpl")
public class JedisDAOImpl implements RedisDAO { public class JedisDAOImpl implements RedisDAO {
private final Logger log = LoggerFactory.getLogger(JedisDAOImpl.class); private final Logger log = LoggerFactory.getLogger(JedisDAOImpl.class);
@Autowired // @Autowired
private JedisCluster jc; private JedisCluster jc;
@Override @Override

View File

@ -32,6 +32,7 @@ import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript; import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -40,18 +41,19 @@ import java.util.concurrent.TimeUnit;
* @author ehlxr * @author ehlxr
* @since 2021-07-15 22:51. * @since 2021-07-15 22:51.
*/ */
@Component("lettuceDAOImpl")
public class LettuceDAOImpl implements RedisDAO { public class LettuceDAOImpl implements RedisDAO {
private static final Logger log = LoggerFactory.getLogger(LettuceDAOImpl.class); private static final Logger log = LoggerFactory.getLogger(LettuceDAOImpl.class);
@Autowired @Autowired
private RedisTemplate<String, String> rt; private RedisTemplate<String, String> redisTemplate;
@Override @Override
public Boolean getDistributedLock(String key, String value, long expireTime) { public Boolean getDistributedLock(String key, String value, long expireTime) {
Boolean set = false; Boolean set = false;
try { try {
set = rt.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.MILLISECONDS); set = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.MILLISECONDS);
log.debug("getLock redis key: {}, value: {}, expireTime: {}, result: {}", key, value, expireTime, set); log.info("getLock redis key: {}, value: {}, expireTime: {}, result: {}", key, value, expireTime, set);
} catch (Exception e) { } catch (Exception e) {
log.error("getLock redis key: {}, value: {}, expireTime: {}", key, value, expireTime, e); log.error("getLock redis key: {}, value: {}, expireTime: {}", key, value, expireTime, e);
} }
@ -63,7 +65,7 @@ public class LettuceDAOImpl implements RedisDAO {
Long execute = null; Long execute = null;
try { try {
RedisScript<Long> redisScript = new DefaultRedisScript<>(RELEASE_LOCK_LUA, Long.class); RedisScript<Long> redisScript = new DefaultRedisScript<>(RELEASE_LOCK_LUA, Long.class);
execute = rt.execute(redisScript, Collections.singletonList(key), value); execute = redisTemplate.execute(redisScript, Collections.singletonList(key), value);
log.debug("releaseLock redis key: {}, value: {}, result: {}", key, value, execute); log.debug("releaseLock redis key: {}, value: {}, result: {}", key, value, execute);
} catch (Exception e) { } catch (Exception e) {
log.error("releaseLock redis key: {}, value: {}", key, value, e); log.error("releaseLock redis key: {}, value: {}", key, value, e);
@ -75,17 +77,17 @@ public class LettuceDAOImpl implements RedisDAO {
public synchronized Boolean slideWindow(String key, int count, long timeWindow) { public synchronized Boolean slideWindow(String key, int count, long timeWindow) {
try { try {
long nowTime = System.currentTimeMillis(); long nowTime = System.currentTimeMillis();
ListOperations<String, String> list = rt.opsForList(); ListOperations<String, String> list = redisTemplate.opsForList();
String farTime = list.index(key, count - 1); String farTime = list.index(key, count - 1);
if (farTime == null) { if (farTime == null) {
list.leftPush(key, String.valueOf(nowTime)); list.leftPush(key, String.valueOf(nowTime));
rt.expire(key, timeWindow + 1000L, TimeUnit.MILLISECONDS); redisTemplate.expire(key, timeWindow + 1000L, TimeUnit.MILLISECONDS);
return true; return true;
} }
if (nowTime - Long.parseLong(farTime) > timeWindow) { if (nowTime - Long.parseLong(farTime) > timeWindow) {
list.rightPop(key); list.rightPop(key);
list.leftPush(key, String.valueOf(nowTime)); list.leftPush(key, String.valueOf(nowTime));
rt.expire(key, timeWindow + 1000L, TimeUnit.MILLISECONDS); redisTemplate.expire(key, timeWindow + 1000L, TimeUnit.MILLISECONDS);
return true; return true;
} }
return false; return false;
@ -103,7 +105,7 @@ public class LettuceDAOImpl implements RedisDAO {
Long execute = null; Long execute = null;
try { try {
RedisScript<Long> redisScript = new DefaultRedisScript<>(SLIDE_WINDOW_LUA, Long.class); RedisScript<Long> redisScript = new DefaultRedisScript<>(SLIDE_WINDOW_LUA, Long.class);
execute = rt.execute(redisScript, Collections.singletonList(key), String.valueOf(count - 1), String.valueOf(timeWindow), String.valueOf(System.currentTimeMillis())); execute = redisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(count - 1), String.valueOf(timeWindow), String.valueOf(System.currentTimeMillis()));
log.debug("slideWindowLua redis key: {}, count: {}, timeWindow: {}, result: {}", key, count, timeWindow, execute); log.debug("slideWindowLua redis key: {}, count: {}, timeWindow: {}, result: {}", key, count, timeWindow, execute);
} catch (Exception e) { } catch (Exception e) {
log.error("slideWindowLua redis key: {}, count: {}, timeWindow: {}", key, count, timeWindow, e); log.error("slideWindowLua redis key: {}, count: {}, timeWindow: {}", key, count, timeWindow, e);

View File

@ -26,7 +26,6 @@ package io.github.ehlxr.springamq.controller;
import io.github.ehlxr.springamq.mq.producer.queue.QueueSender; import io.github.ehlxr.springamq.mq.producer.queue.QueueSender;
import io.github.ehlxr.springamq.mq.producer.topic.TopicSender; import io.github.ehlxr.springamq.mq.producer.topic.TopicSender;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
@ -37,8 +36,8 @@ import javax.annotation.Resource;
/** /**
* @description controller测试 * @description controller测试
*/ */
@Controller // @Controller
@RequestMapping("/activemq") // @RequestMapping("/activemq")
public class ActivemqController { public class ActivemqController {
@Resource @Resource

View File

@ -25,8 +25,6 @@
package io.github.ehlxr.springamq.mq.consumer.queue; package io.github.ehlxr.springamq.mq.consumer.queue;
import org.springframework.stereotype.Component;
import javax.jms.JMSException; import javax.jms.JMSException;
import javax.jms.Message; import javax.jms.Message;
import javax.jms.MessageListener; import javax.jms.MessageListener;
@ -35,7 +33,7 @@ import javax.jms.TextMessage;
/** /**
* @description 队列消息监听器 * @description 队列消息监听器
*/ */
@Component // @Component
public class QueueReceiver1 implements MessageListener { public class QueueReceiver1 implements MessageListener {
@Override @Override

View File

@ -25,8 +25,6 @@
package io.github.ehlxr.springamq.mq.consumer.queue; package io.github.ehlxr.springamq.mq.consumer.queue;
import org.springframework.stereotype.Component;
import javax.jms.JMSException; import javax.jms.JMSException;
import javax.jms.Message; import javax.jms.Message;
import javax.jms.MessageListener; import javax.jms.MessageListener;
@ -35,7 +33,7 @@ import javax.jms.TextMessage;
/** /**
* @description 队列消息监听器 * @description 队列消息监听器
*/ */
@Component // @Component
public class QueueReceiver2 implements MessageListener { public class QueueReceiver2 implements MessageListener {
@Override @Override

View File

@ -24,8 +24,6 @@
package io.github.ehlxr.springamq.mq.consumer.topic; package io.github.ehlxr.springamq.mq.consumer.topic;
import org.springframework.stereotype.Component;
import javax.jms.JMSException; import javax.jms.JMSException;
import javax.jms.Message; import javax.jms.Message;
import javax.jms.MessageListener; import javax.jms.MessageListener;
@ -34,7 +32,7 @@ import javax.jms.TextMessage;
/** /**
* @description Topic消息监听器 * @description Topic消息监听器
*/ */
@Component // @Component
public class TopicReceiver1 implements MessageListener{ public class TopicReceiver1 implements MessageListener{
@Override @Override

View File

@ -24,8 +24,6 @@
package io.github.ehlxr.springamq.mq.consumer.topic; package io.github.ehlxr.springamq.mq.consumer.topic;
import org.springframework.stereotype.Component;
import javax.jms.JMSException; import javax.jms.JMSException;
import javax.jms.Message; import javax.jms.Message;
import javax.jms.MessageListener; import javax.jms.MessageListener;
@ -34,7 +32,7 @@ import javax.jms.TextMessage;
/** /**
* @description Topic消息监听器 * @description Topic消息监听器
*/ */
@Component // @Component
public class TopicReceiver2 implements MessageListener{ public class TopicReceiver2 implements MessageListener{
@Override @Override

View File

@ -24,24 +24,21 @@
package io.github.ehlxr.springamq.mq.producer.queue; package io.github.ehlxr.springamq.mq.producer.queue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator; import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;
import javax.jms.JMSException; import javax.jms.JMSException;
import javax.jms.Message; import javax.jms.Message;
import javax.jms.Session; import javax.jms.Session;
/** /**
* @description 队列消息生产者发送消息到队列 * @description 队列消息生产者发送消息到队列
*/ */
@Component("queueSender") // @Component("queueSender")
public class QueueSender { public class QueueSender {
@Autowired // @Autowired
@Qualifier("jmsQueueTemplate") // @Qualifier("jmsQueueTemplate")
private JmsTemplate jmsTemplate;//通过@Qualifier修饰符来注入对应的bean private JmsTemplate jmsTemplate;//通过@Qualifier修饰符来注入对应的bean
/** /**
@ -49,7 +46,7 @@ public class QueueSender {
* @param queueName 队列名称 * @param queueName 队列名称
* @param message 消息内容 * @param message 消息内容
*/ */
public void send(String queueName,final String message){ public void send(String queueName, final String message) {
jmsTemplate.send(queueName, new MessageCreator() { jmsTemplate.send(queueName, new MessageCreator() {
@Override @Override
public Message createMessage(Session session) throws JMSException { public Message createMessage(Session session) throws JMSException {

View File

@ -24,11 +24,8 @@
package io.github.ehlxr.springamq.mq.producer.topic; package io.github.ehlxr.springamq.mq.producer.topic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator; import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;
import javax.jms.JMSException; import javax.jms.JMSException;
import javax.jms.Message; import javax.jms.Message;
@ -38,11 +35,11 @@ import javax.jms.Session;
* @description Topic生产者发送消息到Topic * @description Topic生产者发送消息到Topic
*/ */
@Component("topicSender") // @Component("topicSender")
public class TopicSender { public class TopicSender {
@Autowired // @Autowired
@Qualifier("jmsTopicTemplate") // @Qualifier("jmsTopicTemplate")
private JmsTemplate jmsTemplate; private JmsTemplate jmsTemplate;
/** /**

View File

@ -28,7 +28,8 @@ import java.util.ArrayList;
import java.util.Random; import java.util.Random;
/** /**
* -Xms600m -Xmx600m -XX:SurvivorRatio=8 -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/ehlxr/Downloads/hprof/1.hprof * -Xms600m -Xmx600m -XX:SurvivorRatio=8 -XX:+PrintGCDetails
* -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/ehlxr/Downloads/hprof/1.hprof
* *
* @author ehlxr * @author ehlxr
* @since 2021-08-08 21:26. * @since 2021-08-08 21:26.
@ -48,7 +49,7 @@ public class OOMTest {
} }
class Picture { class Picture {
private byte[] pixels; private final byte[] pixels;
public Picture(int length) { public Picture(int length) {
this.pixels = new byte[length]; this.pixels = new byte[length];

View File

@ -13,13 +13,13 @@ import java.util.List;
* @create 16:11 * @create 16:11
*/ */
public class StudentTrace { public class StudentTrace {
static List<WebPage> webpages = new ArrayList<WebPage>(); static List<WebPage> webpages = new ArrayList<>();
public static void createWebPages() { public static void createWebPages() {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
WebPage wp = new WebPage(); WebPage wp = new WebPage();
wp.setUrl("http://www." + Integer.toString(i) + ".com"); wp.setUrl("http://www." + i + ".com");
wp.setContent(Integer.toString(i)); wp.setContent(Integer.toString(i));
webpages.add(wp); webpages.add(wp);
} }

View File

@ -1,68 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core" xsi:schemaLocation="http://www.springframework.org/schema/beans
xmlns:jms="http://www.springframework.org/schema/jms" http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-4.0.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.8.0.xsd">
<!-- ActiveMQ 连接工厂 --> <!--&lt;!&ndash; ActiveMQ 连接工厂 &ndash;&gt;-->
<!-- 真正可以产生Connection的ConnectionFactory由对应的 JMS服务厂商提供--> <!--&lt;!&ndash; 真正可以产生Connection的ConnectionFactory由对应的 JMS服务厂商提供&ndash;&gt;-->
<!-- 如果连接网络tcp://ip:61616未连接网络tcp://localhost:61616 以及用户名,密码--> <!--&lt;!&ndash; 如果连接网络tcp://ip:61616未连接网络tcp://localhost:61616 以及用户名,密码&ndash;&gt;-->
<amq:connectionFactory id="amqConnectionFactory" <!--<amq:connectionFactory id="amqConnectionFactory"-->
brokerURL="tcp://192.168.1.251:61616" userName="admin" password="admin" /> <!-- brokerURL="tcp://192.168.1.251:61616" userName="admin" password="admin" />-->
<!-- Spring Caching连接工厂 --> <!--&lt;!&ndash; Spring Caching连接工厂 &ndash;&gt;-->
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory --> <!--&lt;!&ndash; Spring用于管理真正的ConnectionFactory的ConnectionFactory &ndash;&gt; -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory"> <!--<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">-->
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory --> <!-- &lt;!&ndash; 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory &ndash;&gt; -->
<property name="targetConnectionFactory" ref="amqConnectionFactory"></property> <!-- <property name="targetConnectionFactory" ref="amqConnectionFactory"></property>-->
<!-- 同上,同理 --> <!-- &lt;!&ndash; 同上,同理 &ndash;&gt;-->
<!-- <constructor-arg ref="amqConnectionFactory" /> --> <!-- &lt;!&ndash; <constructor-arg ref="amqConnectionFactory" /> &ndash;&gt;-->
<!-- Session缓存数量 --> <!-- &lt;!&ndash; Session缓存数量 &ndash;&gt;-->
<property name="sessionCacheSize" value="100" /> <!-- <property name="sessionCacheSize" value="100" />-->
</bean> <!--</bean>-->
<!-- Spring JmsTemplate 的消息生产者 start--> <!--&lt;!&ndash; Spring JmsTemplate 的消息生产者 start&ndash;&gt;-->
<!-- 定义JmsTemplate的Queue类型 --> <!--&lt;!&ndash; 定义JmsTemplate的Queue类型 &ndash;&gt;-->
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate"> <!--<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">-->
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 --> <!-- &lt;!&ndash; 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 &ndash;&gt; -->
<constructor-arg ref="connectionFactory" /> <!-- <constructor-arg ref="connectionFactory" />-->
<!-- 非pub/sub模型发布/订阅),即队列模式 --> <!-- &lt;!&ndash; 非pub/sub模型发布/订阅),即队列模式 &ndash;&gt;-->
<property name="pubSubDomain" value="false" /> <!-- <property name="pubSubDomain" value="false" />-->
</bean> <!--</bean>-->
<!-- 定义JmsTemplate的Topic类型 --> <!--&lt;!&ndash; 定义JmsTemplate的Topic类型 &ndash;&gt;-->
<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate"> <!--<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">-->
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 --> <!-- &lt;!&ndash; 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 &ndash;&gt; -->
<constructor-arg ref="connectionFactory" /> <!-- <constructor-arg ref="connectionFactory" />-->
<!-- pub/sub模型发布/订阅) --> <!-- &lt;!&ndash; pub/sub模型发布/订阅) &ndash;&gt;-->
<property name="pubSubDomain" value="true" /> <!-- <property name="pubSubDomain" value="true" />-->
</bean> <!--</bean>-->
<!--Spring JmsTemplate 的消息生产者 end--> <!--&lt;!&ndash;Spring JmsTemplate 的消息生产者 end&ndash;&gt;-->
<!-- 消息消费者 start--> <!--&lt;!&ndash; 消息消费者 start&ndash;&gt;-->
<!-- 定义Queue监听器 --> <!--&lt;!&ndash; 定义Queue监听器 &ndash;&gt;-->
<jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory" acknowledge="auto"> <!--<jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory" acknowledge="auto">-->
<jms:listener destination="test.queue" ref="queueReceiver1"/> <!-- <jms:listener destination="test.queue" ref="queueReceiver1"/>-->
<jms:listener destination="test.queue" ref="queueReceiver2"/> <!-- <jms:listener destination="test.queue" ref="queueReceiver2"/>-->
</jms:listener-container> <!--</jms:listener-container>-->
<!-- 定义Topic监听器 --> <!--&lt;!&ndash; 定义Topic监听器 &ndash;&gt;-->
<jms:listener-container destination-type="topic" container-type="default" connection-factory="connectionFactory" acknowledge="auto"> <!--<jms:listener-container destination-type="topic" container-type="default" connection-factory="connectionFactory" acknowledge="auto">-->
<jms:listener destination="test.topic" ref="topicReceiver1"/> <!-- <jms:listener destination="test.topic" ref="topicReceiver1"/>-->
<jms:listener destination="test.topic" ref="topicReceiver2"/> <!-- <jms:listener destination="test.topic" ref="topicReceiver2"/>-->
</jms:listener-container> <!--</jms:listener-container>-->
<!-- 消息消费者 end --> <!--&lt;!&ndash; 消息消费者 end &ndash;&gt;-->
</beans> </beans>

View File

@ -0,0 +1,7 @@
server:
port: 8081
spring:
redis:
host: 127.0.0.1
port: 6379

View File

@ -0,0 +1,20 @@
spring:
profiles:
active: dev
application:
name: budd
logging:
file:
path: /datalog/weblog/${spring.application.name}
config: classpath:logback-spring.xml
server:
tomcat:
uri-encoding: UTF-8
accept-count: 1000
connection-timeout: 30000
servlet:
context-path: /budd
session:
timeout: 60

View File

@ -1,25 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- 查找最新的schemaLocation 访问 http://www.springframework.org/schema/ --> <!-- 查找最新的schemaLocation 访问 http://www.springframework.org/schema/ -->
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
xmlns:amq="http://activemq.apache.org/schema/core" http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.9.0.xsd">
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> <!--<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>-->
<!-- 配置扫描路径 --> <!-- 配置扫描路径 -->
<context:component-scan base-package="me.ehlxr.springamq"> <!--<context:component-scan base-package="me.ehlxr.springamq">-->
<!-- 只扫描Service也可以添加Repostory但是要把Controller排除在外Controller由spring-mvc.xml去加载 --> <!-- 只扫描Service也可以添加Repostory但是要把Controller排除在外Controller由spring-mvc.xml去加载 -->
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" /> --> <!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" /> -->
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" /> --> <!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" /> -->
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" /> --> <!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" /> -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
</context:component-scan> <!--</context:component-scan>-->
</beans> </beans>

View File

@ -1,27 +0,0 @@
### direct log messages to stdout and logFile###
log4j.rootCategory=INFO, stdout,logFile
# OpenSymphony Stuff
log4j.logger.com.opensymphony=INFO
log4j.logger.org.apache.struts2=INFO
log4j.logger.org.apache.commons=INFO
# Spring Stuff
log4j.logger.org.springframework=INFO
log4j.logger.org.springframework.oxm=INFO
# Hibernate Stuff
log4j.logger.org.hibernate=INFO
log4j.logger.org.hibernate.type=INFO
log4j.logger.org.hibernate.tool.hbm2ddl=INFO
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%p] %-d{yyyy-MM-dd HH\:mm\:ss} [%t] [%c.%M\:%L] %m%n
#log4j.appender.logFile=org.apache.log4j.RollingFileAppender
#log4j.appender.logFile.File=${webapp.root}/logs/amq.log
#log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
#log4j.appender.logFile.layout.ConversionPattern=[%p] %-d{yyyy-MM-dd HH\:mm\:ss} [%t] [%c.%M\:%L] %m%n
#log4j.appender.logFile.MaxFileSize = 5MB
#log4j.appender.logFile.MaxBackupIndex =3

View File

@ -0,0 +1,276 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL如果设置为WARN则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时配置文件如果发生改变将会被重新加载默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔如果没有给出时间单位默认单位是毫秒。当scan为true时此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时将打印出logback内部日志信息实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<!--<include resource="org/springframework/boot/logging/logback/base.xml"/>-->
<contextName>logback</contextName>
<!-- name的值是变量的名称value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后可以使“${}”来使用变量。 -->
<!-- <property name="LOG_PATH" value="${logging.file.path}" />-->
<springProperty name="LOG_PATH" source="logging.file.path"/>
<!--<springProperty name="ALIYUN_LOG_ENDPOINT" source="aliyun.log.endpoint"/>-->
<!--<springProperty name="ALIYUN_LOG_ACCESSKEYID" source="aliyun.log.accessKeyId"/>-->
<!--<springProperty name="ALIYUN_LOG_ACCESSKEYSECRET" source="aliyun.log.accessKeySecret"/>-->
<!--<springProperty name="ALIYUN_LOG_PROJECT" source="aliyun.log.project"/>-->
<!--<springProperty name="ALIYUN_LOG_LOGSTORE_INFO" source="aliyun.log.logstore.info"/>-->
<!--<springProperty name="ALIYUN_LOG_LOGSTORE_ERROR" source="aliyun.log.logstore.error"/>-->
<!-- 彩色日志 -->
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([%X{logTraceId}]){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!--<property name="CONSOLE_LOG_PATTERN"-->
<!-- value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([%X{√logTraceId}]){magenta} %clr(-&#45;&#45;){faint} %clr([%15.15t]){faint} %clr(at %class.%method){cyan} \\(%file:%line\\) %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>-->
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用只配置最底级别控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--输出到文件-->
<!-- 时间滚动输出 level为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/debug.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/warn.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--<appender name="ALIYUN_LOG_INFO" class="com.aliyun.openservices.log.logback.LoghubAppender">-->
<!-- <endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>-->
<!-- <accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>-->
<!-- <accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>-->
<!-- <project>${ALIYUN_LOG_PROJECT}</project>-->
<!-- <logStore>${ALIYUN_LOG_LOGSTORE_INFO}</logStore>-->
<!-- <totalSizeInBytes>104857600</totalSizeInBytes>-->
<!-- <maxBlockMs>0</maxBlockMs>-->
<!-- <ioThreadCount>8</ioThreadCount>-->
<!-- <batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>-->
<!-- <batchCountThreshold>4096</batchCountThreshold>-->
<!-- <lingerMs>2000</lingerMs>-->
<!-- <retries>10</retries>-->
<!-- <baseRetryBackoffMs>100</baseRetryBackoffMs>-->
<!-- <maxRetryBackoffMs>50000</maxRetryBackoffMs>-->
<!-- <encoder>-->
<!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>-->
<!-- <charset>UTF-8</charset>-->
<!-- </encoder>-->
<!-- <timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>-->
<!-- <timeZone>Asia/Shanghai</timeZone>-->
<!-- <filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!-- <level>INFO</level>-->
<!-- </filter>-->
<!-- <mdcFields>logTraceId</mdcFields>-->
<!--</appender>-->
<!--<appender name="ALIYUN_LOG_ERROR" class="com.aliyun.openservices.log.logback.LoghubAppender">-->
<!-- <endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>-->
<!-- <accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>-->
<!-- <accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>-->
<!-- <project>${ALIYUN_LOG_PROJECT}</project>-->
<!-- <logStore>${ALIYUN_LOG_LOGSTORE_ERROR}</logStore>-->
<!-- <totalSizeInBytes>104857600</totalSizeInBytes>-->
<!-- <maxBlockMs>0</maxBlockMs>-->
<!-- <ioThreadCount>8</ioThreadCount>-->
<!-- <batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>-->
<!-- <batchCountThreshold>4096</batchCountThreshold>-->
<!-- <lingerMs>2000</lingerMs>-->
<!-- <retries>10</retries>-->
<!-- <baseRetryBackoffMs>100</baseRetryBackoffMs>-->
<!-- <maxRetryBackoffMs>50000</maxRetryBackoffMs>-->
<!-- <encoder>-->
<!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>-->
<!-- <charset>UTF-8</charset>-->
<!-- </encoder>-->
<!-- <timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>-->
<!-- <timeZone>Asia/Shanghai</timeZone>-->
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
<!-- <level>ERROR</level>-->
<!-- </filter>-->
<!-- <mdcFields>logTraceId</mdcFields>-->
<!--</appender>-->
<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
以及指定<appender><logger>仅有一个name属性
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别大小写无关TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
还有一个特俗值INHERITED或者同义词NULL代表强制执行上级的级别。
如果未设置此属性那么当前logger将会继承上级的级别。
addtivity:是否向上级logger传递打印信息。默认是true。
-->
<!--<logger name="org.springframework.web" level="info"/>-->
<!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
<!--
使用mybatis的时候sql语句是debug下才会打印而这里我们只配置了info所以想要查看sql语句的话有以下两种操作
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql不过这样日志那边会出现很多其他消息
第二种就是单独给dao下目录配置debug模式代码如下这样配置sql语句会打印其他还是正常info级别
-->
<!--
root节点是必选节点用来指定最基础的日志输出级别只有一个level属性
level:用来设置打印级别大小写无关TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
不能设置为INHERITED或者同义词NULL。默认是DEBUG
可以包含零个或多个元素标识这个appender将会添加到这个logger。
-->
<springProfile name="dev">
<logger name="io.github.ehlxr" level="debug"/>
</springProfile>
<!--<springProfile name="test">-->
<!-- <logger name="io.github.ehlxr" level="info"/>-->
<!--</springProfile>-->
<!--<springProfile name="pre">-->
<!-- <logger name="io.github.ehlxr" level="info"/>-->
<!--</springProfile>-->
<!--<springProfile name="stress">-->
<!-- <logger name="io.github.ehlxr" level="info"/>-->
<!--</springProfile>-->
<!--<springProfile name="prod">-->
<!-- <logger name="io.github.ehlxr" level="info"/>-->
<!--</springProfile>-->
<!--<logger name="com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver" level="warn"/>-->
<!-- 可用来获取 StatusManager 中的状态 -->
<!--<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/>-->
<!-- 解决 aliyun loghub debug模式下循环发送的问题 -->
<logger name="org.apache.http.impl.conn.Wire" level="WARN"/>
<!--aliyun loghub 为了防止进程退出时,内存中的数据丢失,请加上此选项-->
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
<root level="info">
<appender-ref ref="CONSOLE"/>
<!--<appender-ref ref="DEBUG_FILE"/>-->
<!--<appender-ref ref="INFO_FILE"/>-->
<!--<appender-ref ref="WARN_FILE"/>-->
<!--<appender-ref ref="ERROR_FILE"/>-->
<!--<appender-ref ref="ALIYUN_LOG_INFO"/>-->
<!--<appender-ref ref="ALIYUN_LOG_ERROR"/>-->
</root>
</configuration>

View File

@ -1,40 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- 查找最新的schemaLocation 访问 http://www.springframework.org/schema/ --> <!-- 查找最新的schemaLocation 访问 http://www.springframework.org/schema/ -->
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans
xmlns:mvc="http://www.springframework.org/schema/mvc" http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- 启用MVC注解 --> <!--&lt;!&ndash; 启用MVC注解 &ndash;&gt;-->
<mvc:annotation-driven /> <!--<mvc:annotation-driven />-->
<!-- 静态资源文件不会被Spring MVC拦截 --> <!--&lt;!&ndash; 静态资源文件不会被Spring MVC拦截 &ndash;&gt;-->
<mvc:resources location="/resources/" mapping="/resources/**"/> <!--<mvc:resources location="/resources/" mapping="/resources/**"/>-->
<!-- 指定Sping组件扫描的基本包路径 --> <!--&lt;!&ndash; 指定Sping组件扫描的基本包路径 &ndash;&gt;-->
<context:component-scan base-package="osc.git.eh3.springamq" > <!--<context:component-scan base-package="osc.git.eh3.springamq" >-->
<!-- 这里只扫描Controller不可重复加载Service --> <!-- &lt;!&ndash; 这里只扫描Controller不可重复加载Service &ndash;&gt;-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
</context:component-scan> <!--</context:component-scan>-->
<!-- JSP视图解析器--> <!--&lt;!&ndash; JSP视图解析器&ndash;&gt;-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> -->
<property name="prefix" value="/WEB-INF/views/" /> <!-- <property name="prefix" value="/WEB-INF/views/" /> -->
<property name="suffix" value=".jsp" /> <!-- <property name="suffix" value=".jsp" />-->
<!-- 定义其解析视图的order顺序为1 --> <!--&lt;!&ndash; 定义其解析视图的order顺序为1 &ndash;&gt;-->
<property name="order" value="1" /> <!-- <property name="order" value="1" />-->
</bean> <!--</bean>-->
</beans> </beans>

View File

@ -1,71 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"> version="3.0">
<display-name>ActiveMQSpringDemo</display-name>
<!-- Log4J Start --> <!--&lt;!&ndash; Log4J Start &ndash;&gt;-->
<context-param> <!--<context-param>-->
<param-name>log4jConfigLocation</param-name> <!-- <param-name>log4jConfigLocation</param-name>-->
<param-value>classpath:log4j.properties</param-value> <!-- <param-value>classpath:log4j.properties</param-value>-->
</context-param> <!--</context-param>-->
<context-param> <!--<context-param>-->
<param-name>log4jRefreshInterval</param-name> <!-- <param-name>log4jRefreshInterval</param-name>-->
<param-value>6000</param-value> <!-- <param-value>6000</param-value>-->
</context-param> <!--</context-param>-->
<!-- Spring Log4J config --> <!--&lt;!&ndash; Spring Log4J config &ndash;&gt;-->
<listener> <!--<listener>-->
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> <!-- <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>-->
</listener> <!--</listener>-->
<!-- Log4J End --> <!--&lt;!&ndash; Log4J End &ndash;&gt;-->
<!-- Spring 编码过滤器 start --> <!--&lt;!&ndash; Spring 编码过滤器 start &ndash;&gt;-->
<filter> <!--<filter>-->
<filter-name>characterEncoding</filter-name> <!-- <filter-name>characterEncoding</filter-name>-->
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <!-- <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>-->
<init-param> <!-- <init-param>-->
<param-name>encoding</param-name> <!-- <param-name>encoding</param-name>-->
<param-value>UTF-8</param-value> <!-- <param-value>UTF-8</param-value>-->
</init-param> <!-- </init-param>-->
<init-param> <!-- <init-param>-->
<param-name>forceEncoding</param-name> <!-- <param-name>forceEncoding</param-name>-->
<param-value>true</param-value> <!-- <param-value>true</param-value>-->
</init-param> <!-- </init-param>-->
</filter> <!--</filter>-->
<filter-mapping> <!--<filter-mapping>-->
<filter-name>characterEncoding</filter-name> <!-- <filter-name>characterEncoding</filter-name>-->
<url-pattern>/*</url-pattern> <!-- <url-pattern>/*</url-pattern>-->
</filter-mapping> <!--</filter-mapping>-->
<!-- Spring 编码过滤器 End --> <!--&lt;!&ndash; Spring 编码过滤器 End &ndash;&gt;-->
<!-- Spring Application Context Listener Start --> <!--&lt;!&ndash; Spring Application Context Listener Start &ndash;&gt;-->
<context-param> <!--<context-param>-->
<param-name>contextConfigLocation</param-name> <!-- <param-name>contextConfigLocation</param-name>-->
<param-value>classpath*:applicationContext.xml,classpath*:ActiveMQ.xml</param-value> <!-- <param-value>classpath*:applicationContext.xml,classpath*:ActiveMQ.xml</param-value>-->
</context-param> <!--</context-param>-->
<listener> <!--<listener>-->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> <!-- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>-->
</listener> <!--</listener>-->
<!-- Spring Application Context Listener End --> <!--&lt;!&ndash; Spring Application Context Listener End &ndash;&gt;-->
<!-- Spring MVC Config Start --> <!--&lt;!&ndash; Spring MVC Config Start &ndash;&gt;-->
<servlet> <!--<servlet>-->
<servlet-name>SpringMVC</servlet-name> <!-- <servlet-name>SpringMVC</servlet-name>-->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>-->
<init-param> <!-- <init-param>-->
<param-name>contextConfigLocation</param-name> <!-- <param-name>contextConfigLocation</param-name>-->
<param-value>classpath:spring-mvc.xml</param-value> <!-- <param-value>classpath:spring-mvc.xml</param-value>-->
</init-param> <!-- </init-param>-->
<load-on-startup>1</load-on-startup> <!-- <load-on-startup>1</load-on-startup>-->
</servlet> <!--</servlet>-->
<servlet-mapping> <!--<servlet-mapping>-->
<servlet-name>SpringMVC</servlet-name> <!-- <servlet-name>SpringMVC</servlet-name>-->
<!-- Filter all resources --> <!-- &lt;!&ndash; Filter all resources &ndash;&gt;-->
<url-pattern>/</url-pattern> <!-- <url-pattern>/</url-pattern>-->
</servlet-mapping> <!--</servlet-mapping>-->
<!-- Spring MVC Config End --> <!--&lt;!&ndash; Spring MVC Config End &ndash;&gt;-->
</web-app> </web-app>

View File

@ -0,0 +1,23 @@
package io.github.ehlxr;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Unit test for simple App.
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class BuddApplicationTest {
private static final Logger log = LoggerFactory.getLogger(BuddApplicationTest.class);
@Test
public void redisLockTest() {
}
}