Java 通过Hessian与Spring远程处理一起传输时,BigDecimal值始终为零
当我调用通过Spring的Hessian函数返回BigDecimal值的远程方法时,它总是返回零。 直接调用该方法或使用普通Hessian servlet(非Spring)正常工作 如何解决这个问题 服务器端(Tomcat7) web.xml:Java 通过Hessian与Spring远程处理一起传输时,BigDecimal值始终为零,java,spring,hessian,spring-remoting,Java,Spring,Hessian,Spring Remoting,当我调用通过Spring的Hessian函数返回BigDecimal值的远程方法时,它总是返回零。 直接调用该方法或使用普通Hessian servlet(非Spring)正常工作 如何解决这个问题 服务器端(Tomcat7) web.xml: <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://ja
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<servlet>
<servlet-name>remoting</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>remoting</servlet-name>
<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
</web-app>
客户端
Spring配置-applicationContextHessian.xml:
<beans>
<bean id="posloviLogic" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
<property name="serviceUrl" value="http://localhost:8080/SpringWebTest/remoting/lcspi/lc302/poslovi" />
<property name="serviceInterface" value="hr.spi.logic.lcspi.lc302.PosloviLogicInterface" />
</bean>
</beans>
编辑:
使用的库是Spring 3.2和Hessian 4.0.7您可以使用HessianServlet.setSerializerFactory()来设置自己的SerializerFactory,并返回com.caucho.Hessian.io.BigDecimalDeserializer作为BigDecimal的反序列化程序 我们这样修补了它,效果很好。不知道为什么它没有以这种方式实现
参见我们这样解决了这个问题: 像@keuleJ一样,我们构建了自己的SerializerFactory(见下文),但我们不返回com.caucho.hessian.io.BigDecimalDeserializer,因为它不检查null
public class BigDecimalSerializerFactory extends AbstractSerializerFactory {
private BigDecimalSerializer bigDecimalSerializer = new BigDecimalSerializer();
private BigDecimalDeserializer bigDecimalDeserializer = new BigDecimalDeserializer();
@Override
public Serializer getSerializer(Class cl) throws HessianProtocolException {
if (BigDecimal.class.isAssignableFrom(cl)) {
return bigDecimalSerializer;
}
return null;
}
@Override
public Deserializer getDeserializer(Class cl) throws HessianProtocolException {
if (BigDecimal.class.isAssignableFrom(cl)) {
return bigDecimalDeserializer;
}
return null;
}
}
然后我们定义了自己的反序列化程序。它与com.couchos的实现不同,它验证值是否不为null。有必要扩展AbstractStringValueDeserialize
}
序列化程序仅将BigDecimal转换为字符串表示形式:
公共类BigDecimalSerializer扩展了AbstractSerializer{
@Override
public void writeObject(Object obj, AbstractHessianOutput out) throws IOException {
if (obj == null)
out.writeNull();
else {
Class cl = obj.getClass();
if (out.addRef(obj))
return;
int ref = out.writeObjectBegin(cl.getName());
BigDecimal bi = (BigDecimal) obj;
if (ref < -1) {
out.writeString("value");
out.writeString(bi.toString());
out.writeMapEnd();
} else {
if (ref == -1) {
out.writeInt(1);
out.writeString("value");
out.writeObjectBegin(cl.getName());
}
out.writeString(bi.toString());
}
}
}
您必须同时在服务器端和客户端执行此操作
提示!
在本例中,我们遇到了BigDecimal和DateTime的组合问题,因此stacktraces和调试视图很奇怪。
因此,如果您使用“非标准”对象,请检查它们的序列化!这似乎是一个已知的错误。有关详细信息和可能的解决方法,请参阅。我们也遇到了同样的问题,发现maven central上分发的hessian jar缺少一些关键配置文件。如果您直接从jar下载jar,将包括:
- META-INF/hessian/序列化程序
- META-INF/hessian/反序列化程序
src/main/resources
中解决了这个问题
好处:这个解决方案还纠正了我们在java.util.Locale
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContextHessian.xml");
try {
PosloviLogicInterface posloviLogic = (PosloviLogicInterface) context.getBean("posloviLogic");
BigDecimal bd = posloviLogic.test();
System.out.println(bd); // This returns 0.00
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
public class BigDecimalSerializerFactory extends AbstractSerializerFactory {
private BigDecimalSerializer bigDecimalSerializer = new BigDecimalSerializer();
private BigDecimalDeserializer bigDecimalDeserializer = new BigDecimalDeserializer();
@Override
public Serializer getSerializer(Class cl) throws HessianProtocolException {
if (BigDecimal.class.isAssignableFrom(cl)) {
return bigDecimalSerializer;
}
return null;
}
@Override
public Deserializer getDeserializer(Class cl) throws HessianProtocolException {
if (BigDecimal.class.isAssignableFrom(cl)) {
return bigDecimalDeserializer;
}
return null;
}
public class BigDecimalDeserializer extends AbstractStringValueDeserializer {
@Override
public Class getType() {
return BigDecimal.class;
}
@Override
protected Object create(String value) {
if (null != value) {
return new BigDecimal(value);
} else {
return null;
}
}
@Override
public void writeObject(Object obj, AbstractHessianOutput out) throws IOException {
if (obj == null)
out.writeNull();
else {
Class cl = obj.getClass();
if (out.addRef(obj))
return;
int ref = out.writeObjectBegin(cl.getName());
BigDecimal bi = (BigDecimal) obj;
if (ref < -1) {
out.writeString("value");
out.writeString(bi.toString());
out.writeMapEnd();
} else {
if (ref == -1) {
out.writeInt(1);
out.writeString("value");
out.writeObjectBegin(cl.getName());
}
out.writeString(bi.toString());
}
}
}
SerializerFactory serializerFactory = newSerializerFactory();
serializerFactory.addFactory(new BigDecimalSerializerFactory());