Spring MVC:表单如何将对象传输到控制器??总是400错误
Spring MVC :how a form transfer an object to Controller?? Always 400 error
当我尝试访问时 http://localhost:8080/XX/articles/addArticle
并提交表单,总是出现“400 BAD REQUEST”错误。
我试图查找原因,我得到的只是从表单传输的对象与我的模型类型不同(这里是 Article 对象?)。但是,我觉得我真的不明白..
所有代码都在这里,配置都很好
这里有 2 个模型:
Article.java
@Entity
@Table(name="article_inf")
public class Article {
private int articleId;
private String title;
private User author;
private String content;
public Article() {
}
public Article(String title, User author, String content) {
this.title = title;
this.author = author;
this.content = content;
}
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public int getArticleId() {
return articleId;
}
public void setArticleId(int articleId) {
this.articleId = articleId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@ManyToOne(targetEntity=User.class)
@JoinColumn(name="author", referencedColumnName="userId", nullable=false)
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
User.java
@Entity
@Table(name="agri_user_inf")
public class User {
private int userId;
private String userName;
private String password;
private String cellPhone;
private List<Article> articles;
public User() {
articles = new ArrayList<>();
}
public User(String userName, String password, String cellPhone) {
this.userName = userName;
this.password = password;
this.cellPhone = cellPhone;
}
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
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 getCellPhone() {
return cellPhone;
}
public void setCellPhone(String cellPhone) {
this.cellPhone = cellPhone;
}
@OneToMany(targetEntity=Article.class, mappedBy="author")
public List<Article> getArticles() {
return articles;
}
public void setArticles(List<Article> articles) {
this.articles = articles;
}
控制器
ArticleController.java
@Controller
@RequestMapping("articles")
public class ArticleController {
private ArticleDao articleDao;
@Autowired
public ArticleController(ArticleDao articleDao) {
this.articleDao = articleDao;
}
@RequestMapping(value="addArticle", method=GET)
public String addArticle(ModelMap modelMap) {
List<User> authors = userDao.getAllUsers();
// add all authors
modelMap.addAttribute("authors", authors);
return "articles/addArticleForm";
}
@RequestMapping(value="addArticle", method=POST)
public String addArticle(Article article) {
articleDao.addArticle(article);
return "redirect:/articles";
}
// other code
我的表格addArticleForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!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>Insert title here</title>
</head>
<body>
<form method="post">
title: <input type="text" name="title"/><br/>
author: <select name="author">
<c:forEach items="${authors}" var="author">
<option value="${author}">${author.userName}</option>
</c:forEach>
</select>
<br/>
content: <input type="text" name="content"/><br/>
<input type="submit" value="add"/>
</form>
</body>
</html>
- 您违反了 REST 原则。之后始终在您的端点和资源名称中使用版本。示例 - /api/v1/articles。之后借助 HttpMethods 访问您的资源。例子 - 如果你想
1.1 添加新文章,使用POST请求/api/v1/articles
1.2 删除已有文章,使用DELETE请求/api/v1/articles/{articleId}
1.3 获取一篇文章,使用GET请求到/api/v1/articles/{articleId}
1.4 获取所有文章,使用GET请求到/api/v1/articles
1.5 更新现有文章,使用 PUT 请求 /api/v1/articles/{articleId}
切勿使用将在所有层的数据库中保留的实体。将实体与您的视图连接是一种不好的做法,您可以改用 DTO。
在您的控制器层中使用@ModelAttribute 注释,其名称与视图中的名称相同,以处理传入的 Article 对象。例子
public String addArticle(@ModelAttribute("article") 文章文章 )
要首先添加新文章,您需要创建端点,该端点在 ModelMap 中返回空文章对象。然后你必须在你的前端处理这个(JSP)并按照步骤 3 提交此表单。
希望这会有所帮助。
我找到了解决方案:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!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>Insert title here</title>
</head>
<body>
<form method="post">
title: <input type="text" name="title"/><br/>
author: <select name="author.userId">
<c:forEach items="${authors}" var="author">
<option value="${author.userId}">${author.userName}</option>
</c:forEach>
</select>
<br/>
content: <input type="text" name="content"/><br/>
<input type="submit" value="add"/>
</form>
</body>
</html>
将
当我尝试访问时 http://localhost:8080/XX/articles/addArticle
并提交表单,总是出现“400 BAD REQUEST”错误。
我试图查找原因,我得到的只是从表单传输的对象与我的模型类型不同(这里是 Article 对象?)。但是,我觉得我真的不明白..
所有代码都在这里,配置都很好
这里有 2 个模型:
Article.java
@Entity
@Table(name="article_inf")
public class Article {
private int articleId;
private String title;
private User author;
private String content;
public Article() {
}
public Article(String title, User author, String content) {
this.title = title;
this.author = author;
this.content = content;
}
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public int getArticleId() {
return articleId;
}
public void setArticleId(int articleId) {
this.articleId = articleId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@ManyToOne(targetEntity=User.class)
@JoinColumn(name="author", referencedColumnName="userId", nullable=false)
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
User.java
@Entity
@Table(name="agri_user_inf")
public class User {
private int userId;
private String userName;
private String password;
private String cellPhone;
private List<Article> articles;
public User() {
articles = new ArrayList<>();
}
public User(String userName, String password, String cellPhone) {
this.userName = userName;
this.password = password;
this.cellPhone = cellPhone;
}
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
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 getCellPhone() {
return cellPhone;
}
public void setCellPhone(String cellPhone) {
this.cellPhone = cellPhone;
}
@OneToMany(targetEntity=Article.class, mappedBy="author")
public List<Article> getArticles() {
return articles;
}
public void setArticles(List<Article> articles) {
this.articles = articles;
}
控制器
ArticleController.java
@Controller
@RequestMapping("articles")
public class ArticleController {
private ArticleDao articleDao;
@Autowired
public ArticleController(ArticleDao articleDao) {
this.articleDao = articleDao;
}
@RequestMapping(value="addArticle", method=GET)
public String addArticle(ModelMap modelMap) {
List<User> authors = userDao.getAllUsers();
// add all authors
modelMap.addAttribute("authors", authors);
return "articles/addArticleForm";
}
@RequestMapping(value="addArticle", method=POST)
public String addArticle(Article article) {
articleDao.addArticle(article);
return "redirect:/articles";
}
// other code
我的表格addArticleForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!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>Insert title here</title>
</head>
<body>
<form method="post">
title: <input type="text" name="title"/><br/>
author: <select name="author">
<c:forEach items="${authors}" var="author">
<option value="${author}">${author.userName}</option>
</c:forEach>
</select>
<br/>
content: <input type="text" name="content"/><br/>
<input type="submit" value="add"/>
</form>
</body>
</html>
- 您违反了 REST 原则。之后始终在您的端点和资源名称中使用版本。示例 - /api/v1/articles。之后借助 HttpMethods 访问您的资源。例子 - 如果你想
1.1 添加新文章,使用POST请求/api/v1/articles 1.2 删除已有文章,使用DELETE请求/api/v1/articles/{articleId} 1.3 获取一篇文章,使用GET请求到/api/v1/articles/{articleId} 1.4 获取所有文章,使用GET请求到/api/v1/articles 1.5 更新现有文章,使用 PUT 请求 /api/v1/articles/{articleId}
切勿使用将在所有层的数据库中保留的实体。将实体与您的视图连接是一种不好的做法,您可以改用 DTO。
在您的控制器层中使用@ModelAttribute 注释,其名称与视图中的名称相同,以处理传入的 Article 对象。例子
public String addArticle(@ModelAttribute("article") 文章文章 )
要首先添加新文章,您需要创建端点,该端点在 ModelMap 中返回空文章对象。然后你必须在你的前端处理这个(JSP)并按照步骤 3 提交此表单。
希望这会有所帮助。
我找到了解决方案:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!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>Insert title here</title>
</head>
<body>
<form method="post">
title: <input type="text" name="title"/><br/>
author: <select name="author.userId">
<c:forEach items="${authors}" var="author">
<option value="${author.userId}">${author.userName}</option>
</c:forEach>
</select>
<br/>
content: <input type="text" name="content"/><br/>
<input type="submit" value="add"/>
</form>
</body>
</html>
将