首先我想说,我已经在互联网和SO上搜索了解决方案,但没有找到针对这种特殊情况的解决方案。我刚刚学习java网络编程。我正在制作简单的 mvc 应用程序,用于将教师添加到 MySQL 数据库。 DB 只有 3 个表:'teacher'、'title' 和连接表 'teacher_title'。 “title”是一个查找表,具有“title_id”/“title_description”值。在我的 jsp 页面中,我有用于选择教师职称(例如博士、硕士等)的下拉列表、用于输入教师名字和姓氏的 2 个输入字段以及一个提交/保存按钮。
这是我的 Controller :
/**
* Handles and retrieves the add teacher page
*/
@RequestMapping(value="/add", method = RequestMethod.GET)
public String getAddTeacher(Model model) {
logger.debug("Received request to show add teacher page");
// Add to model
model.addAttribute("teacherAttribute", new Teacher());
model.addAttribute("titleList", titleService.getAll());
return "addTeacher";
}
/**
* Adds a new teacher by delegating the processing to TeacherService.
* Displays a confirmation JSP page
*/
@RequestMapping(value="/add", method = RequestMethod.POST)
public String postAddTeacher(@RequestParam(value = "id") Integer titleId,
@ModelAttribute("teacherAttribute") Teacher teacher) {
logger.debug("Received request to add new teacher");
// Call TeacherService to do the actual adding
teacherService.add(titleId, teacher);
return "addTeacherSuccess";
}
这是addTeacher.jsp页面的重要部分:
<c:url var="saveUrl" value="/essays/main/teacher/add?id=titleId" />
<form:form modelAttribute="teacherAttribute" method="POST" action="${saveUrl}">
<form:label path="title">Title:</form:label>
<form:select path="title" id="titleSelect">
<form:option value="0" label="Select" />
<form:options items="${titleList}" itemValue="titleId" itemLabel="titleDescription" />
</form:select>
...
这是教师实体:
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "TEACHER_ID")
private Integer techerId;
@Column(name = "FIRST_NAME", length = 50)
private String firstName;
@Column(name = "LAST_NAME", length = 50)
private String lastName;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.EAGER)
@JoinTable(name="teacher_title",
joinColumns = @JoinColumn(name="TEACHER_ID"),
inverseJoinColumns = @JoinColumn(name="TITLE_ID")
)
private Title title;
// getters and setters
}
这是标题实体:
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "TITLE_ID")
private Integer titleId;
@Column(name = "TITLE_DESCRIPTION", length = 10)
private String titleDescription;
// getters and setters
}
为了以防万一,这些分别是教师和职称服务:
/**
* Adds new teacher
*/
public void add(Integer titleId, Teacher teacher) {
logger.debug("Adding new teacher");
Session session = sessionFactory.getCurrentSession();
// Retrieve existing title via id
Title existingTitle = (Title) session.get(Title.class, titleId);
// Add title to teacher
teacher.setTitle(existingTitle);
// Persists to db
session.save(teacher);
}
.
/**
* Retrieves a list of titles
*/
public List<Title> getAll() {
logger.debug("Retrieving all titles");
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("FROM Title");
List<Title> titleList = castList(Title.class, query.list());
return titleList;
}
public static <T> List<T> castList(Class<? extends T> clazz, Collection<?> c) {
List<T> r = new ArrayList<T>(c.size());
for(Object o: c)
r.add(clazz.cast(o));
return r;
}
/**
* Retrieves a single title
*/
public Title get(Integer titleId) {
logger.debug("Retrieving single title");
Session session = sessionFactory.getCurrentSession();
// Retrieve existing title
Title title = (Title) session.get(Title.class, titleId);
return title;
}
到目前为止我设法理解的是问题出在我的jsp 中的select 标记上。当我注释掉选择标签并手动输入参数(例如 URL?id=1)时,保存到数据库效果很好。否则,我会收到以下错误:“HTTP 状态 400 - 客户端发送的请求在语法上不正确。”。我也在网上搜索过这个错误,但没有找到适用的解决方案。
这超出了我的浅薄知识范围,无法确定我在哪里犯了错误。预先感谢您。
更新:这是用于添加新教师的新 Controller 方法,其中 @RequestParam
的 value
属性从 id
更改为 title
:
@RequestMapping(value="/add", method = RequestMethod.POST)
public String postAddTeacher(@RequestParam(value = "title") Integer titleId,
@ModelAttribute("teacherAttribute") Teacher teacher) {
logger.debug("Received request to add new teacher");
// Call TeacherService to do the actual adding
teacherService.add(titleId, teacher);
// This will resolve to /WEB-INF/jsp/addTeacherSuccess.jsp
return "addTeacherSuccess";
}
这是新的 addTeacher.jsp,其中 ?id=titleId
已从 URL 中删除:
<c:url var="saveUrl" value="/essays/main/teacher/add" />
<form:form modelAttribute="teacherAttribute" method="POST" action="${saveUrl}">
<form:label path="title">Title:</form:label>
<form:select path="title" id="titleSelect">
<form:option value="0" label="Select" />
<form:options items="${titleList}" itemValue="titleId" itemLabel="titleDescription" />
</form:select>
...
仍然遇到与以前相同的错误。
这是我收到的错误(我不明白):
[TRACE] [http-bio-8080-exec-7 11:10:38] (InvocableHandlerMethod.java:getMethodArgumentValues:166) Error resolving argument [1] [type=com.jovana.domain.Teacher]
HandlerMethod details:
Controller [com.jovana.controller.MainController]
Method [public java.lang.String com.jovana.controller.MainController.postAddTeacher(java.lang.Integer,com.jovana.domain.Teacher)]
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'teacherAttribute' on field 'title': rejected value [4]; codes [typeMismatch.teacherAttribute.title,typeMismatch.title,typeMismatch.com.jovana.domain.Title,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [teacherAttribute.title,title]; arguments []; default message [title]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.jovana.domain.Title' for property 'title'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.jovana.domain.Title] for property 'title': no matching editors or conversion strategy found]
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:110)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:123)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
[TRACE] [http-bio-8080-exec-7 11:10:38] (InvocableHandlerMethod.java:getMethodArgumentValues:166) Error resolving argument [1] [type=com.jovana.domain.Teacher]
HandlerMethod details:
Controller [com.jovana.controller.MainController]
Method [public java.lang.String com.jovana.controller.MainController.postAddTeacher(java.lang.Integer,com.jovana.domain.Teacher)]
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'teacherAttribute' on field 'title': rejected value [4]; codes [typeMismatch.teacherAttribute.title,typeMismatch.title,typeMismatch.com.jovana.domain.Title,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [teacherAttribute.title,title]; arguments []; default message [title]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.jovana.domain.Title' for property 'title'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.jovana.domain.Title] for property 'title': no matching editors or conversion strategy found]
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:110)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:123)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
[DEBUG] [http-bio-8080-exec-7 11:10:38] (AbstractHandlerExceptionResolver.java:resolveException:132) Resolving exception from handler [public java.lang.String com.jovana.controller.MainController.postAddTeacher(java.lang.Integer,com.jovana.domain.Teacher)]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'teacherAttribute' on field 'title': rejected value [4]; codes [typeMismatch.teacherAttribute.title,typeMismatch.title,typeMismatch.com.jovana.domain.Title,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [teacherAttribute.title,title]; arguments []; default message [title]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.jovana.domain.Title' for property 'title'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.jovana.domain.Title] for property 'title': no matching editors or conversion strategy found]
[DEBUG] [http-bio-8080-exec-7 11:10:38] (AbstractHandlerExceptionResolver.java:resolveException:132) Resolving exception from handler [public java.lang.String com.jovana.controller.MainController.postAddTeacher(java.lang.Integer,com.jovana.domain.Teacher)]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'teacherAttribute' on field 'title': rejected value [4]; codes [typeMismatch.teacherAttribute.title,typeMismatch.title,typeMismatch.com.jovana.domain.Title,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [teacherAttribute.title,title]; arguments []; default message [title]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.jovana.domain.Title' for property 'title'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.jovana.domain.Title] for property 'title': no matching editors or conversion strategy found]
[DEBUG] [http-bio-8080-exec-7 11:10:38] (AbstractHandlerExceptionResolver.java:resolveException:132) Resolving exception from handler [public java.lang.String com.jovana.controller.MainController.postAddTeacher(java.lang.Integer,com.jovana.domain.Teacher)]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'teacherAttribute' on field 'title': rejected value [4]; codes [typeMismatch.teacherAttribute.title,typeMismatch.title,typeMismatch.com.jovana.domain.Title,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [teacherAttribute.title,title]; arguments []; default message [title]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.jovana.domain.Title' for property 'title'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.jovana.domain.Title] for property 'title': no matching editors or conversion strategy found]
[DEBUG] [http-bio-8080-exec-7 11:10:38] (AbstractHandlerExceptionResolver.java:resolveException:132) Resolving exception from handler [public java.lang.String com.jovana.controller.MainController.postAddTeacher(java.lang.Integer,com.jovana.domain.Teacher)]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'teacherAttribute' on field 'title': rejected value [4]; codes [typeMismatch.teacherAttribute.title,typeMismatch.title,typeMismatch.com.jovana.domain.Title,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [teacherAttribute.title,title]; arguments []; default message [title]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.jovana.domain.Title' for property 'title'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.jovana.domain.Title] for property 'title': no matching editors or conversion strategy found]
[DEBUG] [http-bio-8080-exec-7 11:10:38] (AbstractHandlerExceptionResolver.java:resolveException:132) Resolving exception from handler [public java.lang.String com.jovana.controller.MainController.postAddTeacher(java.lang.Integer,com.jovana.domain.Teacher)]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'teacherAttribute' on field 'title': rejected value [4]; codes [typeMismatch.teacherAttribute.title,typeMismatch.title,typeMismatch.com.jovana.domain.Title,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [teacherAttribute.title,title]; arguments []; default message [title]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.jovana.domain.Title' for property 'title'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.jovana.domain.Title] for property 'title': no matching editors or conversion strategy found]
[DEBUG] [http-bio-8080-exec-7 11:10:38] (AbstractHandlerExceptionResolver.java:resolveException:132) Resolving exception from handler [public java.lang.String com.jovana.controller.MainController.postAddTeacher(java.lang.Integer,com.jovana.domain.Teacher)]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'teacherAttribute' on field 'title': rejected value [4]; codes [typeMismatch.teacherAttribute.title,typeMismatch.title,typeMismatch.com.jovana.domain.Title,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [teacherAttribute.title,title]; arguments []; default message [title]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.jovana.domain.Title' for property 'title'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.jovana.domain.Title] for property 'title': no matching editors or conversion strategy found]
[DEBUG] [http-bio-8080-exec-7 11:10:38] (DispatcherServlet.java:processDispatchResult:999) Null ModelAndView returned to DispatcherServlet with name 'spring': assuming HandlerAdapter completed request handling
[DEBUG] [http-bio-8080-exec-7 11:10:38] (DispatcherServlet.java:processDispatchResult:999) Null ModelAndView returned to DispatcherServlet with name 'spring': assuming HandlerAdapter completed request handling
[TRACE] [http-bio-8080-exec-7 11:10:38] (FrameworkServlet.java:resetContextHolders:1028) Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@5f57b190
[TRACE] [http-bio-8080-exec-7 11:10:38] (FrameworkServlet.java:resetContextHolders:1028) Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@5f57b190
[DEBUG] [http-bio-8080-exec-7 11:10:38] (FrameworkServlet.java:processRequest:966) Successfully completed request
[DEBUG] [http-bio-8080-exec-7 11:10:38] (FrameworkServlet.java:processRequest:966) Successfully completed request
[TRACE] [http-bio-8080-exec-7 11:10:38] (AbstractApplicationContext.java:publishEvent:332) Publishing event in WebApplicationContext for namespace 'spring-servlet': ServletRequestHandledEvent: url=[/testLookupTable/essays/main/teacher/add]; client=[0:0:0:0:0:0:0:1]; method=[POST]; servlet=[spring]; session=[72089007DB0E4468BA90CDA44FCA8CC0]; user=[null]; time=[144ms]; status=[OK]
[TRACE] [http-bio-8080-exec-7 11:10:38] (AbstractApplicationContext.java:publishEvent:332) Publishing event in WebApplicationContext for namespace 'spring-servlet': ServletRequestHandledEvent: url=[/testLookupTable/essays/main/teacher/add]; client=[0:0:0:0:0:0:0:1]; method=[POST]; servlet=[spring]; session=[72089007DB0E4468BA90CDA44FCA8CC0]; user=[null]; time=[144ms]; status=[OK]
[TRACE] [http-bio-8080-exec-7 11:10:38] (AbstractApplicationContext.java:publishEvent:332) Publishing event in Root WebApplicationContext: ServletRequestHandledEvent: url=[/testLookupTable/essays/main/teacher/add]; client=[0:0:0:0:0:0:0:1]; method=[POST]; servlet=[spring]; session=[72089007DB0E4468BA90CDA44FCA8CC0]; user=[null]; time=[144ms]; status=[OK]
[TRACE] [http-bio-8080-exec-7 11:10:38] (AbstractApplicationContext.java:publishEvent:332) Publishing event in Root WebApplicationContext: ServletRequestHandledEvent: url=[/testLookupTable/essays/main/teacher/add]; client=[0:0:0:0:0:0:0:1]; method=[POST]; servlet=[spring]; session=[72089007DB0E4468BA90CDA44FCA8CC0]; user=[null]; time=[144ms]; status=[OK]
解决方案(谢谢storm_buster)正在将其添加到 Controller 中:
@InitBinder
public void initBinder(WebDataBinder binder, WebRequest request) {
binder.registerCustomEditor(Title.class, "title", new PropertyEditorSupport() {
@Override
public void setAsText(String text) {
setValue((text.equals(""))?null:titleService.getTitle(Integer.parseInt((String)text)));
}
});
}
结束!
您收到此错误是因为您正在使用
@ModelAttribute("teacherAttribute") Teacher teacher)
Spring 无法将您的 requestParam“title”(字符串)转换为属于教师实体的 Title 类。
你有两个解决方案:1-将其添加到您的 Controller
@InitBinder
public void initBinder(WebDataBinder binder, WebRequest request) {
binder.registerCustomEditor(Title.class, "title", new PropertyEditorSupport() {
@Override
public void setAsText(String text) {
setValue((text.equals(""))?null:titleService.getTitle(Integer.parseInt((String)text)));
}
});
}
2- 将您的请求映射修改为:
@RequestMapping(value="/add", method = RequestMethod.POST)
public String postAddTeacher(@RequestParam(value = "title") Integer titleId,
@RequestParam("teacherAttribute") Integer teacherId) {
并添加一个新的界面:
teacherService.add(titleId, teacherId);
我是一名优秀的程序员,十分优秀!