学习struts2建bbs总结七:extends ActionSupport带来的ClassNotFoundException异常

来源:互联网 发布:简单贪吃蛇c语言代码 编辑:程序博客网 时间:2024/05/22 01:57

这个问题可说是这次学习遇到的最怪异的问题了,一直在网上询问了一周多直到现在均未得到答案,大概和高手缘分不深。哈哈。

这时我感觉写总结对于学习是很有帮助的,自从写写这些学习总结,回顾的时候,我竟慢慢的发现了很多原来未曾发现的问题,并且都渐渐解决了。例如之前的prototype模式,jquery,等等。趁着有时间,就及时的写出来,一则和遇到类似问题的朋友共享,二则避免自己以后犯同样错误。

事情是这样的:我在编写程序的过程中,一些action我是这样写的:如

public class PostAction implements Action......

也就是说,我实现的是action接口,直到bbs项目结束,那时刚把那个分页的死机问题解决,我测试了整个bbs运行,是可以正常运行的。只是我无意间看到一些说起baseAction的文章,我自己之前的总结也写了,所以我新建了baseAction类,如下:

import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.apache.struts2.interceptor.ServletRequestAware;import org.apache.struts2.interceptor.SessionAware;import com.opensymphony.xwork2.ActionSupport;public class BaseAction extends ActionSupport implements ServletRequestAware,SessionAware {protected HttpServletRequest request;protected Map<String, Object> session;public void setServletRequest(HttpServletRequest request) {this.request = request;}public void setSession(Map<String, Object> session) {this.session = session;}}

这个类的目的就是生成session以及request,好处就是避免每个action甚至每个方法都要写上这句

Map session=ActionContext.getContext().getSession();

所以,我就把程序中的action,统统修改为extends BaseAction,但自从修改了这句后,程序遇到postAction发帖操作就报异常,我改为extends ActionSupport也是同样报错,如下:

post.jsp主要代码:

<FORM name="postForm" onSubmit="return check()" action="post.action?page=1" method="POST">         <INPUT id="a2" type="hidden" name="boardName" value="${fn:substring(bName,0,20)}"/><INPUT id="a3" type="hidden" name="boardId" value=<%= session.getAttribute("boardId")%>/><DIV class="t"><TABLE cellSpacing="0" cellPadding="0" align="center">    <TR>    <TD class="h" colSpan="3"><B>发表帖子</B></TD>    </TR>    <TR class="tr3">    <TH width="20%"><B>标题</B></TH>    <TH><INPUT class="input" style="PADDING-LEFT: 2px; FONT: 14px Tahoma" tabIndex="1" size="60" name="title"></TH>    </TR>    <TR class="tr3">    <TH vAlign=top>      <DIV><B>内容</B></DIV>    </TH>    <TH colSpan=2>        <DIV>        <span><textarea style="WIDTH: 500px;" name="detail" rows="20" cols="90" tabIndex="2" ></textarea></span>    </DIV>      (不能大于:<FONT color="blue">1000</FONT>字)    </TH></TR></TABLE></DIV><DIV style="MARGIN: 15px 0px; TEXT-ALIGN: center"><INPUT class="btn" tabIndex="3" type="submit" value="提 交"> <INPUT class="btn" tabIndex="4" type="reset"  value="重 置"></DIV><s:token/></FORM>


异常详细:

java.lang.RuntimeException: Invalid action class configuration that references an unknown class named [postAction]    org.apache.struts2.convention.ConventionsServiceImpl.determineResultPath(ConventionsServiceImpl.java:100)    org.apache.struts2.convention.ConventionUnknownHandler.determinePath(ConventionUnknownHandler.java:385)    org.apache.struts2.convention.ConventionUnknownHandler.handleUnknownResult(ConventionUnknownHandler.java:274)    com.opensymphony.xwork2.DefaultUnknownHandlerManager.handleUnknownResult(DefaultUnknownHandlerManager.java:87)    com.opensymphony.xwork2.DefaultActionInvocation.createResult(DefaultActionInvocation.java:226)    com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:367)。。。。。。root causejava.lang.ClassNotFoundException: postAction    org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1680)    org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)    org.apache.struts2.util.ClassLoaderUtils.loadClass(ClassLoaderUtils.java:111)    org.apache.struts2.convention.ConventionsServiceImpl.determineResultPath(ConventionsServiceImpl.java:98)    org.apache.struts2.convention.ConventionUnknownHandler.determinePath(ConventionUnknownHandler.java:385)    org.apache.struts2.convention.ConventionUnknownHandler.handleUnknownResult(ConventionUnknownHandler.java:274)    com.opensymphony.xwork2.DefaultUnknownHandlerManager.handleUnknownResult(DefaultUnknownHandlerManager.java:87)    com.opensymphony.xwork2.DefaultActionInvocation.createResult(DefaultActionInvocation.java:226)    com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.ja

提示找不到类,一般遇到这个异常,都会认为是spring的配置类名写错了或者路径写错了,在网上很多人也说应该是这样的原因。但在这里显示不可能是这种原因。

