From a real interview question, talk about the message mechanism.

Preface

Last Monday, my colleague encountered a more interesting interview question. To the effect, we used a lot in projects like distributed message queues, such as RocketMQ, Kafkaetc., their advantages, such as 解耦everyone is familiar with them, then, there is Did not use some stand-alone queues or event notification mechanisms in the project?

Frankly speaking, most of the students usually develop CRUD as the mainstay. In addition to distributed queues, there are still relatively few things that can get involved with queues. It may be easier to think of, there is 队列such a concept in the thread pool . But this kind of blunt queue "remote relatives" may not be what the interviewer wants to hear. Based on his own experience, Fei Chao will talk about the stand-alone queue or the scene of the event notification mechanism.

Scene description

Let me briefly explain the background. Every company must have some front-end and back-end interaction specifications, such as common formats 请求头参数, 响应jsonformats, etc. This is easy to understand. So we will spring-boot-starter-webcarry out secondary development on the basis of this, and make some enhancements, named here feichao-boot-starter-web. (Don’t ask me what feichao is)

Special statement, the reason why we do secondary development is not only for the above-mentioned functions, all the enhanced functions are not the focus of this article, and will not be introduced here.

But we know that there must be some URLs that do not need to verify the request header. For example, we have also made some enhancements to Swagger feichao-boot-starter-swagger. Therefore, you need to feichao-boot-starter-webmake some URLs that ignore verification.

public class FeiChaoMVCProperties {

   /**
    * 忽略校验请求头的url
    */

   private List<String> filter = new ArrayList<>();
}

What problem did we encounter?

Slightly familiar with the principles of swagger, for example, when we open the html interface of swagger, we must visit your web project to obtain the relevant parameter information of swagger, then the problem is coming. This request obviously does not require schooling. Verify the URL of the request header. In other words, the request initiated by swagger's html interface does not require any request header verification processing. But we are feichao-boot-starter-webdoing interception verification processing of the request header.

For this function, Fei Chao believes that there are several common solutions.

Analysis of common problem solving ideas

1. Rely on api

要么feichao-boot-starter-swagger依赖feichao-boot-starter-web然后往FeiChaoMVCPropertiesfilter里面set进相关的swagger请求URL,从而达到忽略校验的目的。但是这样就会出现一个问题,就是feichao-boot-starter-swagger就会依赖feichao-boot-starter-web。我们都知道,starter就相当于一个组件,组件和组件之间就不应该有依赖关系,再说,我们写代码,提倡的不就是低耦合。其实生活也是一样的,舔狗不就是因为过度依赖对方,一直舔,最后一无所有?

当然你可能会说,那我把这个FeiChaoMVCProperties放在一个公共的common.jar不就行了?当然这个也可以,但是你想FeiChaoMVCProperties的字段以及后续维护,肯定是和该starter-web相关的,如果放在common.jar,和我们面向对象的想法,总还是有些违背。

2.配置

那么还有一种方案,就是FeiChaoMVCProperties还是放在starter-web,但是FeiChaoMVCProperties的内容,是可以通过配置文件配置的方式来设置值,这样,把swagger的相关URL,放在配置文件不就行了。看似没问题,但是你想啊,我现在用丝袜哥(swagger)你就配置一下url,那万一我后面又多增加一个肥朝哥,难道你配置文件又要配置一下url?

如何解决遇到的问题?

那么这个问题如何解决呢?我们可以利用Spring的事件机制,当然有些同学可能用到的是GuavaEventBus。但是为了尽量减少依赖,我们就直接用Spring的。

我们在feichao-boot-starter-web的模块就可以进行监听

@Component
public class FilterUrlListener implements ApplicationListener<UrlFilterEvent>{

   @Autowired
   private SpringMVCProperties springMVCProperties;

   @Override
   public void onApplicationEvent(UrlFilterEvent event) {
       List<String> urls = event.getSource();
       springMVCProperties.getFilter().addAll(urls);
   }

}

然后feichao-boot-starter-swagger进行发送

@Component
@Slf4j
public class SwaggerFilterUrlEvent implements ApplicationContextAware {

   @Override
   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
       applicationContext.publishEvent(new UrlFilterEvent(SwaggerConstant.SWAGGER_URLS));
   }
}

这样,两个组件之间就彻底解耦开来。后续除了丝袜哥(swagger)外,即使增加一个肥朝哥的组件,都不需要改动feichao-boot-starter-web的代码。只需要在肥朝哥的组件中,发送一个消息即可。

因为肥朝平常的日常工作主要是基础架构相关的,任何一个耦合的设计,一旦改动起来,影响还是比较大的。当然除了上述场景,还有一些其他场景,比如目前公司做的是海外业务,就会涉及到国际化,那么就会有多个服务会用到语言这个东西。怎么把语言这个字段,在多个业务之间传递,就会是个问题。如果你直接在业务的DTO,比如订单DTO加个语言的字段,那么就明显很不友好了。如何做到业务方随时随地都能获取语言,但是语言这个字段又不和具体业务DTO耦合?那么这个肥朝下期再讲,防止一些假粉老是白嫖,每次看完了就取关!!!

知识拓展

关注肥朝公众号的老粉丝想必都知道,肥朝向来不解决某一个问题,对于这个问题的思考,我们到这里就截止了吗?当然不是,比如,我们文中提到的过滤URL。这个过滤URL,我们希望做成类似SpringMVC,或者Tomcat这样,能配置/*/feichao/*等形式,那么怎么实现这个需求呢?

其实这个问题,常见的错误做法是,花费大量的时间写一个这样的匹配URL逻辑,甚至恶补一下正则表达式之类的。但是这些做法都有如下缺点:

1.如果你写的这个规则比较蹩脚,业务方的同事需要了解你这个配置的规则,需要一定的学习成本

2.自己写的,bug多多不说,正则这个出问题了,不好debug

3.花费的时间巨大,得不偿失

那么,根据肥朝的愚见,比较合适的做法是怎么样呢?其实这个你直接参考Tomcat或者SpringMVC中的这个功能,看一下他们是怎么实现的,然后把他们的代码拷贝过来,这样,业务方的同学,需要配相关URL的时候,他就根本不需要重新学习,就按照之前SpringMVC的配置习惯来即可,另外,经过SpringMVC、Tomcat等知名项目考验,稳定性没问题,最重要的是,你如果有阅读源码的优秀习惯,找到这段功能代码,基本是半个小时之内,比你自己写个类似逻辑,简直好太多,所以,不要再问我,看源码有没有用了。

当然这个功能,Spirng提供了一个好的工具类做类似的事,你直接使用即可,AntPathMatcher。什么,你不知道这个工具类,早喊你关注肥朝的公众号你就是不听!

除此之外,还有哪些使用场景?

当然对于事件机制,还有很多的使用场景,比如,肥朝要求每个项目配置文件必须设置appName,那么我就需要在Spring容器启动的时候,做相应的校验,如果没设置,就不允许项目启动。当然还有今天群里朋友讨论的,一些CRUD记录操作日志的场景,除了注解+AOP的方式来记录操作日志,也可以在执行完操作后,发出一个消息,然后在监听消息做相关的日志记录。

当然,相信日常工作内容丰富多彩极具挑战性的你,也肯定还有一些其他的使用场景,欢迎留言告诉肥朝。



图片


Guess you like

Origin blog.51cto.com/15082403/2591228