post 上的 SpringMVC 模型属性 returns null

SpringMVC model attribute returns null on post

我正在开发一个 SpringMVC 3 普通应用程序,但我被困在某个地方。本质上,在 GET 操作中填充字段的模型属性在 POST 中返回 NULL(即使我没有对它们进行任何操作)。我检查了这个和其他论坛,我想出的唯一答案是为我应该放入模型的 classes 实现编辑器,一个可用于注册自定义编辑器并使其可用的初始化器到应用程序(在 servletname-servlet.xml 文件中)。我所做的所有操作,但绝对没有运气。我想知道是否有人可以帮助我。 谢谢你。

以下控制器:

@Controller
@RequestMapping(value="/nourish")
public class NourishController {

private PetDAO pdao = new PetDAO();
private UserDAO udao = new UserDAO();
private FeedVirtualPet feedvp = new FeedVirtualPet();

@RequestMapping(method = RequestMethod.GET)
public String nourish(Model model, HttpServletRequest request){
    NourishPetDTO npdto = new NourishPetDTO();
    PetDTO      pdto=pdao.findPetByBusinessKey((PetDTO)request.getSession().getAttribute("pet"));
    npdto.setPet(pdto);
    npdto.setAmt(0);
    model.addAttribute("npdto", npdto);
    return "nourish";
}


@RequestMapping(method = RequestMethod.POST)
public String nourishPOST(@ModelAttribute("npdto") NourishPetDTO npdto,
        //BindingResult result,
        HttpServletRequest request){

    System.out.println("*****nourishPOST.npdto.amt: "+npdto.getAmt());
    System.out.println("*****nourishPOST.npdto.pet.petname: "+npdto.getPet().getPetName());
    System.out.println("*****nourishPOST.npdto.pet.hunger:     "+npdto.getPet().getHunger());
    PetDTO pdto = feedvp.feed(npdto.getPet(), npdto.getAmt());
    request.getSession().setAttribute("user", pdto.getOwner());
    return "redirect:detailPet";
}
}

具有 GET 和 POST 操作的方法,并关联到以下 jsp - 在这个视图中,所有模型信息都通过 EL 正确显示:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" session="true"  pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Nourish your pet!!</title>
</head>
<body>
Your stats for <h3>${npdto.pet.petName}</h3><br>
    Please note that any value you put inside will:
        <ol>
            <li>Subtract value to your current hunger level</li>
            <li>Add (value) to your current health level</li>
        </ol>
    Please note that any value you'll put will in many manners "resized":
    <ol>
        <li>It must be even. If not, a default 0 value will be  applied</li>
        <li>It can't be greater than 4. If it's greater, the maxium value  of 4 will be anyway considered.</li>
        <li>If it ain't a number, a default zero value will be passed</li>
    </ol>
<table>
    <tr><td>Health</td><td>${npdto.pet.health}</td></tr>
    <tr><td>Hunger</td><td>${npdto.pet.hunger}</td></tr>
</table>
<form action="nourish" method="post"  >
    nourishment: <input type="text" name="amt"/>
    <input type="submit" value="Nourish!"/>
</form>
</body>
</html>

(请注意我没有使用返回 NULL 的模型属性,以确保我没有对它做任何事情)

POST 操作在指令

上失败
System.out.println("*****nourishPOST.npdto.pet.petname:"+npdto.getPet().getPetName());

作为 Tomcat returns NullPointerException。

如前所述,我一直在寻找这个问题的解决方案,我能找到的一切都是添加编辑器 classes 并将编辑器注册到活页夹。结果还是一样。

无论如何,这些是 classes:

NourishPetEditor.java

public class NourishPetEditor extends PropertyEditorSupport {

private PetEditor pedit;

public PetEditor getPedit() {
    return pedit;
}


public NourishPetEditor() {
    // TODO Auto-generated constructor stub
    pedit =  new PetEditor();
}

@Override 
public String getAsText(){
    NourishPetDTO npdto= (NourishPetDTO)getValue();
    return super.getAsText()+","+npdto.getAmt();
}

public NourishPetDTO makeNourishPetDTOInstance(String [] parts){

    NourishPetDTO npdto = new NourishPetDTO(); 
    npdto.setPet(pedit.makePetDTOInstance(parts));
    npdto.setAmt(Integer.parseInt(parts[9]));
    return npdto;

}


public void setAsText(String key){
    String []parts = key.split(",");
    NourishPetDTO npdto = makeNourishPetDTOInstance(parts);
    setValue(npdto);
}
}

