1. Problem raising
In Struts2, if the ModelDriven<model> interface is implemented, the passed parameters can be injected into the model, and the model can be used in the Action, but what should I do if there are two models that need to be used in the same Action? For example, in the previous section, we completed the online payment function, but the payment has not yet ended. We need to receive information feedback from third parties. For example, after successful payment, we need to send emails and text messages to the payer. So we also need to obtain the parameters passed from the third party in the payAction. Since the parameters passed from the third party are different from those passed by us, we have to write a Model (BackData) to receive those parameters. So the problem is, our PayAction has been written as follows: public class PayAction extends BaseAction<SendData>, that is, the ModelDriven<SendData> interface has been implemented in the BaseAction. So how do we receive another Model in an action and have to handle them differently?
There is a solution (actually, it cannot be called a solution... because it is not solved at all...) which is to write a Model and then let SendData and BackData inherit it, but the problem is that these two Models have nothing to do at all, why do you need to inherit the same Model? So this solution is actually escaping the above problem.
This problem is solved well in SpringMVC (SpringMVC hasn't really started learning. If you say something wrong, please correct it!) because each method in SpringMVC corresponds to a Model, rather than each Action corresponds to a Model, which is convenient. I can just write two methods in the same Action, and different methods deal with different Models.
2. Solution to the problem
Struts2 also provides a solution to this problem:
Struts2 stores many maps in the ActionContext, such as the request, session, application, etc. mentioned earlier. There is also a parameterMap, which stores all the request parameters of the request. As long as our Action implements the parameterAware interface, we can get this parameterMap. This is the same as ModelDriven. If we implement the ModelDriven<Model> interface, then we can get the Model in the Action, that is, define a Model and implement the set method.
Okay, now the problem is easy to solve. The payment parameters and the returned parameters are different. That is to say, the parameters that enter PayAcition twice are different, that is, the data installed in the parameterMap twice is different. As long as we select a parameter in the Action (the parameter can be distinguished from the two different request requests) as a judgment, we will know which Model should be used to receive the parameters (SendData or BackData). Let's rewrite the code in PayAction:
@Controller("payAction")@Scope("prototype")public class PayAction extends BaseAction<Object> implements ParameterAware {//Note that SendData cannot be written in the BaseAction inherited above. You need to write Object. Later, we will determine which one to use //Define a Map to receive request private Map<String, String[]> parameters; @Override public void setParameters(Map<String, String[]> parameters) { this.parameters = parameters; } /*In the struts-default.xml article, the ServletConfig interceptor is executed before ModelDriven, so when we inject the model, the request parameter is already available, so we can use parameters in the getModel() method to determine which request is used by parameters */ @Override public Object getModel() { //There is a payment channel coded parameter (pd_FrpId) when paying, but it does not return // This way we can use this parameter to determine whether it is paid or returned if(parameters.get("pd_FrpId") != null) { model = new SendData(); } else { model = new BackData(); } return model; } //Method for sending data to Yibao public String goBank() { //The corresponding sent model: SendData SendData sendData = (SendData)model; //The logic of sending data has been implemented in the previous section... } //The method of receiving returned data public void backBank() { //The corresponding received model: BackData BackData backData = (BackData)model; //The logic of handling returned data...it will be implemented later, //The knowledge point of Struts2 first handles multiple Model requests}}3. Struts2 processing flow
Let’s analyze the execution process of Struts2, which will be more conducive to understanding the above principles. Struts processing flow:
1) After obtaining the request, first create the Action's proxy, and then create the Action when creating the proxy;
2) Execute 18 interceptors, and then call the Action method after the interceptor is executed successfully;
3) After the Action method is executed, 18 interceptors are called. So according to this process, we know: first create Action> and then execute the interceptor (first execute ServletConfig, then execute ModelDriven, because the ServletConfig interceptor is equipped in front of ModelDriven). So in the above code, we can use the data in parameterMap in the getModel() method to make judgments.
Use the following simple timing diagram to intuitively represent the above processing flow:
This shows the processing flow of Struts2 intuition, so it is easy to understand the above processing multiple Model requests. At this point, the part of the method of Struts2 to handle multiple Model requests has been analyzed. The following is a small logic in this project.
4. Improve the method of receiving data
A logic behind this is the implementation of logic, that is, processing the returned data. The logic here mainly includes: updating the order status (paid, shipped, etc.), sending emails, sending text messages, etc. We will first complete the update order status, send emails and send text messages to the subject, and we will write it later.
First improve the backBank() method:
public void backBank() { BackData backData = (BackData)model; System.out.println(model); boolean isOK = payService.checkBackData(backData); if(isOK) { //1. Update the order status, the parameters are transmitted in according to the situation in the database, used to test forderService.updateStatusById(Integer.valueOf(201605006), 2); //2. Send an email according to the user email address //3. Send a mobile phone text message System.out.println("----success!!-----"); } else { System.out.println("----false!!!-----"); }}Then we complete the checkBackData(backData) method in payService (the logic is basically the same as in Section 21):
@Service("payService")public class PayServiceImpl implements PayService { //Omit irrelevant code/*************************************** above is the method to send the request*******************************************************/ // Complete the append private String joinBackDataParam(BackData backData) { // Append string to prepare for encryption verification StringBuffer infoBuffer = new StringBuffer(); infoBuffer.append(backData.getP1_MerId()); infoBuffer.append(backData.getR0_Cmd()); infoBuffer.append(backData.getR1_Code()); infoBuffer.append(backData.getR2_TrxId()); infoBuffer.append(backData.getR3_Amt()); infoBuffer.append(backData.getR4_Cur()); infoBuffer.append(backData.getR5_Pid()); infoBuffer.append(backData.getR6_Order()); infoBuffer.append(backData.getR7_Uid()); infoBuffer.append(backData.getR8_MP()); infoBuffer.append(backData.getR9_BType()); return infoBuffer.toString(); } // Encrypt the returned data and compare it with the ciphertext sent over. If OK, it means that the data has not been tampered with. public boolean checkBackData(BackData backData){ String joinParam=this.joinBackDataParam(backData); // Get your own ciphertext String md5 = DigestUtil.hmacSign(joinParam.toString(),key); // Comparison of ciphertext with the ciphertext sent over return md5.equals(backData.getHmac()); } }Finally, we complete the updateStatusById method in ForderService:
//ForderService interface public interface ForderService extends BaseService<Forder> { //Omit other unrelated codes... //Update the order status according to the order number public void updateStatusById(int id, int sid);}//ForderServiceImpl implementation class @Service("forderService")public class ForderServiceImpl extends BaseServiceImpl<Forder> implements ForderService { //Omit other unrelated codes @Override public void updateStatusById(int id, int sid) { String hql = "update Forder f set f.status.id=:sid where f.id=:id"; getSession().createQuery(hql) .setInteger("sid", sid) .setInteger("id", id) .executeUpdate(); } }This will enable the order status to be updated after the customer pays.
Original link: http://blog.csdn.net/eson_15/article/details/51465067
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.