我正在使用Spring框架版本3.0.2以及Hibernate (NetBeans 6.9.1)的web应用程序。后来我才知道,有一个bug会导致上传多个文件出现问题,就像我之前的一个问题一样。
我已经完成了获取解决方案的努力,但没有成功。因此,我将Spring版本升级到3.2.0。
在较早的版本(3.0.2)中,AJAX在Jackson 1.9.8(其下载页面)中工作正常,但在较晚的版本(3.2.0)中,一切都工作正常,但AJAX调用在JavaScript代码中到处发出错误警报。
有一个场景,当在国家选择框中选择一个国家时,相应的状态列表将与DAO一起从Spring控制器检索。在Spring控制器中与URL映射的方法如下:
@RequestMapping(value="ajax/GetStateList", method=RequestMethod.GET)
public @ResponseBody List<Object[]> getStateSelectBox(HttpServletRequest request)
{
return cityService.getStateSelectBox(request.getParameter("countryId"));
}
在国家选择框中选择国家时调用此方法。getStateSelectBox()
方法在DAO类中定义如下:
@Service
@Transactional(readOnly = true, propagation=Propagation.REQUIRES_NEW)
public final class CityDAO implements CityService
{
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
@SuppressWarnings("unchecked")
public List<Object[]> getStateSelectBox(String id)
{
List<Object[]> list = sessionFactory.getCurrentSession()
.createQuery("select s.stateId, s.stateName from StateTable s where countryId.countryId=:id order by s.stateId")
.setParameter("id", Long.parseLong(id)).list();
for(Object[]o:list)
{
System.out.println(o[0]+" : "+o[1]);
}
return list;
}
}
foreach
循环只是为了演示,它显示了与AJAX请求提供的countryId
相对应的所有状态及其id,但List
不返回给JSP。
用于发送此AJAX请求的JavaScript代码会发出错误警报。似乎JSON映射存在一些问题。在Spring框架的早期版本(3.0.2)中也是如此。我不确定为什么这会导致更高版本的Spring(3.2.0)出现问题。有什么与Spring版本3.2.0,我可能错过了?
如果需要查看JavaScript代码,完整的JavaScript代码如下所示:
function getStates(countryId)
{
if(countryId==""||countryId==null||countryId==undefined||isNaN(countryId))
{
var str="<select id='cmbStates' name='cmbStates' onchange='errorMessage(this.value);' class='validate[required] text-input'><option value=''>Select</option></select>";
$('#stateList').html(str);
alert("Please select an appropriate option.");
return;
}
var div=document.createElement("div");
div.id="temp";
document.body.appendChild(div);
$.ajax({
datatype:"json",
type: "GET",
contentType: "application/json",
url: "/wagafashion/ajax/GetStateList.htm",
data: "countryId=" + countryId+"&t="+new Date().getTime(),
success: function(response)
{
if(typeof response==='object'&&response instanceof Array)
{
var str="<select id='cmbState' name='cmbState' onchange='errorMessage(this.value);' class='validate[required] text-input'><option value=''>Select</option>";
var l=response.length;
for(var i=0;i<l;i++)
{
str+="<option value='"+response[i][0]+"'>"+$('#temp').text(response[i][1]).html()+"</option>";
}
str+="</select>";
$('#stateList').html(str); // select box is written to #stateList div
$('#temp').remove();
}
},
error: function(e)
{
alert('Error: ' + e);
}
});
}
可以肯定的是,Jackson库在类路径上,我没有在服务器端得到任何错误或异常。AJAX请求成功,它通过Spring转到DAO,并且从数据库中检索到类型为List<Object[]>
的列表,但它不是JSON对JSP的响应(可以/应该映射到JavaScript数组)。据推测,JSON映射似乎缺少了一些东西,而在早期版本的Spring中却不是这样。
编辑:
我尝试在两个框架中解析List<Object[]>
, 3.0.2和3.2.0,如
List<Object[]> list = cityService.getStateSelectBox(request.getParameter("countryId"));
ObjectMapper objectMapper=new ObjectMapper();
try
{
objectMapper.writeValue(new File("E:/Project/SpringHibernet/wagafashionLatest/temp.json"), list);
}
catch (IOException ex){}
文件temp.json
包含以下字符串:
[[21,"Gujarat"],[22,"Maharashtra"],[23,"Kerala"],[24,"New Delhi"]]
在两种情况下(使用两种框架)。因此,在这两种情况下,JSON响应应该是相同的。
temp.json
文件也可以按如下方式反序列化。
try
{
ObjectMapper mapper=new ObjectMapper();
List<Object[]> list = mapper.readValue(new File("E:/Project/SpringHibernet/wagafashionLatest/temp.json"), new TypeReference<List<Object[]>>() {});
for(Object[]o:list)
{
System.out.println(o[0]+" : "+o[1]);
}
}
catch (IOException ex)
{
}
它工作得很好,foreach
循环遍历List<Object[]>
类型的List
。因此,问题可能是由Spring框架本身引起的。我不确定还需要什么。为什么杰克逊没有把它画出来?
我在Spring论坛上有同样的帖子。从对问题的回答中得到的解决方案最终对我有效,需要按如下方式配置dispatcher-servlet.xml
文件。
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="false" />
<property name="ignoreAcceptHeader" value="false" />
<property name="mediaTypes" >
<value>
atom=application/atom+xml
html=text/html
json=application/json
*=*/*
</value>
</property>
</bean>
这使得JSON可以与Jackson 1.9.8和Spring 3.2.0一起工作。这归功于对该问题的所有回复。
我的整个dispatcher-servlet.xml
文件现在看起来如下所示。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="controller" />
<context:component-scan base-package="validatorbeans" />
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="false" />
<property name="ignoreAcceptHeader" value="false" />
<property name="mediaTypes" >
<value>
atom=application/atom+xml
html=text/html
json=application/json
*=*/*
</value>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index.htm">indexController</prop>
</props>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<bean name="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />
</beans>
我使用的是Spring 3.1.3,我发现Jackson映射试图在响应中创建根对象。这是杰克逊地图绘制仪。我没试过用老的杰克逊地图机。如果你也升级了Jackson,你可能会看到同样的问题。
在过去,对象数组会像
这样被映射[{name:'name1',id:4},{name:'name2',id:6}]
现在我发现他们为对象提供了一个自动生成的对象名称,因此返回的是类似
的内容{ objectArray: [{name:'name1',id:4},{name:'name2',id:6}]}
所以你需要引用response.objectArray[0]
而不是直接引用response[0]
在任何情况下,JSON响应的格式都可能有所改变。您应该查看新的响应,看看需要在javascript中进行哪些更改才能使其映射到新的结构。