PetEditor.java

package com.virtualpet.dtoeditors;
import java.beans.PropertyEditorSupport;

import com.virtualpet.virtualpet_daos.PetDAO;  
import com.virtualpet.virtualpet_dtos.PetDTO;
import com.virtualpet.virtualpet_dtos.UserDTO;
public class PetEditor extends PropertyEditorSupport{

private PetDAO pdao;

public PetEditor() {
    // TODO Auto-generated constructor stub
}

public PetEditor(PetDAO pdao) {
    // TODO Auto-generated constructor stub
    this.pdao = pdao;

}


public String getAsText(){
    PetDTO pdto = (PetDTO) this.getValue();

    return pdto.getClass().getName()+","+ //0
    pdto.getPetName()+","+ //1
    pdto.getHealth()+","+  //2
    pdto.getHunger()+","+  //3
    pdto.getMood()+","+","+ //4
    pdto.getOwner().getClass().getName()+","+ //5
    pdto.getOwner().getUsername()+","+ //6
    pdto.getOwner().getEmail()+","+pdto.getOwner().getPassword(); //7,8

}

public void setAsText(String key) throws IllegalArgumentException {
    String []parts = key.split(",");
    PetDTO pdto = makePetDTOInstance(parts);
    setValue(pdto);
}


public UserDTO makeUserDTOInstance(String[] parts)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {

            UserDTO udto = (UserDTO)Class.forName(parts[5]).newInstance();
            udto.setUsername(parts[6]);
            udto.setEmail(parts[7]);
            udto.setPassword(parts[8]);
            return udto;
}


public PetDTO makePetDTOInstance(String[]parts){
    try{
        PetDTO pdto = (PetDTO) Class.forName(parts[0]).newInstance();
        pdto.setPetName(parts[1]);
        pdto.setHealth(Integer.parseInt(parts[2]));
        pdto.setHunger(Integer.parseInt(parts[3]));
        pdto.setMood(Integer.parseInt(parts[4]));

        UserDTO udto = makeUserDTOInstance(parts);

        pdto.setOwner(udto);
        return pdto;
    }
    catch (Exception e){
        throw new IllegalArgumentException();
    }
}
}

我会饶你 UserEditor,因为它与 PetEditor 非常相似。 最后,用于绑定自定义编辑器和模型的初始化器 类.

VirtualPetDTOInitializer.java

package com.virtualpet.dtoeditors;

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.context.request.WebRequest;

import com.virtualpet.virtualpet_dtos.NourishPetDTO;
import com.virtualpet.virtualpet_dtos.PetDTO;
import com.virtualpet.virtualpet_dtos.UserDTO;

public class VirtualPetDTOInitializer implements WebBindingInitializer {

public void initBinder(WebDataBinder binder, WebRequest arg1) {
    // TODO Auto-generated method stub
        binder.registerCustomEditor(UserDTO.class, new UserEditor( ));
        binder.registerCustomEditor(PetDTO.class, new PetEditor( ));
        binder.registerCustomEditor(NourishPetDTO.class, new NourishPetEditor());
}
}

这个class在dispatcher中定义了一个属性值-servlet.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<bean id="userDao"
    class="com.virtualpet.virtualpet_daos.UserDAO"/>
<bean id="petDao"
    class="com.virtualpet.virtualpet_daos.PetDAO" />
<bean    class="org.springframwork.web.servlet.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="webBindingInitializer">
        <bean class="com.virtualpet.dtoeditors.VirtualPetDTOInitializer"/>
    </property>
</bean>
</beans>

作为 Spring MVC 的新手,我必须告诉你,这个错误是我在实现这些 classes 之前就遇到的。所以,看起来它们不是一个因素,但是,它们的实现是我能找到的关于在 POST 之后返回 null 的模型属性的所有内容。 有人可以帮忙吗?提前致谢。

您需要执行以下操作之一:

  1. npdto 的值存储在隐藏的表单字段中

  2. 在会话npdto中存储npdto

  3. 从您的 post 处理程序中的数据库重新读取 npdto

你可能想要#2,在这种情况下,在你的控制器上添加 @SessionAttributes("npdto")

您还应该向 post 处理程序添加一个 SessionStatus 参数,并在您不再需要该项目时调用 sessionStatus.complete() 从会话中清除该项目。

请参阅 以获取参考答案。