gpt4 book ai didi

java - NumberFormat 不适用于 ModelAndView 和 HandlerInterceptorAdapter

转载 作者:行者123 更新时间:2023-11-30 11:49:28 28 4
gpt4 key购买 nike

我创建了一个自定义 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;
}
}

在 acme.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 :

@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> 的普通 Controller 方法?

编辑:这是 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>

最佳答案

Spring 通过 BindingResult 对象处理格式化。当您在 Controller 中向模型添加值时,spring 会验证它们,创建一个 BindingResult 并将其添加到模型中。这种机制只适用于 Controller ,不适用于拦截器,我不确定是有意还是无意,但它确实是这样工作的。如果您想对拦截器中设置的值进行绑定(bind),那么您需要自己进行绑定(bind)。像这样修改你的拦截器:

public class AcmeInterceptor extends HandlerInterceptorAdapter {

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

AcmeController controller = (AcmeController) handler;

AcmeModel acmeModel = controller.getAcmeModel();
String key = "acmeModel";

BeanPropertyBindingResult bpb = new BeanPropertyBindingResult(
acmeModel, key);

bpb.initConversion(controller.getBinder().getConversionService());

modelAndView.addObject(key, acmeModel);
modelAndView.addObject(BindingResult.MODEL_KEY_PREFIX + key, bpb);

}

}

如您所见,这段代码将额外的 BindingResult 对象添加到模型中。它需要获取 ConversionService。现在它是通过从 Controller 获取它来完成的。 Controller 可以像这样使用@InitBinder 注释访问它

public class AcmeController {

private WebDataBinder binder;

@InitBinder
protected void initBinder(WebDataBinder binder) {

this.binder = binder;

}

另一种选择是在拦截器中实现 preHandle 方法而不是 postHandle。 PreHandle不能访问模型,但是它可以访问请求,所以在preHandle中你可以将AcmeModel作为属性添加到reqiest然后在你的 Controller 中你可以获取值,将它添加到模型中,然后它将被绑定(bind)与其他模型属性一样,由 Spring 提供。

关于java - NumberFormat 不适用于 ModelAndView 和 HandlerInterceptorAdapter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8379840/

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