所以我试图制作一个小的Spring MVC应用程序来学习Spring上的绳索,现在我发现自己有一个相当奇怪的问题。我有两个模型类:Game
和Publisher
,它们之间具有双向关系。每当我尝试通过html表单(在带有相关Spring标签的JSP页面上)将Game
对象作为ModelAttribute传递时,它总是返回一个nullpointer,其中使用对相关Publisher
对象的引用成为。我怀疑它与Spring只能将一个ModelAttribute传递给视图这一事实有关。有谁知道为什么会发生这种情况以及如何使它从视图中返回正确的Publisher
对象?
相关代码:
游戏课程:
public class Game {
private final long id;
@NotNull
private String title;
@NotNull
private Genre genre;
@NotNull
private Date releaseDate;
@NotNull
private Publisher publisher;
public Game() {
this.id = IdRegistry.GAMEIDREGISTRY.getId();
this.title = null;
this.genre = null;
this.releaseDate = null;
this.publisher = null;
}
public long getId() {
return id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Genre getGenre() {
return genre;
}
public void setGenre(Genre genre) {
this.genre = genre;
}
public Date getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(Date releaseDate) {
this.releaseDate = releaseDate;
}
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
}
发布商类:
public class Publisher {
private final long id;
@NotNull
private String name;
@NotNull
private List<Game> games;
public Publisher() {
this.id = IdRegistry.PUBLISHERIDREGISTRY.getId();
this.name = null;
this.games = new ArrayList<>();
}
public Publisher(String name) {
this.id = IdRegistry.PUBLISHERIDREGISTRY.getId();
this.name = name;
this.games = new ArrayList<>();
}
public Publisher(long id, String name) {
this.id = id;
this.name = name;
this.games = new ArrayList<>();
}
public Publisher(String name, List<Game> games) {
this.id = IdRegistry.PUBLISHERIDREGISTRY.getId();
this.name = name;
this.games = games;
}
public Publisher(long id, String name, List<Game> games) {
this.id = id;
this.name = name;
this.games = games;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Game> getGames() {
return games;
}
public void setGames(List<Game> games) {
this.games = games;
}
public void addGame(Game game) {
games.add(game);
}
public void addGames(Collection<Game> games) {
this.games.addAll(games);
}
public void removeGame(Game game) {
games.remove(game);
games.sort(null);
}
public void removeGames(Collection<Game> games) {
this.games.removeAll(games);
}
}
相关控制器方法:
@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
public ModelAndView getEditForm(@PathVariable long id) {
ModelAndView model = new ModelAndView("/game/editgame");
model.addObject("game", service.getGame(id));
model.addObject("genres", service.getAllGenres());
model.addObject("publishers", service.getAllPublishers());
return model;
}
@RequestMapping(value = "/edit", method = RequestMethod.POST)
public String editGame(@Valid @ModelAttribute("game") Game game, BindingResult bResult, SessionStatus status) {
if(bResult.hasErrors())
return "addgame";
service.updateGame(game.getId(), game.getTitle(), game.getGenre(), game.getReleaseDate(), game.getPublisher().getId());
status.setComplete();
return "redirect:/game.htm";
}
查看表单:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ page session="true" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<jsp:include page="/WEB-INF/jsp/head.jsp">
<jsp:param name="title" value="Edit games here" />
</jsp:include>
<body>
<%@include file="/WEB-INF/jsp/header.jsp" %>
<div class="container">
<h1>Edit games here</h1>
<c:url var="post_url" value="/game/edit.htm" />
<form:form id="gameform" role="form" method="post" modelAttribute="game" action="${post_url}">
<form:input path="id" type="hidden" id="id" name="id" value="${sessionScope.game.id}"/>
<div class="form-group">
<label for="title">Title</label>
<form:input path="title" type="text" class="form-control" id="title" name="title" value="${sessionScope.game.title}" placeholder="Title" required="required"/>
</div>
<div class="form-group">
<label for="genre">Genre</label>
<form:select path="genre" class="form-control" id="genre" name="genre" value="${sessionScope.game.genre}" placeholder="Genre" required="required">
<c:forEach var="genre" items="${genres}">
<form:option value="${genre}"/>
</c:forEach>
</form:select>
</div>
<div class="form-group">
<label for="releaseDate">Release Date</label>
<fmt:formatDate var="fmtDate" value="${sessionScope.game.releaseDate}" type="date" pattern="yyyy-MM-dd" />
<form:input path="releaseDate" type="date" class="form-control" id="releaseDate" name="releaseDate" value="${fmtDate}" placeholder="yyyy-mm-dd" required="required"/>
</div>
<div class="form-group">
<label for="publisher">Publisher</label>
<form:select path="publisher" class="form-control" id="publisher" name="publisher" value="${sessionScope.game.publisher}" placeholder="Publisher" required="required">
<c:forEach var="publisher" items="${publishers}">
<form:option value="${publisher.name}"/>
</c:forEach>
</form:select>
</div>
<input class="btn btn-primary btn-block" type="submit" value="Update">
</form:form>
</div>
</body>
</html>