gpt4 book ai didi

java - Spring ClassCastException 与通用表单 Bean 类

转载 作者:行者123 更新时间:2023-12-01 17:34:06 24 4
gpt4 key购买 nike

我尝试使用泛型类作为 Spring 表单支持 bean,但当 Spring 框架尝试将对象转换为实际类型时,最终会出现 ClassCastException。

提交表单时,尝试调用 SrvRecord 对象上的方法时会发生以下错误(第 105 行,用注释标记):

java.lang.ClassCastException: java.lang.Object cannot be cast to com.[...].portal.entity.SrvRecord
at com.[...].portal.controller.SrvController.add(SrvController.java:105)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:585)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:390)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:440)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

形成 Bean:

public class RecordBean<T>
{

private T original;
private T modified;

public RecordBean()
{
super();
}

public RecordBean(T original)
{
this.original = original;
this.modified = original;
}

public T getOriginal()
{
return original;
}

public void setOriginal(T original)
{
this.original = original;
}

public T getModified()
{
return modified;
}

public void setModified(T modified)
{
this.modified = modified;
}

}

Controller 方法:

@RequestMapping(value = "new", method = RequestMethod.GET)
public String add(Model model)
{
SrvRecord srvRecord = getSrvRecord();

RecordBean<SrvRecord> record = new RecordBean<SrvRecord>(srvRecord);
model.addAttribute("record", record);

return "generic/new";
}

@RequestMapping(value = "new", method = RequestMethod.POST)
public String add(Model model, @ModelAttribute("record") RecordBean<SrvRecord> record)
{
// Call a method on the SrvRecord object
doSomething(record.getModified().getZone().getName()); // line 105
doSomething(record.getOriginal().getZone().getName());

// ...
}

查看:

<c:url value="/edit" var="formUrl" />
<form:form commandName="record" action="${formUrl}">
<form:input type="hidden" path="original.zone" />
<form:input type="hidden" path="original.name" />
<!-- ... -->

<form:input path="modified.zone" /><br />
<form:input path="modified.name" /><br />
<!-- ... -->
</form:form>

任何想法或建议都会很棒。能够使用通用表单 bean 将从基线中消除大量不必要的代码。

仅供引用,使用的Spring版本是3.0.6.RELEASE。

谢谢,美女

最佳答案

您可以在 Spring 上提交错误。问题是 Spring 使用反射来确定参数类型,并且它们忽略了泛型,因此只是实例化一个没有泛型的普通 RecordBean 对象。因此,RecordBean 中的对象只是作为 Object 创建的,无法将其转换为 SrvRecord。唯一的解决方法是不使用泛型。

背景

Spring内部使用MethodParameter类来读取方法参数。有一个方法叫做

public Class<?> getParameterType()

调用:

this.method.getParameterTypes()[this.parameterIndex]

此代码读取没有泛型的参数。他们需要调用它来正确处理它

this.method.getGenericParameterTypes()[this.parameterIndex]

后面的方法

 HandlerMethodInvoker.resolveModelAttribute()

被调用以通过执行

来实例化命令类
 bindObject = BeanUtils.instantiateClass(paramType);

但 paramType 的值为“com.test.RecordBean”,而不是预期的“com.test.RecordBean

关于java - Spring ClassCastException 与通用表单 Bean 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8154104/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com