您的位置:首页 > 编程语言 > Java开发

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

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

这时我感觉写总结对于学习是很有帮助的,自从写写这些学习总结,回顾的时候,我竟慢慢的发现了很多原来未曾发现的问题,并且都渐渐解决了。例如之前的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 cause

java.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之后,结果大不一样,但拦截器-->[b]ActionSupport校验这个顺序没变[/b]),如果定义了效验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截取字符串,遇到中文的时候我这里是无法截取的,当时显示的页面上,遇到中文字符串就是空白,英文字符串就可以正常截取。不知道是出了什么问题,这些留待以后研究了。

到这里,这次的总结算是写完了,感觉写学习总结学习到的似乎不比写程序学习到的少。希望各位朋友也多写总结,利人利己,呵呵。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