I am 3Y, a markdown programmer with one year CRUD experience and ten years’ experience 👨🏻💻 known as a quality octuan player all the year round

Today’s task is to implement the austin-API and Austin-apI-IMPl modules. Once this is done, the entire link between the modules is open

Austin projectThe core function: Sending a message

Significance of the project: As long as there is a need to send messages, there should be a project like Austin to send all kinds of messages uniformly. This facilitates the collection of functions and improves the efficiency of business requirements development

No more BB, let’s start today’s topic

01. Interface design

The interface for sending messages is defined under austini-API module, and the specific logic is implemented under Austin-API-IMPL. My interface implementation definition:

public interface SendService {
​
​
    /** * Single template single copy send interface *@param sendRequest
     * @return* /
    SendResponse send(SendRequest sendRequest);
​
​
    /** * Single template multiple text send interface *@param batchSendRequest
     * @return* /
    SendResponse batchSend(BatchSendRequest batchSendRequest);
​
}
Copy the code

For external interfaces, it is recommended to provide Batch interfaces in addition to Single interfaces. Because it is likely that the business side will need to execute in batches at once (if there is only a Single interface, multiple remote calls will be required, which is not appropriate for the business)

The interface parameters I defined are as follows:

public class SendRequest {
​
    /** * Execute the business type */
    private String code;
​
    /** * Message template Id */
    private Long messageTemplateId;
​
​
    /** * Message related parameters */
    private MessageParam messageParam;
    
}
Copy the code

MessageTemplateId is used to query the entire template in the database, MessageParam is a parameter that is passed in by the business itself (important is the parameter information of the receiver and the document), and Code represents the type of business to be performed in the current request (which can be extended based on this code). More on that later)

02. Code implementation

As you can see from the flow, after austin-API receives the request, it sends the message to MQ

What’s the good of that? If the service of a message times out, Austin-API may run the risk of timeout if it calls the delivery interface service directly, dragging down the performance of the entire interface. MQ is here to be asynchronous and decoupled, and to some extent resilient to business traffic.

For the vast majority of sent messages, the business does not care that the sent result is known at the time the interface is invoked, and some channels do not know the sent result at the time they are sent (the final result is informed asynchronously, such as SMS and PUSH).

For these reasons, it makes sense to introduce MQ to carry interface traffic and do asynchrony.

The other day I posted an article on the blog platform called “Interviewers: How to Design when System requirements change?” , a netizen commented:

Interviewer: I see. Go home and wait for the announcement. … Leader: Xiao Wang, where are we on the reconfiguration plan for our variable system? Xiao Wang: No problem. First, divide the responsibility chain according to our business, then deploy scripts in each specific step, and add a unified management interface of service orchestration on the upper layer… Leader: That sounds interesting. How are the candidates today? Xiao Wang: Don’t mention it. He says he has 5 years of experience in large-scale system design, but he hasn’t even used Redis. It’s recruitment season, and two intern tool guys are all I need to help me. Leader: Ok, let’s classify milestones and time points. Let’s start at confluence. Xiao Wang: Ok.

In this implementation, I also use the responsibility chain mode, specific complete code we go to Gitee pull. Many students find it difficult to understand the code. You can sort out each role in the responsibility chain according to the figure below. If you really don’t understand it, I suggest you read my previous articles on responsibility chain (I have submitted two).

Back to the code implementation, this time I implement the business is: parameter pre-check -> parameter assembly -> send a message

Ah, have drawn so many pictures, the first point like, pay attention to a wave of first.

In one of these, the next time you pull the code, you might see a “post-check,” or something. But anyway, with this logic I don’t have to write all sorts of if and else on the same class anymore. Just add an Action at a node and you’re done.

(Note: this is the first version of the implementation, I will definitely add logic or comments on the basis of the later, in fact, I am writing, but I usually have a small stage to push the code, so remember gitee under star to see the latest code.)

Let’s start with the pre-check, mainly to determine whether the template ID has been passed in, whether the message parameter has been passed in (the general check of parameters, if there is a problem, directly break the link, return to tell the caller that there is a problem)

The next step is to assemble parameters, which basically look up the contents of the entire template by template ID, and then assemble their TaskInfo based on the business input.

There may be some students who have questions ❓ : why not directly use template POJO? Instead, you need to assemble it into TaskInfo?

In fact, it is easier to understand that the template serves as the information for the user to configure the message, which is the most primitive information. But we need to do some processing when we send it. For example, I want to concatenate parameters on user-written URL links, I want to replace placeholders with real values, I want to add business ids to templates to track data, and so on.

In plain English, TaskInfo is template based with some platforming fields (businessId) added to it, parsing the actual content that the user is trying to send with the template, and so on.

It’s worth noting here that msgContent is the description of the field. In the template, this field is defined in the database comment as (this field must be stored in the database in JSON format) :

'msg_content' vARCHAR (600) COLLATE UTF8MB4_unicoDE_CI NOT NULL DEFAULT 'COMMENT'Copy the code

The JSON structure varies from channel to channel:

  • Message: {” content “:” “, “url” : “”}
  • Mail: {” content “:” “, “the subTitle” : “”}
  • Push: {” content “:” “, “the subTitle” : “”,” phoneImgUrl “:” “}
  • Applet: {“content”:””,”pagePath”:””……. }

My first thought was to define all the fields that channels might use under TaskInfo. That didn’t look good, so I decided to define various models (different delivery channels with their own content models).

So, when I was in the assembly TaskInfo use reflection to be mapped, replace the placeholder with is PropertyPlaceholderHelper

Sending TaskInfo is easy. I serialize TaskInfo directly to JSON and then deserialize it when I read it.

Note that since TaskInfo uses the ContentModel to store the ContentModel, we need to include “class information” when serializing JSON, otherwise we won’t get the subclass data when unserializing JSON.

03,

For projects with source code, I don’t really want to go through every step of the code I wrote. Because I don’t think MY writing is that complicated, and there’s no showmanship involved.

However, since the code push, after reminding you to follow the project partners in the group, several of them gave me feedback that they could not understand, so I will mention this article separately.

Looking back, after the Austin-API layer receives the request, before sending the message to MQ, it’s pretty simple here. It is possible to do the general business here (such as the general weight removal function), but after thinking about it, it is still not a good idea.

Austin-api is kind of an access layer, so far it just reads the configuration from the database through the ID, and there are no time-consuming operations (which means the concurrency it can carry is huge). Assuming there will be a bottleneck in the future to read from the database by ID, we can also consider fetching the configuration from Redis or even local memory.

This is up to the business: changes to a template tend to be small, and even with cache consistency issues, that amount of time is perfectly acceptable.

Question: Why do I need MQ to send a message?

Answer: Sending a message is actually calling the API provided by each service. Assuming that the service of a message times out, Austin-API will have the risk of timeout if it calls the service directly, dragging down the performance of the entire interface. MQ is here to be asynchronous and decoupled, and to some extent resilient to business traffic.

Question: Can you briefly describe what the access layer does?

Answer:

Follow my wechat public number [Java3y] in addition to technology I will also talk about some daily, some words can only say quietly ~ [line interview + write Java project from zero] continuous high intensity update! O star!!!!! Original is not easy!! Three times!!

Gitee link: gitee.com/austin

GitHub link: github.com/austin