java NumberFormat不适用于ModelAndView和HandlerInterceptorAdapter
我创建了一个自定义HandlerInterceptorAdapter
来覆盖postHandle
方法:
public class AcmeInterceptor extends HandlerInterceptorAdapter {
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
AcmeController controller = (AcmeController) handler;
controller.finalize(modelAndView);
}
}
在AcmeModel中,我定义了一个用NumberFormat注释的字段:
public class AcmeModel {
private BigDecimal cost = BigDecimal.valueOf(67890.6789);
@NumberFormat(style = Style.CURRENCY)
public BigDecimal getCost() {
return cost;
}
}
在极致。jsp我使用<spring:bind>
输出格式化的值:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<spring:bind path="acmeModel.cost">
Cost: <c:out value="${status.value}" />
</spring:bind>
现在,我首先尝试这样的控制器:
@Controller
public class AcmeController {
@RequestMapping("/")
public ModelAndView index() {
ModelAndView modelAndView = new ModelAndView("WEB-INF/views/acme.jsp");
modelAndView.addObject(new AcmeModel());
return modelAndView;
}
public void finalize(ModelAndView modelAndView) {
}
}
这是我得到的结果:
Cost: $67,890.68
这是令人费解的部分。如果我将对addObject
的调用移动到finalize
的主体中:
@Controller
public class AcmeController {
@RequestMapping("/")
public ModelAndView index() {
ModelAndView modelAndView = new ModelAndView("WEB-INF/views/acme.jsp");
//modelAndView.addObject(new AcmeModel());
return modelAndView;
}
public void finalize(ModelAndView modelAndView) {
modelAndView.addObject(new AcmeModel());
}
}
然后输出变成:
Cost: 67890.6789
将对象添加到处理程序方法中的ModelAndView
与影响<spring:bind>
的常规控制器方法有什么区别
编辑:下面是servlet的bean定义
<beans ...>
<mvc:annotation-driven />
<context:component-scan base-package="com.example" />
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean id="acmeInterceptor" class="com.example.numberformat.AcmeInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
</beans>
# 1 楼答案
Spring通过BindingResult对象处理格式化。当您在控制器中向模型添加值时,spring会验证这些值,创建BindingResult并将其添加到模型中。这种机制只适用于控制器,不适用于拦截器,可能是有意的,也可能不是,我不确定,但它肯定是这样工作的。如果您希望对拦截器中设置的值进行绑定,则需要自行进行绑定。修改拦截器如下:
正如您所见,这段代码将额外的BindingResult对象添加到模型中。它需要获得转换服务。目前,它是通过从控制器获取数据来完成的。控制器可以使用@InitBinder注释访问它,如下所示
另一种选择是在拦截器中实现preHandle方法,而不是postHandle。PreHandle无法访问模型,但它可以访问请求,因此在PreHandle中,您可以将AcmeModel作为属性添加到Requiest中,然后在控制器中,您可以获取值,将其添加到模型中,然后它将像其他模型属性一样由Spring绑定