In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly explains "the methods and steps of realizing pipeline pattern based on Spring". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "the methods and steps of implementing pipeline pattern based on Spring".
Pipeline mode (Pipeline Pattern) is one of the common variants of chain of responsibility mode (Chain of Responsibility Pattern). In the pipeline mode, the pipeline acts as an assembly line, transferring the data to a processing sequence. After the data is processed in each step, it is transferred to the next step for processing until all the steps are completed.
PS: pure chain of responsibility mode will have only one processor on the chain to process data, while multiple processors in pipeline mode will process data.
When to use pipe mode
When the task code is complex and needs to be split into multiple sub-steps, especially when you may add new sub-steps, delete old sub-steps, and swap the order of sub-steps anywhere later, you can consider using pipeline mode.
Use pipe mode happily
Background playback
At the beginning of building a model platform, the function of creating a model instance includes three steps: "input data verification-> create a model instance based on input-> Save the model instance to the relevant DB table", which is not complicated, so the code at that time is roughly like this:
Public class ModelServiceImpl implements ModelService {/ * submit model (build model instance) * / public CommonReponse buildModelInstance (InstanceBuildRequest request) {/ / input data to verify validateInput (request); / / create model instance ModelInstance instance = createModelInstance (request) based on input; / / save the instance to the relevant DB table saveInstance (instance);}}
Before long, however, we found that the format of the form input data did not fully meet the input requirements of the model, so we wanted to add "form data preprocessing". This function has not yet been put into practice, and some business parties have proposed that they also need to deal with the data (for example, according to the merchant's form input, generate some other business data as model input).
So after "input data check", you also need to add "form input and output preprocessing" and "business side custom data processing (optional)". At this point I was faced with a choice: do you want to continue to implement these new processing steps by adding new methods to buildModelInstance? The advantage is that you can be lazy right now, but what about the disadvantages:
ModelService should only be used to receive HSF requests, not to host business logic. If you write all the logic of the submission model in this class, it violates a single responsibility and later causes the class code to explode.
In the future, every time I add a new processing step or delete a step, I have to modify buildModelInstance, which is supposed to be very cohesive, in violation of the opening and closing principle.
Therefore, in order not to dig a hole for myself in the future, I think it is necessary to think about a comprehensive plan. At this time, my little head began to fly around and suddenly flashed past the ChannelPipeline in Netty-- Oh, the plumbing mode was just what I needed!
There are also a variety of ways to implement the pipeline pattern, and then based on the previous background, I share my current "best routine" for implementing the pipeline pattern based on Spring.
Define the context of pipeline processing
/ * context passed to the pipeline * / @ Getter@Setterpublic class PipelineContext {/ * processing start time * / private LocalDateTime startTime; / * processing end time * / private LocalDateTime endTime; / * get the data name * / public String getName () {return this.getClass () .getSimpleName ();}}
Define a context processor
The context processor in the / * pipeline * / public interface ContextHandler {/ * handles the input context data * * @ param context context data * @ return returns true means the next ContextHandler continues processing, and returns false indicates the end of processing * / boolean handle (T context);}
For ease of illustration, let's first define the context and associated processors for the earliest version of submit Model Logic:
/ * context of model instance construction * / @ Getter@Setterpublic class InstanceBuildContext extends PipelineContext {/ * * Model id * / private Long modelId; / * * user id * / private long userId; / * form input * / private Map formInput / * after saving the model instance, record the error message of id * / private Long instanceId; / * model creation error * / private String errorMsg; / / other parameters @ Override public String getName () {return "model instance construction context";}}
Processor-input data check:
@ Componentpublic class InputDataPreChecker implements ContextHandler {private final Logger logger = LoggerFactory.getLogger (this.getClass ()); @ Override public boolean handle (InstanceBuildContext context) {logger.info ("--input data check--"); Map formInput = context.getFormInput (); if (MapUtils.isEmpty (formInput)) {context.setErrorMsg ("form input data cannot be empty"); return false } String instanceName = (String) formInput.get ("instanceName"); if (StringUtils.isBlank (instanceName)) {context.setErrorMsg ("form input data must contain instance name"); return false;} return true;}}
Processor-create a model instance based on input:
@ Componentpublic class ModelInstanceCreator implements ContextHandler {private final Logger logger = LoggerFactory.getLogger (this.getClass ()); @ Override public boolean handle (InstanceBuildContext context) {logger.info ("- create a model instance based on input data -"); / / pretend to create a model instance return true;}}
Processor-Save the model instance to the relevant DB table:
@ Componentpublic class ModelInstanceSaver implements ContextHandler {private final Logger logger = LoggerFactory.getLogger (this.getClass ()); @ Override public boolean handle (InstanceBuildContext context) {logger.info ("--Save the model instance to the relevant DB table--"); / / pretend to save the model instance return true;}}
At this point, the question arises: what method should be used to concatenate the ContextHandler of the same Context into a pipeline? Think about it:
Add a setNext method to ContextHandler, and each implementation class must specify its next processor. The disadvantage is also obvious: if you add a new ContextHandler in the middle of the current pipeline, it is necessary to modify the setNext method of the previous ContextHandler; in addition, the code is written for people to read, so you can't intuitively know the processing link of the entire pipeline at a glance, but also go to each relevant ContextHandler to check it.
Add @ Order annotation to ContextHandler, and determine the sequence of each ContextHandler according to the number given in @ Order. At the beginning, each number interval can be larger (for example, 10, 20, 30). Later, when adding a new ContextHandler, you can specify the number (11, 21, 31), so you can avoid the problem of modifying the code in the above scheme. However, it is still impossible to avoid the problem of going into each relevant ContextHandler to know that the pipeline is handling the link.
Write a routing table in advance, specify the mapping of "Context-> pipes" (pipes are represented by List), and the order of processors in the pipes. According to this routing table, Spring builds a Map,Map whose key is Context at startup, and the value is List. In this way, if you want to know the processing link of each pipeline, just look at this routing table and make it clear at a glance. The disadvantage is that every time a new ContextHandler is added, this routing table also needs to make a small change on the corresponding pipeline-but if you can read the code more clearly, I think such a change is worthwhile and acceptable.
Build a pipe routing table
Based on the Java Bean configuration of Spring, we can easily construct the routing table of the pipeline:
/ * * configuration of pipe routing * / @ Configurationpublic class PipelineRouteConfig implements ApplicationContextAware {/ * * data types-> routing of processor type lists in pipes * / private static final Map
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 255
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.