gpt4 book ai didi

java - 解释一下 Spring MVC Controller 的行为

转载 作者:太空宇宙 更新时间:2023-11-04 07:56:40 25 4
gpt4 key购买 nike

我有这门课:

@Component
@Scope("session")
@Entity
@Table(name = "users")
public class User {

@Id
@GeneratedValue
@GenericGenerator(name = "incremental", strategy = "increment")
private Long userID;

@Column(nullable = false)
private String username;

@Column(nullable = false)
private String email;

@Column(nullable = false)
private String password;
// getters and setters
}

这个 Controller :

@Controller
@SessionAttributes("user")
@Scope("request")
public class UserCreationWizard {
@Autowired
private User user;

@ModelAttribute("user")
private User createUser() {
return user;
}

@RequestMapping(value = "/new/users/page/", method = RequestMethod.GET)
public String begin(HttpServletRequest request) {
return "wizard";
}

@RequestMapping(value = "/new/users/page/{page}", method = RequestMethod.POST)
public String step(@ModelAttribute("user") User user,
@RequestParam("username") String username,
@RequestParam("email") String password,
@PathVariable() Integer page) {

return "wizard" + page;
}

@RequestMapping(value = "/new/users/page/end", params = "submit", method = RequestMethod.POST)
public String end(@RequestParam("password") String password) {

user.setPassword(password);
user.setActive(true);
user.setLastLoggedIn(Calendar.getInstance());

Session s = HibernateUtils.getSessionFactory().openSession();
Transaction t = s.beginTransaction();
try {
s.persist(user);
s.flush();
t.commit();

s.close();
} catch (HibernateException e) {
t.rollback();
}
return "wizard";
}
}

begin() 只是加载用户创建向导中的第一个 View (一个 jsp)。它具有用户名电子邮件的输入字段。在 View 中,您进行 POST 表单提交,这会触发 step()。在第二个 View (wizard+page.jsp) 中,您有一个 password 字段和一个触发 end() 的提交输入。

  1. 在 Debug模式下,我注意到在 step() 中,我将 User 作为ModelAttribute,我不需要设置其用户名字段和密码。它们是自动从 RequestParams 中获取的属性。然而,在 end() 中,我没有 ModelAttribute,我必须手动设置密码。 Spring 如何处理这个问题?
  2. 此外,如果我取出 Controller 中的 createUser() 方法,应用程序失败,表示找不到 session 属性“用户”。该方法如何作为方法链接到 MethodAttribute参数?
  3. 最后,如果我取出@SessionAttributes,应用程序不会失败,但我感觉出了什么问题。 User 用户现在对所有 httprequest 来说都是全局的吗?

我的一般问题是:Spring beans 是否映射到它们的名称?例如。这里我将“user”作为用户,在 session 中将“user”作为请求参数,将“password”作为 User 成员变量。

最佳答案

好的,有很多问题。让我们看看,所有引用都是针对当前 Spring MVC 版本的文档。

1) 您在 user 属性中看到的行为在“Using @ModelAttribute on a method argument”部分中进行了解释

An @ModelAttribute on a method argument indicates the argument should be retrieved from the model. If not present in the model, the argument should be instantiated first and then added to the model. Once present in the model, the argument's fields should be populated from all request parameters that have matching names. This is known as data binding in Spring MVC, a very useful mechanism that saves you from having to parse each form field individually.

Spring 是如何做到这一点的?好吧,源代码是最终的答案,但猜测并不难:Spring 知道参数是 User 的实例,并且通过反射它可以读取该类的方法,特别是其 setter。在本例中,它找到 setUsername()setEmail(),并且这些方法的参数是 String,因此它与请求中的参数兼容。

(顺便说一句:@RequestParam(“email”)字符串密码可能是一个错误。至少令人困惑)

2) 方法 createUser() 前面有注释 @ModelAttribute("user")。 “Using @ModelAttribute on a method”部分涵盖了这一点

An @ModelAttribute on a method indicates the purpose of that method is to add one or more model attributes.

因此,此方法会在模型上放置一个与名称 “user” 关联的对象,然后可供其他方法(例如 step())用作参数。请注意,注释控制模型中对象使用的标识符。如果将代码更改为

@ModelAttribute("strangeWeirdIdentifier")
private User createUser() { return user; }

应用程序将崩溃。但如果您将 step() 签名更改为

,它将再次起作用
public String step(@ModelAttribute("strangeWeirdIdentifier") User user,
@RequestParam("username") String username,
@RequestParam("email") String password,
@PathVariable() Integer page) {

3) 1) 和 2) 中描述的过程在请求期间将对象存储在模型中。使用类注释@SessionAttributes("user"),您可以将对象添加到当前Session 或等效对象中,从而延长该对象的生命周期。例如,您可以在其他 Controller 中使用该对象,就像 step() 方法一样。

最后要说清楚

  • 问题 2 中看到的注释出现在问题 1 中看到的用法之前。
  • 可能不需要问题 3 中的注释
  • Spring 不会将 bean 映射到 Java 代码中的名称,而是映射到注释中使用的名称。为了清楚起见,重复与示例中相同的名称并不罕见。

希望这比官方文档更清晰,因为官方文档通常太简短了,我会给你的。

关于java - 解释一下 Spring MVC Controller 的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13520837/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com