java之SpringMVC 模型属性在发布时返回 null

mate10pro 阅读:54 2023-08-03 15:25:56 评论:0

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

以下 Controller :

@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 - 在这个 View 中,所有模型信息都通过 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 返回 NullPointerException。

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

无论如何,这些是类:

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); 
} 
} 

宠物编辑器.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 非常相似。 最后,用于绑定(bind)自定义编辑器和模型类的初始化程序。

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()); 
} 
} 

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

请您参考如下方法:

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

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

  2. 在 session 中存储npdto

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

您可能想要#2,在这种情况下,将 @SessionAttributes("npdto") 添加到您的 Controller 之上。

您还应该将 SessionStatus 参数添加到您的 post 处理程序,并在不需要时调用 sessionStatus.complete() 以从 session 中清除该项目更多的。

参见 Spring MVC: Validation, Post-Redirect-Get, Partial Updates, Optimistic Concurrency, Field Security供引用答案。


标签:springMVC
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号