在写一个使用spring3 的form标签的例子时,一直报错,错误信息为:java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'user' available as request attribute 。具体信息为:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'user' available as request attribute at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:141) at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:174) at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:194) at org.springframework.web.servlet.tags.form.LabelTag.autogenerateFor(LabelTag.java:129) at org.springframework.web.servlet.tags.form.LabelTag.resolveFor(LabelTag.java:119) at org.springframework.web.servlet.tags.form.LabelTag.writeTagContent(LabelTag.java:89) at org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:102) at org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:79) at org.apache.jsp.WEB_002dINF.jsp.register_jsp._jspx_meth_sf_005flabel_005f0(register_jsp.java:255) at org.apache.jsp.WEB_002dINF.jsp.register_jsp._jspService(register_jsp.java:140) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646) at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436) at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374) at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302) at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238) at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250) at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1047) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549) at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Thread.java:662)
在网上找了好长时间都不是原因所在,一直在想form标签中的modelAttribute是怎么跟project中相应的类联系在一起的,同事说是根据<form:input path="field"/>中的path attribute跟相应类中的field对应起来,由spring像注入一样给每个field赋值。所以一直在JSP页面查找原因,网上找的也都是改JSP页面,结果还是没有解决掉。
错误信息是“对于bean name 'xxxx' 既没有BindingResult也没有普通的目标对象可以用来作为请求属性”。突然想到在进入form表单页面之前,要有一个'xxxx'对象才可以在表单的标签中识别出来,所以在进入该JSP页面之前的Controller类里面相应的方法里面加上一个'xxxx'的对象。解决如下:
return new ModelAndView("register").addObject(new User());已经验证这样修改之后就不会报错。
例子的结构如图:
web.xml 的内容:
<?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_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>springMVCForm</display-name> <servlet> <servlet-name>springMVCForm</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>springMVCForm</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/springMVCForm-servlet.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
springMVCForm-servlet.xml 的内容:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <mvc:annotation-driven /> <context:component-scan base-package="org.spring.wayne" /> <bean id="config" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:db-config.properties</value> </list> </property> </bean> <!-- 获取数据源 --> <bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource"> <property name="driverClassName"> <value>${db.dirverClass}</value> </property> <property name="url"> <value>${db.url}</value> </property> <property name="username"> <value>${db.username}</value> </property> <property name="password"> <value>${db.password}</value> </property> </bean> <bean name="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> <constructor-arg ref="dataSource" /> </bean> <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg ref="dataSource" /> </bean> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀,在requestmapping输入的地址后自动调用该类进行视图解析 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /><!-- 跳转页面的前缀路径 如 /web-inf/jsp/ --> <property name="suffix" value=".jsp"></property><!-- 跳转页面后缀 如 helloWorld.jsp --> </bean> </beans>
db-config.properties的内容:
db.url= jdbc:mysql://localhost:3306/springmvcdb?useUnicode=true&characterEncoding=utf8 db.username=root db.password= db.dirverClass= com.mysql.jdbc.Driver
UserDao.class的内容:
package org.spring.wayne.dao; import org.spring.wayne.dao.basic.BasicDao; @Repository public class UserDao extends BasicDao { public void addUser(User user) { String SQL = "INSERT INTO TBL_USER(USERNAME ,PASSWORD) VALUES('" + user.getUserName() + "' ,'" + user.getPassword() + "')"; getJdbcTemplate().execute(SQL); } }
BasicDao.class的内容:
package org.spring.wayne.dao.basic; import org.springframework.beans.factory.annotation.Autowired; public class BasicDao { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private NamedParameterJdbcTemplate namedParameterJdbcTemplate; public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() { return namedParameterJdbcTemplate; } public void setNamedParameterJdbcTemplate(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; } }
UserService.class的内容:
package org.spring.wayne.service; import org.spring.wayne.web.form.User; public interface UserService { public void addUser(User user); }UserServiceImpl.class的内容:
package org.spring.wayne.service.impl; import org.spring.wayne.dao.UserDao; @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public void addUser(User user) { userDao.addUser(user); } }
RegController.class的内容:
package org.spring.wayne.web.controller; import javax.validation.Valid; @Controller public class RegController { @Autowired private UserService userService; @RequestMapping("/register.do") public String handler(@ModelAttribute("user") @Valid User user, BindingResult result, Model model) { if (!result.hasErrors()) { model.addAttribute("userName", user.getUserName()); model.addAttribute("password", user.getPassword()); userService.addUser(user); return "welcome"; } else return "register"; } }
WelcomeController.class的内容:
package org.spring.wayne.controller; import org.spring.wayne.web.form.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class WelcomeController { @RequestMapping("/welcome.do") public ModelAndView handler() { return new ModelAndView("register").addObject(new User()); } }User.class的内容:
package org.spring.wayne.web.form; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.NotEmpty; public class User { private String errors; @NotNull @NotEmpty(message = "This cannot be null") @Size(min = 4, max = 6, message = "length is wrong") private String userName; @NotNull @NotEmpty @Size(min = 6, max = 10) private String password; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getErrors() { return errors; } public void setErrors(String errors) { this.errors = errors; } }
index.jsp的内容:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>The Index Page</title> </head> <body> <h3> <a href="<%=basePath %>welcome.do">Click here to start</a> </h3> </body> </html>
register.jsp的内容:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>The Register Page</title> <script type="text/javascript"> function doSubmit() { var sf = document.getElementById("sf"); sf.submit(); } </script> <style type="text/css"> .errors { font-size: 12px; color: red; } </style> </head> <body> <sf:form id="sf" method="POST" modelAttribute="user" action="register.do"> <sf:errors path="errors" /> <fieldset> <legend>Register</legend> <table cellspacing="0"> <tr> <td><sf:label path="userName">UserName:</sf:label> </td> <td><sf:input path="userName" /> </td> <td><sf:errors path="userName" class="errors" /> </td> </tr> <tr> <td><sf:label path="password">Password:</sf:label> </td> <td><sf:password path="password" /> </td> <td><sf:errors path="password" class="errors" /> </td> </tr> <tr> <td colspan="2"><input type="button" value="Submit" onClick="doSubmit()"> </td> </tr> </table> </fieldset> </sf:form> </body> </html>
welcome.jsp的内容:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>The Welcome Page</title> </head> <body> Welcome, ${userName }, your password is ${password }! <br> <h3>This item has been inserted into the table !</h3> </body> </html>
用到的jar包包括spring3中的dist目录下的所有jar包,validation-api,hibernate-validator,slf4j-api,slf4j-log4j,log4j,commons-logging,tomcat-dbcp,mysql-connector-java-5.1.12-bin包。
运行截图如下:
运行project后的界面:
点击page中的链接后如图所示:
当UserName和Password为空时提示错误信息:
输入符合要求的UserName和Password跳转到下一个页面:
现在查询数据库可以看到一条记录:
该Spring MVC JUnit测试实例请点击(Spring MVC JUnit Test测试实例 附:读取WEB-INF下配置文件的方法)
#