SSH网上商城项目实战24Struts2中如何处理多个Model请求

Posted 武哥聊编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSH网上商城项目实战24Struts2中如何处理多个Model请求相关的知识,希望对你有一定的参考价值。

1. 问题的提出

  Struts2中如果实现了ModelDriven<model>接口就可以将传来的参数注入到model中了,就可以在Action中使用该model,但是如果现在有两个model都需要在同一个Action中使用该咋整呢?比如上一节我们完成了在线支付功能,但是支付完成了还没结束,我们需要接收从第三方那边反馈回来的信息,比如成功支付后,我们需要给付款方发送邮件和短信等。所以我们还需要在payAction中获取从第三方传过来的参数,由于从第三方传过来的参数与我们传过去的参数是不同的,所以接收那些参数我们也得写一个Model(BackData),那么问题来了,我们的PayAction已经写成这样子了:public class PayAction extends BaseAction<SendData>,即已经在BaseAction中实现了ModelDriven<SendData>接口了,那么如何在一个action中再接收一个Model,并且还得对它们进行不同的处理呢?
  有种解决办法(其实也不能称为解决办法……因为根本就没解决……)就是写一个Model,然后让SendDataBackData继承它,但是问题是这两个Model根本就没关系,为啥要继承同一个Model,所以这种解决办法实际上是在逃避上面的问题。
  在SpringMVC(SpringMVC还没真正开始学,如果有说错,请指正!)很好的解决了这个问题,因为SpringMVC中每个方法对应一个Model,而不是每个Action对应一个Model,这就方便了,我在同一个Action中写两个方法即可,不同的方法处理不同的Model。

2. 问题的解决

  针对这个问题,Struts2也提供了一种解决办法:
  Struts2在ActionContext中存储了很多个Map,比如之前提到的request, session, application等,其中还有个parameterMap,该Map中存储了request所有的请求参数,只要我们的Action实现了parameterAware接口,就能拿到这个parameterMap,这就跟ModelDriven的道理是一样的,如果我们实现了ModelDriven<Model>接口,那么我们在Action中就能获得该Model,即定义一个Model并实现set方法即可。
  好了,那现在问题好办了,支付的参数和返回的参数是不同的,也就是说两次进入PayAcition中的参数是不同的,即两次的parameterMap中装的数据不一样,那只要我们在Action中选取一个参数(该参数只要能区分两次是不同的request请求即可)作为判断,就知道当前该用哪个Model来接收参数(SendData还是BackData)。下面我们改写一下PayAction中的代码:

@Controller("payAction")
@Scope("prototype")
public class PayAction extends BaseAction<Object> implements ParameterAware {
//注意上面继承的BaseAction中不能写SendData了,要写Object,等下我们再判断具体使用哪个 

    //定义一个Map接收request的请求参数
    private Map<String, String[]> parameters;
    @Override
    public void setParameters(Map<String, String[]> parameters) {
        this.parameters = parameters;

    }   
    /*在struts-default.xml文中,ServletConfig拦截器在ModelDriven之前先执行,所以我们在注入model的时候,
    request参数已经有了,这样我们就可以在getModel()方法中通过参数来判断是哪个请求了*/
    @Override
    public Object getModel() {
    //付款的时候有支付通道编码的参数(pd_FrpId),返回的时候没有
    //这样我们就可以通过该参数判断是支付还是返回了
        if(parameters.get("pd_FrpId") != null) {
            model = new SendData();
        } else {
            model = new BackData();
        }
        return model;
    }

    //向易宝发送数据的方法
    public String goBank() {
        //对应发送的model:SendData
        SendData sendData = (SendData)model;
        //处理发送数据的逻辑,前一节已经实现过了……
    }

    //接收返回的数据的方法
    public void backBank() {
        //对应接收的model:BackData
        BackData backData = (BackData)model;
        //处理返回数据的逻辑……后面再来实现,
        //先讲Struts2处理多个Model请求这个知识点
    }
}

3. Struts2的处理流程

  我们再来分析一下Struts2的执行流程,这样更加利于理解上面的原理。Struts处理流程:

  • 获取请求后,先创建Action的代理,在创建代理的时候顺便创建了Action;
  • 执行18个拦截器,拦截器执行成功后再调用Action的方法;
  • Action的方法执行完毕后,再调用18个拦截器

所以根据这个流程,我们知道:先创建Action–>再执行拦截器(先执行ServletConfig,再执行ModelDriven,因为ServletConfig拦截器配在ModelDriven的前面)。所以在上面的代码中,我们才可以在getModel()方法中去拿parameterMap中的数据来进行判断。  
  用下面简单的时序图来直观的表示一下上面的处理流程吧:

Created with Raphaël 2.1.2 struts2启动 struts2启动 Action代理和Action对象 Action代理和Action对象 18个拦截器 18个拦截器 创建 按顺序执行 执行其他拦截器…… 执行ServletConfig拦截器,将request参数放到parameterMap中 执行ModelDriven拦截器,初始化model(我们就在这里拿上面参数进行判断的) 执行其他拦截器…… 再去执行Action中相应的方法 再按顺序执行一次拦截器

以上是关于SSH网上商城项目实战24Struts2中如何处理多个Model请求的主要内容,如果未能解决你的问题,请参考以下文章

深度学习实战pytorch中如何处理RNN输入变长序列padding

SpringBoot.09.SpringBoot中如何处理Filter抛出的异常

PHP 中如何处理并发请求(使用线程、线程池或子进程)

前端VUE项目中如何处理图片加载失效/裂开的问题

实际JAVAWEB项目中如何处理异常消息

在Java 8中如何处理日期和时间