bean 名称 'tweets' 的 BindingResult 和普通目标对象都不能用作请求属性
Neither BindingResult nor plain target object for bean name 'tweets' available as request attribute
我正在尝试向用户 post 添加一个全局表单。出于某种原因,我得到了这个错误,我已经为此工作了一段时间,它一定是我的控制器的问题,但不确定
在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>
在 TweetsController 中
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
@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;
}
}
用户class
@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;
}
}
如何让表单显示在页面上并且用户可以post?
您的 TweetsController
有错误。你写它的方式你的 @ModelAttribute construct
方法将在每次请求之前被调用,总是创建一个新实例。
要解决此问题,您应该使用 @SessionAttributes("tweets")
注释您的控制器。这样,当您的 construct
方法被调用时,它会将模型属性存储在模型中,但也会存储在会话存储中。此外,无论何时访问 "tweets"
模型属性,都会在会话中查找它。因此,您的 construct
方法只会在最初被调用。
@SessionAttributes("tweets")
还将确保模型变量始终存在于请求中,您的错误将得到解决。
令人困惑的一点是,有时您将 class Tweets
存储,有时 CreateTweet
作为 "tweets"
模型属性存储。无论如何,以下控制器应该适合你
@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:/";
}
}
我正在尝试向用户 post 添加一个全局表单。出于某种原因,我得到了这个错误,我已经为此工作了一段时间,它一定是我的控制器的问题,但不确定
在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>
在 TweetsController 中
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
@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;
}
}
用户class
@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;
}
}
如何让表单显示在页面上并且用户可以post?
您的 TweetsController
有错误。你写它的方式你的 @ModelAttribute construct
方法将在每次请求之前被调用,总是创建一个新实例。
要解决此问题,您应该使用 @SessionAttributes("tweets")
注释您的控制器。这样,当您的 construct
方法被调用时,它会将模型属性存储在模型中,但也会存储在会话存储中。此外,无论何时访问 "tweets"
模型属性,都会在会话中查找它。因此,您的 construct
方法只会在最初被调用。
@SessionAttributes("tweets")
还将确保模型变量始终存在于请求中,您的错误将得到解决。
令人困惑的一点是,有时您将 class Tweets
存储,有时 CreateTweet
作为 "tweets"
模型属性存储。无论如何,以下控制器应该适合你
@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:/";
}
}