耗子叔ARTS:第十一周
Algorithm:
/**
* 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。
* <p>
* J 中的字母不重复,J 和 S中的所有字符都是字母。字母区分大小写,因此"a"和"A"是不同类型的石头。
* <p>
* 示例 1:
* <p>
* 输入: J = "aA", S = "aAAbbbb"
* 输出: 3
* 示例 2:
* <p>
* 输入: J = "z", S = "ZZ"
* 输出: 0
* 注意:
* <p>
* S 和 J 最多含有50个字母。
* J 中的字符不重复。
* <p>
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/jewels-and-stones
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
JAVA:
public static int numJewelsInStones(String J, String S) {
int num = 0;
char[] jArray = J.toCharArray();
char[] sArray = S.toCharArray();
for (char j : jArray) {
for (char s : sArray) {
if (j == s) {
num++;
}
}
}
return num;
}
Review:
http://www.hxen.com/englishnews/nation/2019-06-14/519537.html
The Huawei Disaster Reveals Google’s Iron Grip on Android
Open source isn’t as open as you think
BEIJING, June 13 (Xinhua) -- "China will fight to the end if the United States continues to escalate trade frictions," the Ministry of Commerce (MOC) said Thursday.
China will not give ground on issues of principle during bilateral economic and trade talks, which are clearly stated in a white paper on bilateral trade consultations issued earlier this month, MOC spokesperson Gao Feng told a press conference.
In response to the new threat of tariffs by the United States, Gao said China is firmly against U.S. unilateralism and bullying.
"China's stance on trade war has been consistent and clear. We do not want, but is not afraid of a trade war.
The United States has taken a practice of maximum pressure and continuously escalated trade frictions, causing serious setbacks in the China-U.S. trade talks, according to Gao. "The United States is entirely to blame."
"China's attitude is very clear. The United States must change its attitude, show sincerity and correct its wrong practices if it wants the talks to continue," Gao said.
Tip:
@RunWith(MockitoJUnitRunner.class)
@Mock
RestTemplate restTemplate;
@Mock
XXXClient client;
@InjectMocks
ServiceImpl serviceImpl;
@before
MockitoAnnotations.intiMocks(this)
mokito mock的方法的参数要么全部使用mock方式,要不全都不适用mock方式。
有的参数用真实参数,有的用mockito.eq(类名)
会抛出 org.mockito.exections.misusing.InvalidUseOfMatchersException:
Invaild use of argument matchers!
单元测试抛出异常的话,是可以用mock以及结合单元测试(Spring)加载方式的。
单元测试如何覆盖try catch中catch内部的语句
例如:DataSource (随便写的一个service)
@autowired
DataSource dataSource;
@InjectMocks
DataSource mockDataSource;
@Mock
opeatorService operatorService;
在方法内部实现。
mock.dothrow(runtimeException.class)when(operatorService).find();
mockDataSource.getDataSource();-->内部存在operatorService.find()方法
当运行到operatorService.find()那一行代码时,就会抛出你所定义的异常。这样就可以解决单元测试覆盖try catch中catch内部的语句。
注意:
用mock过得service调用方法,才会触发mock效果。即现在的throw Exception.
Share:
https://mp.weixin.qq.com/s/BywcSVxCdMCVOdJlwvDbTg
Spring Cloud Stream 使用延迟消息实现定时任务(RabbitMQ)
原创: 翟永超 程序猿DD 1月5日
来源:https://0x9.me/xnC2g
应用场景
我们在使用一些开源调度系统(比如:elastic-job等)的时候,对于任务的执行时间通常都是有规律性的,可能是每隔半小时执行一次,或者每天凌晨一点执行一次。然而实际业务中还存在另外一种定时任务,它可能需要一些触发条件才开始定时,比如:编写博文时候,设置2小时之后发送。对于这些开始时间不确定的定时任务,我们也可以通过Spring Cloud Stream来很好的处理。
为了实现开始时间不确定的定时任务触发,我们将引入延迟消息的使用。RabbitMQ中提供了关于延迟消息的插件,所以本文就来具体介绍以下如何利用Spring Cloud Stream以及RabbitMQ轻松的处理上述问题。
动手试试
插件安装
关于RabbitMQ延迟消息的插件介绍可以查看官方网站:https://www.rabbitmq.com/blog/2015/04/16/scheduling-messages-with-rabbitmq/
安装方式很简单,只需要在这个页面:http://www.rabbitmq.com/community-plugins.html 中找到 rabbitmq_delayed_message_exchange插件,根据您使用的RabbitMQ版本选择对应的插件版本下载即可。
注意:只有RabbitMQ 3.6.x以上才支持
在下载好之后,解压得到 .ez结尾的插件包,将其复制到RabbitMQ安装目录下的 plugins文件夹。
然后通过命令行启用该插件:
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
该插件在通过上述命令启用后就可以直接使用,不需要重启。
另外,如果您没有启用该插件,您可能为遇到类似这样的错误:
ERROR 156 --- [ 127.0.0.1:5672] o.s.a.r.c.CachingConnectionFactory : Channel shutdown: connection error; protocol method: #method(reply-code=503, reply-text=COMMAND_INVALID - unknown exchange type 'x-delayed-message', class-id=40, method-id=10)
应用编码
下面通过编写一个简单的例子来具体体会一下这个属性的用法:
@EnableBinding(TestApplication.TestTopic.class)
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@Slf4j
@RestController
static class TestController {
@Autowired
private TestTopic testTopic;
/**
* 消息生产接口
*
* @param message
* @return
*/
@GetMapping("/sendMessage")
public String messageWithMQ(@RequestParam String message) {
log.info("Send: " + message);
testTopic.output().send(MessageBuilder.withPayload(message).setHeader("x-delay", 5000).build());
return "ok";
}
}
/**
* 消息消费逻辑
*/
@Slf4j
@Component
static class TestListener {
@StreamListener(TestTopic.INPUT)
public void receive(String payload) {
log.info("Received: " + payload);
}
}
interface TestTopic {
String OUTPUT = "example-topic-output";
String INPUT = "example-topic-input";
@Output(OUTPUT)
MessageChannel output();
@Input(INPUT)
SubscribableChannel input();
}
}
内容很简单,既包含了消息的生产,也包含了消息消费。在 /sendMessage接口的定义中,发送了一条消息,一条消息的头信息中包含了 x-delay字段,该字段用来指定消息延迟的时间,单位为毫秒。所以上述代码发送的消息会在5秒之后被消费。在消息监听类 TestListener中,对 TestTopic.INPUT通道定义了 @StreamListener,这里会对延迟消息做具体的逻辑。由于消息的消费是延迟的,从而变相实现了从消息发送那一刻起开始的定时任务。
在启动应用之前,还要需要做一些必要的配置,下面分消息生产端和消费端做说明:
消息生产端
spring.cloud.stream.bindings.example-topic-output.destination=delay-topic
spring.cloud.stream.rabbit.bindings.example-topic-output.producer.delayed-exchange=true
注意这里的一个新参数 spring.cloud.stream.rabbit.bindings.example-topic-output.producer.delayed-exchange,用来开启延迟消息的功能,这样在创建exchange的时候,会将其设置为具有延迟特性的exchange,也就是用到上面我们安装的延迟消息插件的功能。
消息消费端
spring.cloud.stream.bindings.example-topic-input.destination=delay-topic
spring.cloud.stream.bindings.example-topic-input.group=test
spring.cloud.stream.rabbit.bindings.example-topic-input.consumer.delayed-exchange=true
在消费端也一样,需要设置 spring.cloud.stream.rabbit.bindings.example-topic-output.producer.delayed-exchange=true。如果该参数不设置,将会出现类似下面的错误:
ERROR 9340 --- [ 127.0.0.1:5672] o.s.a.r.c.CachingConnectionFactory : Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'type' for exchange 'delay-topic' in vhost '/': received 'topic' but current is ''x-delayed-message'', class-id=40, method-id=10)
完成了上面配置之后,就可以启动应用,并尝试访问 localhost:8080/sendMessage?message=hello接口来发送一个消息到MQ中了。此时可以看到类似下面的日志:
2019-01-02 23:28:45.318 INFO 96164 --- [ctor-http-nio-3] c.d.s.TestApplication$TestController : Send: hello
2019-01-02 23:28:45.328 INFO 96164 --- [ctor-http-nio-3] o.s.a.r.c.CachingConnectionFactory : Attempting to connect to: [localhost:5672]
2019-01-02 23:28:45.333 INFO 96164 --- [ctor-http-nio-3] o.s.a.r.c.CachingConnectionFactory : Created new connection: rabbitConnectionFactory.publisher#5c5f9a03:0/SimpleConnection@3278a728 [delegate=amqp://guest@127.0.0.1:5672/, localPort= 53536]
2019-01-02 23:28:50.349 INFO 96164 --- [ay-topic.test-1] c.d.stream.TestApplication$TestListener : Received: hello
从日志中可以看到, Send:hello和 Received:hello两条输出之间间隔了5秒,符合我们上面编码设置的延迟时间。
深入思考
在代码层面已经完成了定时任务,那么我们如何查看延迟的消息数等信息呢?
此时,我们可以打开RabbitMQ的Web控制台,首先可以进入Exchanges页面,看看这个特殊exchange,具体如下:
可以看到,这个exchange的Type类型是 x-delayed-message。点击该exchange的名称,进入详细页面,就可以看到更多具体信息了:
代码示例
本文示例读者可以通过查看下面仓库的中的 stream-delayed-message项目:
Github:https://github.com/dyc87112/SpringCloud-Learning/tree/master/4-Finchley
Gitee:https://gitee.com/didispace/SpringCloud-Learning/tree/master/4-Finchley
如果您对这些感兴趣,欢迎star、follow、收藏、转发给予支持!
获得更多关于Spring Cloud的实战内容,持续关注我哦!
·END·