关于action向JSP传值

问题:

最近在写SSH的项目,小弟遇到一个问题,一个List 数据在action里回传到JSP获取的问题。当我写到这一步时,我首先想到了老师在跟我们讲的时候说耦合的问题,那是什么耦合呢?这里我说一下。

我查了相关资料,我的理解是这样的……在我们想action像jsp传值的时候我们经常用这种耦合的方法:

action代码:
HttpServletRequest request=ServletActionContext.getRequest();
request.setAttribute("list", list);
jsp代码:
List<User> list=( List<User> )request.getAttribute("list");


这样就能在jsp页面获取这个list集合了,但是这样的方式时耦合的,那为什么耦合呢?

ation中与Servlet API严重耦合。参见以下代码:


public class yourAction extends Action {

    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
                                                ........

Action中重写execute方法必须传入HttpServletRequest和HttpServletResponse对象。在上述代码我是直接创建的HttpServletRequest对象才实现了相关功能。
这里就是所谓的与Servlet API严重耦合的地方。

就像我们写Servlet时用的doPost和doGet 方法似的,如果想用Servlet里的这两个方法必须传入HttpServletRequest和HttpServletResponse对象,否则无法使用。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

..........

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
        .........
    }

解决办法:

下边的文字可不看,简单一句话就是为了:避免与Servlet API耦合在一起,方便Action类做单元测试,

程序员在写完代码时,相应的单元测试也应写完整,否则你的代码就是不能让人信服的
Struts2将Action与Servlet的API进行解耦之后,就使得单元测试变得非常容易了
比如HttpServletRequest对象,它是由Tomcat容器给我们提供的,我们自己产生不出来
若Action中充斥者ServletAPI,哪怕仅一个,那么一般意义上的JUnit单元测试便无法进行
若Action中耦合了ServletAPI,可以采用apache的Cactus对它进行测试,这要稍微麻烦些
另外也可以采用Mock,它本身是模拟的Servlet的API的一些相关的对象
然后用模拟出来的对象代替容器中产生的对象,来实现对应用程序的访问
而Struts2的Action已经脱离了ServletAPI,所以无需这两种方式,便可直接用JUnit测试

Struts2没有与任何的Servlet API耦合
这样可以不依赖于Web容器【如Tomcat】轻松测试Action
Struts2为我们提供了三种方式,使得我们可以轻松获得Servlet的API
①ActionContext
②ServletActionContext
③实现特定接口
由于com.opensymphony.xwork2.ActionContext已经与Servlet的API完全解耦了

所以建议首选ActionContext,次之采用ServletActionContext,最不推荐使用接口

第一种:com.opensymphony.xwork2.ActionContext类

首先通过ActionContext类的静态getContext()方法获得当前线程相关的一个ActionContext实例
然后就可以通过该实例调用它的众多方法得到Servlet的一些API

重点:注意所对应的方法,不要用错了

public Object get(Object key)方法,就相当于HttpServletRequest.getAttribute()
public void put(Object key, Object value)对应 HttpServletRequest.setAttribute()
public Map<String, Object> getParameters()对应 HttpServletRequest.getParameterMap()
public Map<String, Object> getSession()方法对应 javax.servlet.http.HttpSession
session.put(Object key, Object value)对应Servlet编程中的HttpSession.setAttribute(…)

也就是说,ActionContext能够获得三个Map类型的Request, Session, Application对象
ActionContext有一个好处,就是它已经将底层的Servlet进行了转化,比如它将session转化成Map
这样在测试时,Struts2便可脱离Servlet容器进行单纯的JUnit测试

举例:

用session
Action代码:
        ActionContext.getContext().getSession().put("list",list);
        ActionContext.getContext().getSession().put("msg", "欢迎您!");
Jsp代码:
List <User> list=(List<User>)session.getAttribute("list");
至于那个msg字段用String msg=(String)session.getAttribute("msg");或者
EL表达式 :${session.msg}  可省略session


用Request:
Action代码:
        ActionContext.getContext().put("list",list);
        ActionContext.getContext().put("msg", "欢迎您!");
Jsp代码:
List <User> list=(List<User>)request.getAttribute("list");
String msg=(String)request.getAttribute("msg");
最常用的就是这两种了

第二种:org.apache.struts2.ServletActionContext类

ServletActionContext.getRequest()对应javax.servlet.http.HttpServletRequest
ServletActionContext.getResponse()对应javax.servlet.http.HttpServletResponse
ServletActionContext.getServletContext()对应javax.servlet.ServletContext

它的方法全都是static的。另外它所获得的ServletContext对象,就相当于Application
因为它的生命周期与Application生命周期是一样的,只要服务器不关闭,就都是有效的
ServletActionContext可以获得和容器绑定的Request, Response, ServletContext对象
这里获得的都不是Map对象,所以在测试的时候,就必须要启动Tomcat服务器

第三种:org.apache.struts2.util.ServletContextAware接口

它仅有个void setServletContext(javax.servlet.ServletContext context)方法
通过该方法获得的ServletContext就相当于Application,二者生命周期都是相同的
以及org.apache.struts2.interceptor.ServletRequestAware接口
同样有个void setServletRequest(javax.servlet.http.HttpServletRequest request)方法
以及org.apache.struts2.interceptor.ServletResponseAware接口
同样有个void setServletResponse(javax.servlet.http.HttpServletResponse response)方法
使用方式及示例代码,如下所示
此时需设置一个跟Servlet容器耦合的HttpServletRequest类型的request成员变量
当执行完setServletRequest()方法,成员变量就被它的HttpServletRequest参数赋值了
该方法是由Struts2自动调用的,显然这是一种非常非常典型的依赖注入【DI】
由Struts2自动将容器产生的HttpServletRequest对象set到我们应用中的变量上
这样成员变量request就变成了容器所产生的HttpServletRequest对象了
接下来就可以正常的使用request了,使用方法与在Servlet中的使用方式是一样的

public class DecoupleAction implements ServletRequestAware {  
    private HttpServletRequest request;  
    public void setServletRequest(HttpServletRequest arg0) {  
        this.request = arg0;  
    }  
}  
public class DecoupleAction implements ServletRequestAware {  
    private HttpServletRequest request;  
    public void setServletRequest(HttpServletRequest arg0) {  
        this.request = arg0;  
    }  
}  
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

离水的鱼儿

一分也是爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值