应用Struts2.1.6须注意的几点(转载)

来源:互联网 发布:mac sai 编辑:程序博客网 时间:2024/06/15 00:54

 

*注:在学习Struts2.0的过程中,我所看得视频中用的Struts2.0.x版本,而我所用的是最新版Struts2.1.6。由于版本的不同,视频里行得通的代码在我的电脑出现错误,故特地上网搜索找到了原因。

看完《Sturts2权威指南》的前三章,也看了一些Sturts2的文章。等到自己写个登录验证Demo时候却总是有想不到的问题,登录了一个钟头也没有登录成功,相当郁闷,就是按照书上还有当的那些资料上做的,但是为什么就不成功呢?后来想到肯定是版本问题。因为那些资料的版本都太低,我用的版本是Struts2.1.6,再有Jar包导入有问题,不知道具体导哪些,有时候导多了,就出问题,因为少配置文件。但是从官方列子中导入那些jar包还是有问题。上班时候在网上撒网狂搜,终于找到点解决办法,下班后重新导入jar包问题果然解决了,下面我就把我这个登陆验证遇到的问题总结下来,希望对大家有帮助,也让大家少走我那样的弯路。觉得挺简单,但是处理起来却不是那么容易,感觉和实际往往相差太大距离。废话不说了,下面我就把该注意的地方写下来:

首先是Jar包问题,Struts2.1.6的jar包和Struts2.0版本的有区别,如果你和我一样用的是Struts2.1.6的话,导入以下6个jar包:
    struts2-core-2.1.6.jar
freemarker-2.3.13.jar
commons-logging-1.0.4.jar
ognl-2.6.11.jar
xwork-2.1.2.jar
commons-fileupload-1.2.1.jar
Struts 2.1.6的最小jar包配置比Struts2.0.14多了一个commons-fileupload-1.2.1.jar。
如果要使用Struts2的注释功能,在Struts2.0.14中只要引用了struts2-core-2.1.6.jar文件即可,而在 struts2.1.6中还需要引用struts2-convention-plugin-2.1.6.jar文件,而且注释类的包也变了(又增加了一些新的注释类),Struts2.0.14中的注释类在org.apache.struts2.config包中,而struts2.1.6的注释类在 org.apache.struts2.convention.annotation包中。除此之外,有些注释的属性名也变了,如Result注释在 struts2.0.14中有一个value属性,表示一个要转入的URL,而在Struts2.1.6的Result注释中使用location属性代替了value属性(不再有value属性了),但它们的使用方法相同。

接下来配置WEB.XML文件
  这是《Struts2权威指南》上和网上大多数人说的配法
<filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.Struts2.dispatcher.FilterDispatcher      
</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>
但是在Struts2.1.6中 最好将org.apache.Struts2.dispatcher.FilterDispatcher改为
   org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
也就是
<filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
        </filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>

接下来就是Struts.xml文件,此文件应该放在classes目录下,也就是工程的src目录下,和struts1不同不是和web.xml一样放在WEB-INF目录下。
<action name="login" class="lee.LoginAction">
            <result name="success">/success.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
action中的name等同于Struts1 action中的 path 但是和Struts1不同的是 name前不加 “/”

接下来是配置动态方法调用,所谓动态方法调用指的是一个Action中有多个方法,系统根据表单元素给定的action来访问不同的方法,而不用写多个Action。和Struts1继承DispartureAction一样可以在一个类中写多个Action。但是Struts2中不是在Struts.xml配置中添加Parameter参数而是下面这样
<package name="Struts2Demo" extends="struts-default">
        <action name="loginAction" class="lee.LoginAction">
            <result name="success">/success.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
        <action name="addUserAction" class="lee.LoginAction"
method="addUser">
            <result name="success">/success.jsp</result>
        </action>
        <action name="deleteUserAction" class="lee.LoginAction"
method="deleteUser">
            <result name="success">/success.jsp</result>
        </action>
</package>

下面为一个相对应的Action 类
package lee;

