为什么我的Spring ModelAttribute从具有空引用的表单返回?

时间:2016-04-08 14:19:21

标签: java spring spring-mvc modelattribute

所以我试图制作一个小的Spring MVC应用程序来学习Spring上的绳索,现在我发现自己有一个相当奇怪的问题。我有两个模型类:GamePublisher,它们之间具有双向关系。每当我尝试通过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>

0 个答案:

没有答案