在 jsp 中使用 JSTL <form:select> 标签时视图未正确绑定
View not bound correctly in using JSTL <form:select> tag in jsp
enter code here
我有一个控制器,下面有两个 url 映射到名为 Member 的业务对象的 GET 和 POST。
控制器:
@RequestMapping(value = "/usr/updateMember", method = RequestMethod.GET)
public ModelAndView findForEdit(@RequestParam("id") Integer id) {
ModelAndView modelAndView = new ModelAndView("registration");
try {
List<City> cities = getGenericDao().getAllItems(City.class);
List<Chapter> chapters = getGenericDao().getAllItems(Chapter.class);
modelAndView.getModel().put("cities", cities);
modelAndView.getModel().put("chapters", chapters);
Member member = getGenericDao().getItem(Member.class, id);
modelAndView.getModel().put("edit", true);
modelAndView.getModel().put("loggedinuser", getPrincipal());
modelAndView.getModel().put("roles", userRoleService.findAll());
modelAndView.getModel().put("member", member);
} catch (Exception e) {
System.out.println(e.getMessage());
}
return modelAndView;
}
@RequestMapping(value = "/usr/updateMember", method = RequestMethod.POST)
public String update(@ModelAttribute("member") Member member, BindingResult result, SessionStatus status) {
getGenericDao().update(member);
status.setComplete();
return "redirect:/list.do";
}
我的看法如下:
<form:form method="POST" modelAttribute="member"
class="horizForm">
<div class="row">
<div class="form-group col-md-">
<label class="col-md-3" for="name">Member
Name</label>
<div class="col-md">
<form:input type="text" path="name" id="name"
class="form-control input-sm" />
<div class="has-error">
<form:errors path="name" class="help" />
</div>
</div>
</div>
</div>
...
<div class="row">
<div class="form-group col-md-12">
<label class="col-md-3" for="userRoles">Roles</label>
<div class="col-md">
<form:select path="userRoles" items="${roles}" multiple="true"
itemValue="memberId" itemLabel="role"
class="form-control input-sm" />
<div class="has-error">
<form:errors path="userRoles" class="help" />
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-md-">
<label class="col-md-3 control-labl" for="chapter">Chapter</label>
<div class="col-md-7">
<%-- <form:select path="chapter.id" items="${chapters}" itemValue="id"
itemLabel="name" class="form-control input-sm"> --%>
<%-- <option value="-1">Select a Chapter</option>
<c:forEach var="chp" items="${chapters}">
<option value="${chp.id}">${chp.name}</option>
</c:forEach> --%>
<%-- </form:select> --%>
<form:select path="chapter" class="form-control input-sm">
<!-- <option value="-1">Select a Chapter</option> -->
<c:forEach var="chp" items="${chapters}">
<option value="${chp}">${chp.name}</option>
</c:forEach>
</form:select>
<div class="has-error">
<%-- <form:errors path="chapter.id" class="help-inline" /> --%>
<form:errors path="chapter" class="help-inline" />
</div>
</div>
</div>
</div>
GET 按预期工作,视图中填充了字符串、列表和章节类型对象的预期值。
当我尝试通过 POST 更新成员时,它没有获得绑定到 List 和 Chapter 对象的值,并且 BindingResult 具有以下值。
org.springframework.validation.BeanPropertyBindingResult: 3 errors
Field error in object 'member' on field 'chapter': rejected value [Chapter [chapterId=1, chapterName=SUPER]]; codes [typeMismatch.member.chapter,typeMismatch.chapter,typeMismatch.com.codex.survey.beans.Chapter,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [member.chapter,chapter]; arguments []; default message [chapter]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.codex.survey.beans.Chapter' for property 'chapter'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.codex.survey.beans.Chapter] for property 'chapter': no matching editors or conversion strategy found]
Field error in object 'member' on field 'userRoles': rejected value [2]; codes [typeMismatch.member.userRoles,typeMismatch.userRoles,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [member.userRoles,userRoles]; arguments []; default message [userRoles]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.List' for property 'userRoles'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.codex.survey.beans.UserRole] for property 'userRoles[0]': no matching editors or conversion strategy found]
我无法弄清楚这里的视图出了什么问题,请帮我解决这个问题。
感谢期待。
不同于有状态的、基于组件的框架(例如 JSF)Spring MVC 无法自动将原始 HTTP 参数转换为相应的对象类型。
因此您需要注册一个转换器来处理这个问题,并在 Spring 上下文中注册它。有多种方法可以做到这一点,但一种实现方式如下:
@Component
public class StringToChapterConverter implements Converter<String, Chapter> {
@Autowired
private ChaperService service;
/**
*chapterId is the HTTP post param passed in by the framework
*/
public Chapter convert(String chapterId) {
return service.findChapter(Integer.parseInt(chapterId));
}
}
如何注册取决于您的配置。但是假设 Java 代码配置然后:
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "..." })
public class MvcConfiguration extends WebMvcConfigurerAdapter{
//other configuration
@Override
public void addFormatters(FormatterRegistry formatterRegistry) {
formatterRegistry.addConverter(getChapterConverter());
}
@Bean
public StringToChapterConverter getChapterConverter(){
return new StringToChapterConverter();
}
}
因此,现在有了上述内容,当发出绑定到 Chapter 对象的请求时,框架将查看是否为 Chapter 类型定义了合适的转换器,然后调用相应的 convert(String源),它使您能够 return 来自您的数据库或任何地方的实例。
进一步了解:
enter code here
我有一个控制器,下面有两个 url 映射到名为 Member 的业务对象的 GET 和 POST。
控制器:
@RequestMapping(value = "/usr/updateMember", method = RequestMethod.GET)
public ModelAndView findForEdit(@RequestParam("id") Integer id) {
ModelAndView modelAndView = new ModelAndView("registration");
try {
List<City> cities = getGenericDao().getAllItems(City.class);
List<Chapter> chapters = getGenericDao().getAllItems(Chapter.class);
modelAndView.getModel().put("cities", cities);
modelAndView.getModel().put("chapters", chapters);
Member member = getGenericDao().getItem(Member.class, id);
modelAndView.getModel().put("edit", true);
modelAndView.getModel().put("loggedinuser", getPrincipal());
modelAndView.getModel().put("roles", userRoleService.findAll());
modelAndView.getModel().put("member", member);
} catch (Exception e) {
System.out.println(e.getMessage());
}
return modelAndView;
}
@RequestMapping(value = "/usr/updateMember", method = RequestMethod.POST)
public String update(@ModelAttribute("member") Member member, BindingResult result, SessionStatus status) {
getGenericDao().update(member);
status.setComplete();
return "redirect:/list.do";
}
我的看法如下:
<form:form method="POST" modelAttribute="member"
class="horizForm">
<div class="row">
<div class="form-group col-md-">
<label class="col-md-3" for="name">Member
Name</label>
<div class="col-md">
<form:input type="text" path="name" id="name"
class="form-control input-sm" />
<div class="has-error">
<form:errors path="name" class="help" />
</div>
</div>
</div>
</div>
...
<div class="row">
<div class="form-group col-md-12">
<label class="col-md-3" for="userRoles">Roles</label>
<div class="col-md">
<form:select path="userRoles" items="${roles}" multiple="true"
itemValue="memberId" itemLabel="role"
class="form-control input-sm" />
<div class="has-error">
<form:errors path="userRoles" class="help" />
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-md-">
<label class="col-md-3 control-labl" for="chapter">Chapter</label>
<div class="col-md-7">
<%-- <form:select path="chapter.id" items="${chapters}" itemValue="id"
itemLabel="name" class="form-control input-sm"> --%>
<%-- <option value="-1">Select a Chapter</option>
<c:forEach var="chp" items="${chapters}">
<option value="${chp.id}">${chp.name}</option>
</c:forEach> --%>
<%-- </form:select> --%>
<form:select path="chapter" class="form-control input-sm">
<!-- <option value="-1">Select a Chapter</option> -->
<c:forEach var="chp" items="${chapters}">
<option value="${chp}">${chp.name}</option>
</c:forEach>
</form:select>
<div class="has-error">
<%-- <form:errors path="chapter.id" class="help-inline" /> --%>
<form:errors path="chapter" class="help-inline" />
</div>
</div>
</div>
</div>
GET 按预期工作,视图中填充了字符串、列表和章节类型对象的预期值。
当我尝试通过 POST 更新成员时,它没有获得绑定到 List 和 Chapter 对象的值,并且 BindingResult 具有以下值。
org.springframework.validation.BeanPropertyBindingResult: 3 errors
Field error in object 'member' on field 'chapter': rejected value [Chapter [chapterId=1, chapterName=SUPER]]; codes [typeMismatch.member.chapter,typeMismatch.chapter,typeMismatch.com.codex.survey.beans.Chapter,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [member.chapter,chapter]; arguments []; default message [chapter]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.codex.survey.beans.Chapter' for property 'chapter'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.codex.survey.beans.Chapter] for property 'chapter': no matching editors or conversion strategy found]
Field error in object 'member' on field 'userRoles': rejected value [2]; codes [typeMismatch.member.userRoles,typeMismatch.userRoles,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [member.userRoles,userRoles]; arguments []; default message [userRoles]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.List' for property 'userRoles'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.codex.survey.beans.UserRole] for property 'userRoles[0]': no matching editors or conversion strategy found]
我无法弄清楚这里的视图出了什么问题,请帮我解决这个问题。
感谢期待。
不同于有状态的、基于组件的框架(例如 JSF)Spring MVC 无法自动将原始 HTTP 参数转换为相应的对象类型。
因此您需要注册一个转换器来处理这个问题,并在 Spring 上下文中注册它。有多种方法可以做到这一点,但一种实现方式如下:
@Component
public class StringToChapterConverter implements Converter<String, Chapter> {
@Autowired
private ChaperService service;
/**
*chapterId is the HTTP post param passed in by the framework
*/
public Chapter convert(String chapterId) {
return service.findChapter(Integer.parseInt(chapterId));
}
}
如何注册取决于您的配置。但是假设 Java 代码配置然后:
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "..." })
public class MvcConfiguration extends WebMvcConfigurerAdapter{
//other configuration
@Override
public void addFormatters(FormatterRegistry formatterRegistry) {
formatterRegistry.addConverter(getChapterConverter());
}
@Bean
public StringToChapterConverter getChapterConverter(){
return new StringToChapterConverter();
}
}
因此,现在有了上述内容,当发出绑定到 Chapter 对象的请求时,框架将查看是否为 Chapter 类型定义了合适的转换器,然后调用相应的 convert(String源),它使您能够 return 来自您的数据库或任何地方的实例。
进一步了解: