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,然后让SendData
和BackData
继承它,但是问题是这两个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
中的数据来进行判断。
用下面简单的时序图来直观的表示一下上面的处理流程吧:
这就很直观的看出Struts2的处理流程了,那么对于上面处理多个Model请求也很好理解了。到这里,Struts2处理多个Model请求的方法部分已经分析完了,下面针对本项目中的一个小逻辑,做一下完善。
4. 完善接收数据的方法 |
上面遗留了一个逻辑的实现,即处理返回的数据,这里的逻辑主要有:更新订单状态(已付款,已发货等),发送邮件,发送短信等。我们先把更新订单状态完成,主语发送邮件和发送短信的功能,我们后面再写。
先完善backBank()
方法:
public void backBank() {
BackData backData = (BackData)model;
System.out.println(model);
boolean isOK = payService.checkBackData(backData);
if(isOK) {
//1. 更新订单状态,参数是自己根据数据库中的情况传进去的,用来测试
forderService.updateStatusById(Integer.valueOf(201605006), 2);
//2. 根据user邮箱地址,发送邮件
//3. 发送手机短信
System.out.println("----success!!----");
} else {
System.out.println("----false!!!----");
}
}
然后我们完成payService中的checkBackData(backData)
方法(逻辑和21节中的基本一样):
@Service("payService")
public class PayServiceImpl implements PayService {
//省略不相关代码
/******************************上面是发送请求的方法**************************************/
// 完成返回数据的追加
private String joinBackDataParam(BackData backData) {
// 追加字符串,为加密验证做准备
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();
}
// 对返回来的数据进行加密,并且和传过来的密文进行比较,如果OK则说明数据没有被篡改
public boolean checkBackData(BackData backData){
String joinParam=this.joinBackDataParam(backData);
// 加密后得到自己的密文
String md5 = DigestUtil.hmacSign(joinParam.toString(),key);
// 密文和传过来密文比较
return md5.equals(backData.getHmac());
}
}
最后我们完成ForderService中的updateStatusById
方法:
//ForderService接口
public interface ForderService extends BaseService<Forder> {
//省略其他无关代码……
//根据订单编号,更新订单状态
public void updateStatusById(int id, int sid);
}
//ForderServiceImpl实现类
@Service("forderService")
public class ForderServiceImpl extends BaseServiceImpl<Forder> implements ForderService {
//省略其他无关代码
@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();
}
}
这样就能在顾客付款后更新订单状态了。
【SSH网上商城项目实战24】Struts2中如何处理多个Model请求的更多相关文章
-
【SSH网上商城项目实战30】项目总结
转自:https://blog.csdn.net/eson_15/article/details/51479994 0. 写在前面 项目基本完成了,加上这个总结,与这个项目相关的博客也写了30篇了 ...
-
【SSH网上商城项目实战30】项目总结(附源码下载地址)
项目基本完成了,加上这个总结,与这个项目相关的博客也写了30篇了,积少成多,写博客的过程是固化思路的一个过程,对自己很有用,同时也能帮助别人.顺便说个题外话,在学习的过程中肯定会遇到很多异常出现,我们 ...
-
【SSH网上商城项目实战27】域名空间的申请和项目的部署及发布
转自:https://blog.csdn.net/wwww_com/article/details/54405355 前面陆陆续续的完成了网上商城的一些基本功能,虽然还有很多地方有待完善,但是不影响 ...
-
【SSH网上商城项目实战21】从Demo中看易宝支付的流程
转自: https://blog.csdn.net/eson_15/article/details/51447492 这一节我们先写一个简单点的Demo来测试易宝支付的流程,熟悉这个流程后, ...
-
【SSH网上商城项目实战16】Hibernate的二级缓存处理首页的热门显示
转自:https://blog.csdn.net/eson_15/article/details/51405911 网上商城首页都有热门商品,那么这些商品的点击率是很高的,当用户点击某个热门商品后需要 ...
-
【SSH网上商城项目实战01】整合Struts2、Hibernate4.3和Spring4.2
转自:https://blog.csdn.net/eson_15/article/details/51277324 今天开始做一个网上商城的项目,首先从搭建环境开始,一步步整合S2SH.这篇博文主要总 ...
-
【SSH网上商城项目实战15】线程、定时器同步首页数据(类似于博客定期更新排名)
转自:https://blog.csdn.net/eson_15/article/details/51387378 上一节我们做完了首页UI界面,但是有个问题:如果我在后台添加了一个商品,那么我必须重 ...
-
【SSH网上商城项目实战25】使用java email给用户发送邮件
转自: https://blog.csdn.net/eson_15/article/details/51475046 当用户购买完商品后,我们应该向用户发送一封邮件,告诉他订单已生成之类的信息, ...
-
【SSH网上商城项目实战20】在线支付平台的介绍
转自:https://blog.csdn.net/eson_15/article/details/51441431 之前已经完成了首页的显示,用户添加购物车,确认订单等功能,下面就是支付功能的开发了. ...
随机推荐
-
移动平台对于META标签的定义[转]
下面介绍一些有关标记的例子及解释. 一.meta 标签分两大部分:HTTP 标题信息(http-equiv)和页面描述信息(name). 1.http-equiv 属性的 Content-Type 值 ...
-
【Gym 100712A】Who Is The Winner?
题 题意 解题数目越多越排前,解题数目相同罚时越少越排前,求排第一的队伍名字. 分析 用结构体排序. 代码 #include<cstdio> #include<algorithm&g ...
-
[转] C# 键盘中的按键对应的KeyValue
原文C#KeyValue对应键盘 首先先看一下什么情况下需要对按键进行识别: KeyPress事件响应函数中,有KeyPressEventArgs, 对应于e.KeyChar; KeyDown事件响应 ...
-
jquery UI推荐
Bootstrap http://www.bootcss.com/ http://www.ligerui.com/ http://j-ui.com/#demo_page2 http://jqueryu ...
-
YII 路由配置
伪静态,通过设置server服务,做域名地址的转换工作. urlManager地址美化,通过程序的方式实现地址美化工作. 通过在主配置文件里配置组件来实现: 'components'=>arra ...
-
scrapy入门使用
scrapy入门 创建一个scrapy项目 scrapy startporject mySpider 生产一个爬虫 scrapy genspider itcast "itcast.cn&qu ...
-
HAProxy 实现 mysql 负载均衡
通过yum 安装和配置HAProxy # yum install -y haproxy #安装haproxy # rpm -qa | grep haproxy #查看安装的haprox ...
-
在Windows2008下安装SQL Server 2005无法启动服务的解决办法
在Windows2012下安装SQL Server 2005无法启动服务的解决办法 1.正常安装任一版本的SQL Server 2005. 2.安装到SqlServer服务的时候提示启动服务失败 此 ...
-
关于er模型中的identifying relationship or non-identifying relationship
最近,主要负责项目管理和领域模型设计方面的工作,昨天在将UML类图转换为ER模型的时候,发现有identifying relationship or non-identifying relations ...
-
Oracle12c版本中未归档隐藏参数
In this post, I will give a list of all undocumented parameters in Oracle 12.1.0.1c. Here is a query ...