BindingResult 和 bean 名称“tweets"的普通目标对象都不能用作请求属性 [英] Neither BindingResult nor plain target object for bean name 'tweets' available as request attribute

查看:31
本文介绍了BindingResult 和 bean 名称“tweets"的普通目标对象都不能用作请求属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将全局表单添加到用户可以发布的位置.由于某种原因,我收到了该错误,对此进行了一段时间的研究,这一定是我的控制器有问题但不确定

I'm trying to add a global form to where a user can post. I get that error for some reason, been working on this for a while, it must be something with my controller but not sure

在 home.jsp 中

in home.jsp

<form:form modelAttribute= "tweets">
<form:input path="tweet" />
 <input id="user" name="user" type="hidden" value="${user}"/>
<input type="submit" value="send" />
</form:form>

在推文控制器中

 public class TweetsController {

private TweetsService tweetsService;

@ModelAttribute("tweets")
// name for tweet form in home public Tweets
public Tweets construct() {

    return new Tweets();
}

// //----------------------------------------------------------------------
@RequestMapping(value = "/")
public String newTweet(Model model) {
    model.addAttribute("tweets", new Tweets());
    return "/home";
}

@RequestMapping(method = RequestMethod.GET)
public String tweet(Model model) throws MessagingException {

    // key value - attribute and the value of the attribute
    // if key isn't passed, it will default to camelCased class name
    model.addAttribute("tweets", new CreateTweet());

    return "home";

}

@RequestMapping(method = RequestMethod.POST)
public String tweet(@ModelAttribute("tweets") CreateTweet tweet, BindingResult result,
        RedirectAttributes redirectAttributes) {

    if (result.hasErrors()) {
        return "redirect:/";
    }

    tweetsService.createTweet(tweet);

    return "redirect:/";

}

  }

TweetsServiceImpl

TweetsServiceImpl

@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class TweetsServiceImpl implements TweetsService {

    private TweetsRepository tweetsRepo;
@Autowired
private UserRepository userRepo;

@Autowired
public TweetsServiceImpl(UserRepository userRepo, TweetsRepository tweetsRepo) {

    this.userRepo = userRepo;
    this.tweetsRepo = tweetsRepo;

}

public TweetsRepository getTweetsRepo() {
    return tweetsRepo;
}

public void setTweetsRepo(TweetsRepository tweetsRepo) {
    this.tweetsRepo = tweetsRepo;
}

public UserRepository getUserRepo() {
    return userRepo;
}

public void setUserRepo(UserRepository userRepo) {
    this.userRepo = userRepo;
}

public List<Tweets> findAll() {

    return tweetsRepo.findAll();
}

@Override
@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public void createTweet(CreateTweet createTweet) {
    Tweets tweet = new Tweets();
    tweet.setTweet(createTweet.getTweet());
    tweet.setUser(createTweet.getUser());
    tweetsRepo.save(tweet);

}

}

创建推文

public class CreateTweet {


@NotNull
@Size(min=1, max=500)
private String tweet;

@NotNull
private User user; 


public String getTweet() {
    return tweet;
}

public void setTweet(String tweet) {
    this.tweet = tweet;
}

public User getUser() {
    return user;
}

public void setUser(User user) {
    this.user = user;
}


}

用户类

 @Entity
@Table(name = "usr", indexes = { @Index(columnList = "email", unique = true) })
// using usr because in may conflict with the name of the class
public class User {

    public static final int EMAIL_MAX = 250;
    public static final int NAME_MAX = 50;

    /*
     * public static enum Role {
     * 
     * UNVERIFIED, BLOCKED, ADMINISTRATOR
     * 
     * }
     */

    // primary key long, needs to be annotated with @Id
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    // add columns
    @Column(nullable = false, length = EMAIL_MAX)
    private String email;

    @Column(nullable = false, length = NAME_MAX)
    private String name;

    // no length, the password will be encrypted to some longer value than the
    // user enters
    @Column(nullable = false)
    private String password;

    @OneToMany(mappedBy="user")
    List<Tweets> tweets;


    public List<Tweets> getTweets() {
        return tweets;
    }

    public void setTweets(List<Tweets> tweets) {
        this.tweets = tweets;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Column(nullable = false)
    private String username;



    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean isEditable() {
        User loggedIn = MyTools.getSessionUser();

        if (loggedIn == null) {
            return false;
        }

        return loggedIn.getId() == id;
    }

    public String getUsername() {

        return username;
    }

}

如何让表单显示在页面上并且用户可以发帖?

How can I get the form to show on the page and users can post?

推荐答案

您的 TweetsController 有错误.您编写它的方式将在每次请求之前调用 @ModelAttribute 构造 方法,并始终创建一个新实例.

Your TweetsController has mistakes. The way you wroted it your @ModelAttribute construct method will be called before every request, always making a new instance.

要解决此问题,您应该使用 @SessionAttributes("tweets") 注释您的控制器.这样,当您的 construct 方法被调用时,它会将模型属性存储在模型中,同时也在会话存储中存储.此外,每当访问 "tweets" 模型属性时,都会在会话中查找它.因此,您的 construct 方法只会在最初被调用.

To fix this, you should annotate your controller with @SessionAttributes("tweets"). This way when your construct method is called it will store the model attribute in the model but also in the session store as well. Also, whenever the "tweets" model attribute is accessed it will be looked up in the session. For this reason your construct method will be called only initially.

@SessionAttributes("tweets") 还将确保模型变量始终存在于请求中,并且您的错误将得到解决.

@SessionAttributes("tweets") will also ensure that the model variable always exists in the request and your error will be resolved.

令人困惑的一点是,有时您将 Tweets 类存储,有时将 CreateTweet 存储为 "tweets" 模型属性.无论如何,以下控制器应该适合您

A confusing bit is that sometimes you store a class Tweets and sometimes CreateTweet as a "tweets" model attribute. Anyways, the following controller should work for you

@SessionAttributes("tweets")
public class TweetsController {

    private TweetsService tweetsService;

    @ModelAttribute("tweets")
    // name for tweet form in home public Tweets
    public Tweets construct() {
        return new Tweets();
    }

    // //----------------------------------------------------------------------
    @RequestMapping(value = "/")
    public String newTweet(Model model) {
        model.addAttribute("tweets", new CreateTweet());
        return "/home";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String tweet(@ModelAttribute("tweets") CreateTweet tweet, BindingResult result,
                        RedirectAttributes redirectAttributes) {
        if (result.hasErrors()) {
            return "redirect:/";
        }
        tweetsService.createTweet(tweet);
        return "redirect:/";
    }

}

这篇关于BindingResult 和 bean 名称“tweets"的普通目标对象都不能用作请求属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