因为当我实现action接口,即implements Action的时候可以正常运行,则说明肯定不是配置文件的问题,要不然implements Action的时候就要报错的。事实上是implements Action的时候正常运行。

这个问题困扰我很久,我在网上查了许许多多有关Action以及ActionSupport的区别,几乎异口同声只是说,action只是一个接口,而actionSupport实现了Action接口,并且还提供了许多方法比如效验等,都建议直接继承ActionSupport。似乎ActionSupport可以无条件的取代Action接口。我看到这些文章,自然是解决不了我遇到的问题。

后来,我先不管什么异常,既然继承了ActionSupport,那 配置一下PostAction-post-validation.xml吧,因为post.jsp只有个标题和正文变量,xml文件如下:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd"> <validators>        <field name="title">            <field-validator type="requiredstring">            <param name="trim">true</param>            <message>不能为空!</message>        </field-validator>        <field-validator type="stringlength">            <param name="trim">true</param>           <param name="maxLength">20</param><param name="minLength">4</param><message>要在4--20位!</message>        </field-validator>    </field>            <field name="detail">       <field-validator type="requiredstring">            <param name="trim">true</param>            <message>不能为空!</message>        </field-validator>        <field-validator type="stringlength">            <param name="trim">true</param>           <param name="maxLength">1000</param><param name="minLength">4</param><message>要在4--1000!</message>        </field-validator>    </field>          </validators>

然后我在strust.xml文件中,定义 了<result name="input">/error.jsp</result>,其中error.jsp加上:<s:fielderror/><s:actionerror/>

因为ActionSupport实现了ValidationAware接口,可以获得或设置字段错误信息、动作错误信息以及动作消息。其中,hasActionErrors方法判断是否存在动作层的错误,getFieldErrors获得字段错误信息(一个Map 对象)。

我的猜测(注意是猜测,我并没有深入研究):如果某个action继承了ActionSupport,则ActionSupport里的方法自然会对相应的jsp文件进行一些字段检测什么的,如果jsp有问题,则上面的hasActionErrors或getFieldErrors则会返回true,这时根据struts.xml返回“input”定义的视图页面。

例如,我上面在post.jsp中点击发帖按钮,程序便应该执行postAction,但执行之前会经过拦截器,以及ActionSupport中的校验(我在这里的测试结果显示,当点击发帖按钮,执行顺序是:过滤器---->拦截器--->ActionSupport的效验,其中过滤器web.xml的位置和url-pattern的路径设置有讲究,如果过滤器放在struts之后,结果大不一样,但拦截器-->ActionSupport校验这个顺序没变),如果定义了效验xml文件以及“input”对应的jsp文件,如这时我在实际测试过程发现页面调转到了error.jsp。如下:

当时我看到这个界面真是太兴奋太高兴了。终于知道程序的问题在哪里。我于是找到post.jsp文件,找到有关boardId字段的信息,发现下面这句

<INPUT id="a3" type="hidden" name="boardId" value=<%= session.getAttribute("boardId")%>/>属性值写错了,action中“session.put("BOARD_ID", boardId);

所以这句代码修改为:

<INPUT id="a3" type="hidden" name="boardId" value=<%= session.getAttribute("BOARD_ID")%>/>


再次运行,终于一切正常了!!看来,<s:fielderror/><s:actionerror/>用处真大呀。由此看出,继承ActionSupport还有个好处,就是它会帮你坚持jsp中每个字段属性,是否有效,如上面的截图,当遇到无效字段时,就直接转入input,不再执行action,从而报出找不到类的异常。而实现Action接口,则不会对jsp文件进行字段检测,所以虽然我的jsp有错误的时候,也一样可以进入action执行。

其实对jsp的相关知识自己也需要加强,例如这次出现的许多多此一举的事情。其中我需要在jsp中截取一个字符串,需要字符串的前20个字符就好,为了这个,我居然用了一段js代码截取,如下:

function SetString(str,len) {  var strlen = 0;   var s = "";  for(var i = 0;i < str.length;i++)  {   if(str.charCodeAt(i) > 128){    strlen += 2;   }else{     strlen++;   }   s += str.charAt(i);   if(strlen >= len){     return s ;   }  } return s; } 

<script> document.write(SetString("<%=session.getAttribute("BOARD_NAME").toString().trim()%>",20));</script> 

写了这2段代码来实现,可是后来学习了jsp标签,真笑话自己啊。上面的代码在jsp文件其实只需要2句即可,如下:

<c:set var="bName" value="${session.BOARD_NAME}"/>${fn:substring(bName,0,20)} 
当然需要引用

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>

不过这里我还得提出一个问题,如果上面我用struts2的标签函数substring截取字符串,遇到中文的时候我这里是无法截取的,当时显示的页面上,遇到中文字符串就是空白,英文字符串就可以正常截取。不知道是出了什么问题,这些留待以后研究了。


到这里,这次的总结算是写完了,感觉写学习总结学习到的似乎不比写程序学习到的少。希望各位朋友也多写总结,利人利己,呵呵。


原创粉丝点击