public class LoginAction {
private String userName;

private String passWord;

public String getPassWord() {
return passWord;
}

public void setPassWord(String passWord) {
this.passWord = passWord;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

/**
* 默认登录方法
*/
public String execute() throws Exception {
System.out.println("this is login Action");
if (getUserName().equals("xueying") &&
getPassWord().equals("xueying")) {
return "success";
} else {
return "error";
}
}
    /**
     * Add user
     * @return
     * @throws Exception
     */
    public String addUser() throws Exception{
     System.out.print("this is add Action");
      return "success";
    }
    /**
     * delete User
     * @return
     * @throws Exception
     */
    public String deleteUser() throws Exception{
     System.out.print("this is delete Action");
     return "success";
    }
}
为同一个类配置多个Action 在 action中指定method参数 method对应类中相应方法的名称。name为页面调用时的名称。不指定method就会调用默认的execute()方法
注意:要使用动态方法调用,必须设置Struts2允许动态方法调用,通过设置struts.enable.DynamicMethodInvocation常量来完成,该常量属性的默认值是true。
Index.jsp如下
<%@ taglib uri="/struts-tags" prefix="s" %>  导入标签文件

<body>
  <s:form method="post" action="loginAction">
    <s:textfield name="userName"></s:textfield>
    <s:password name="passWord"></s:password>
    <s:submit></s:submit>
  </s:form>
  <a href="addUserAction.action" >add user1</a><br/>
  <a href="/Struts2Demo/addUserAction.action" >add user2</a><br/>
  <a href="/Struts2Demo/login!addUserAction.action" >add user3</a>
  </body>
调用addUser方法 可以是上面三种链接方式中的任意一种。
仔细看上面struts.xml中三个action的定义,可以发现他们除了name和method属性不同以外,其余的都一样,这种定义相当的冗余,为了解决这种类型的问题,Struts2提供了通配符定义方式。
  将Struts.xml中的三个action合并为一个,配置如下
   <action name="*Action" class="lee.LoginAction" method="{1}">
          <result name="success">/success.jsp</result>
          <result name="error">/error.jsp</result>
  </action>
如果是这样配置就不能用第三种连接方式调用了,链接也就不能写成下面这样
<a href="/Struts2Demo/login!addUserAction.action" >add user3</a>
同样也就掉不到默认的execute方法,要想调用execute方法,只能将execute看做一个自己定义的方法,而非默认的重写方法,也就是在页面executeAction这样调用。表单提交改成
<s:form method="post" action="executeAction.action">
但是这样在访问页面时候会在控制台打印两条警告
2009-8-30 13:31:44 com.opensymphony.xwork2.util.logging.commons.CommonsLogger warn
警告: No configuration found for the specified action: 'executeAction.action' in namespace: ''. Form action defaulting to 'action' attribute's literal value.
2009-8-30 13:31:44 com.opensymphony.xwork2.util.logging.commons.CommonsLogger warn
警告: No configuration found for the specified action: 'executeAction.action' in namespace: ''. Form action defaulting to 'action' attribute's literal value.
但是如果不用Struts2标签,直接改为 HTML form表单,就不会出现那两条警告 
<form method="post" action="executeAction.action">
但是又有问题出来了,如果在定义一个类,然后在struts.xml文件中也是类似配置,如下:
<action name="*Action" class="lee.LoginAction" method="{1}">
            <result name="success">/success.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
        <action name="*Action" class="lee.UserAction" method="{1}">
            <result name="success">/success.jsp</result>
            <result name="error">/error.jsp</result>
</action>
页面调用时候就会出现问题
<a href="addNameAction.action" >add name</a><br/>
<a href="deleteUserAction.action" >delete user1</a><br/>
都会到第二个action(最后一个配置的action)中去找相应的配置。如果找不到就会抛出500错误。为解决这一问题,就得用到类通配符,就是在class属性和method属性中同时使用表达式。这时的Struts.xml文件如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <package name="Struts2Demo" extends="struts-default">
        <action name="*_*" class="lee.{1}Action" method="{2}">
            <result name="success">/success.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
    </package>
</struts>
Index.jsp页面如下:
<body>
  <s:form method="post" action="Login_checkUser.action">
       昵称:<s:textfield name="userName"></s:textfield><br/>
       密码:<s:password name="passWord"></s:password><br/>
      <s:submit value="提交"></s:submit>
  </s:form>
  <a href="Login_deleteUser.action" >delete user1</a><br/>
  <a href="User_addName.action" >add name</a><br/>
  </body>
在调用时候就像这样:Login_deleteUser.action _前面为类名,后面为方法名,当请求此地址时,就会调用 lee.LoginAction处理类中的deleteUser方法来处理请求。当然具体情况还得根据Struts.xml配置文件来定!Struts2除了允许在name、class、method中使用表达式外,在<result/>元素中也可以使用表达式,如下:
<action name="*Acion" class="lee.LoginAction" method="login">
            <result name="success">/{1}.jsp</result>
       </action>
当请求为LoginAction.do时,将调用lee.LoginAction处理类中的Login方法处理用户的请求,当返回为success时,显示/Login.jsp页面。

再有就是Struts标签问题
如果Web应用使用了Servlet 2.3以前的规范,因为Web应用不会自动加载Struts 2框架的标签文件,因此必须在web.xml文件中配置加载Struts 2标签库。
配置加载Struts 2标签库的配置片段如下:
   <taglib>
<!-- 配置Struts 2标签库的URI -->
<taglib-uri>/s</taglib-uri>
<!-- 指定Struts 2标签库定义文件的位置 -->
<taglib-location>/WEB-INF/struts-tags.tld</taglib-location>
  </taglib>
在上面配置片段中,指定了Struts 2标签库配置文件物理位置:/WEB-INF/struts- tags.tld,因此我们必须手动复制Struts 2的标签库定义文件,将该文件放置在Web应用的WEB-INF路径下。
如果Web应用使用Servlet 2.4以上的规范,则无需在web.xml文件中配置标签库定义,因为Servlet 2.4规范会自动加载标签库定义文件。
Struts 2的标签库定义文件包含在struts2-core-2.0.6.jar文件里,在struts2-core-2.0.6.jar文件的META-INF 路径下,包含了一个struts-tag.tld文件,这个文件就是Struts 2的标签库定义文件,Servlet 2.4规范会自动加载该标签库文件。
对于Servlet 2.4以上的规范,Web应用自动加载该标签库定义文件。加载struts-tag.tld标签库定义文件时,该文件的开始部分包含如下代码片段:
<taglib>
   <!-- 定义标签库的版本 --> 
   <tlib-version>2.2.3</tlib-version>
   <!-- 定义标签库所需的JSP版 -->
   <jsp-version>1.2</jsp-version>
   <short-name>s</short-name>  
   <!-- 定义Struts 2标签库的URI -->
   <uri>/struts-tags</uri>
   、、、、
   </taglib>
因为该文件中已经定义了该标签库的URI:struts-tags,这就避免了在web.xml文件中重新定义Struts 2标签库文件的URI。

最后就是Action访问Servlet API问题
Struts2中提供了一个ActionContext类(当前Action的上下文对象),通过这个类可以访问Servlet API。下面是该类中提供的几个常用方法:
1.public static ActionContext getContext() :获得当前Action的ActionContext实例。
2.public Object get(Object key) :此方法类似于调用HttpServletRequest的getAttribute(String name)方法。
3.public void put(Object key, Object value) :此方法类似于调用HttpServletRequest 的
setAttribute(String name, Object o)。
4. public Map getParameters() :获取所有的请求参数。类似于调用HttpServletRequest对象
的getParameterMap() 方法。
5. public Map getSession() :返回一个Map对象,该Map对象模拟了HttpSession实例。
6. public void setSession(Map session) : 直接传入一个Map实例,将该Map实例里的
key-value对转换成session的属性名-属性值对。
7. public Map getApplication() :返回一个Map对象,该对象模拟了该应用的ServletContext
实例。
8. public void setApplication(Map application) :直接传入一个Map实例,将该Map实例里
的key-value对转换成application的属性名-属性值对。
还有其它的,想具体了解就看API吧,我就不一一列举了。
例如登录后将登陆名放到作用域中然后在页面中显示出来
public String checkUser() throws Exception{
// 获得当前Action的ActionContext实例
    ActionContext context = ActionContext.getContext();
    //放到session中
    context.getSession().put("logname",getUserName() );
//放到request作用域中
    context.put("loginname",getUserName() );
    return "success";
}

原创粉丝点击